Set length of CylinderGeometry in Three.js - javascript

The following code creates an object with proportional lengths.
My question is:
How can I set the length of one of the sides? (indicated with the red line)?
Edit:
I'm also looking into rectShape but I'm not sure if I can make this into a 3d shape.
var shape = THREE.SceneUtils.createMultiMaterialObject(
new THREE.CylinderGeometry( 30, 30, 30, 7, 1 ),
multiMaterial );
shape.position.set(0, 25, 0);
scene.add( shape );
Result:
To create an image like this (top view):

Related

Three.js - Strange lines on custom mesh

I'm trying to make a custom mesh in order to have a lot of customizable planes in the scene.
Here is some code:
geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertexPositions, 3 ).setDynamic( true ) );
geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ).setDynamic( true ) );
geometry.addAttribute( 'opacity', new THREE.BufferAttribute( opacity, 1 ).setDynamic( true ) );
// Initialize material
var material = new THREE.ShaderMaterial( { vertexColors: THREE.VertexColors, transparent: true, vertexShader: vertexShader, fragmentShader: fragmentShader } );
// Create something like a Wireframe of the planes
var Pgeometry = new THREE.BufferGeometry();
Pgeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( ApointsPositions ), 3 ).setDynamic( true ) );
var points = new THREE.LineSegments( Pgeometry, new THREE.PointsMaterial( { color: 0x353535 } ) );
scene.add( points );
// Create planes and add to scene
planeMeshes = new THREE.Mesh( geometry, material );
planeMeshes.setDrawMode( THREE.TriangleStripDrawMode );
scene.add( planeMeshes );
My custom material is working fine and let me to use opacity on every vertex. Every plane is created and everything works fine.
The problem is that, when I render the scene, there are some strange lines on every planes row, here's a full working Codepen: Codepen link
Do you see those diagonal lines there? Are you able to tell me what's happening? I didn't find their origin.
Thank you in advance!
The reason you're seeing diagonals is because you're using THREE.TriangleStripDrawMode, so the rightmost triangles share vertices with the leftmost triangles of the next row. You're seeing a really stretched out triangle cut across.
To solve this, get rid of the line where you're assigning TriangleStripDrawMode, which will go back to the default of three vertices per triangle (no sharing of vertices).
Problem 2:
The first triangle on each iteration is being drawn in a clockwise order, but the second triangle on each iteration is being drawn in a counter-clockwise order, so you will not see the second one unless you change the vertex order to be clockwise.
Here's how you have it in your Codepen:
// Second tri is drawn counter-clockwise
AvertexPositions.push( x, y + 60, 0 ); //
AvertexPositions.push( x + 80, y + 60, 0 ); // Second triangle of a plane
AvertexPositions.push( x + 80, y, 0 );
This is how it should be:
// Now, it is clockwise, matching first tri
AvertexPositions.push( x, y + 60, 0 ); //
AvertexPositions.push( x + 80, y, 0 ); //
AvertexPositions.push( x + 80, y + 60, 0 ); // Second triangle of a plane
It is important to draw all your triangles in the same winding order. Otherwise, some will be facing forward, and some will be facing backward. You can choose which side gets rendered, or render both sides with Materials.Side

Label on AxisHelper withTextGeometry and rotation issue

I have a main scene with a sphere and another subwindow (in right bottom) where I have drawn the (x,y,z) axis of main scene.
In this subwindow, I would like to draw the labels "X" "Y" and "Z" on each axis (more precisely located on the end of each AxisHelper). I know how to use TextGeometry but the issue is that I can't get to make rotate these labels in order to make them appear always in face on the user.
You can see the problem on the [following link][1] : label "X" is fixed relatively to axis and is rotating with camera, so it is not always in face of user.
From these two links link1 and link2, I tried to add (in my example, I tried with only "X" label) :
function addLabelAxes() {
// Axes label
var loader = new THREE.FontLoader();
loader.load( 'js/helvetiker_regular.typeface.js', function ( font ) {
var textGeo1 = new THREE.TextGeometry( 'X', {
font: font,
size: 5,
height: 0.1,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelEnabled: true,
} );
var color = new THREE.Color();
color.setRGB(255, 255, 255);
textMaterial = new THREE.MeshBasicMaterial({ color: color });
var meshText1 = new THREE.Mesh(textGeo1, textMaterial);
// Position of axes extremities
var positionEndAxes = axes2.geometry.attributes.position;
var label1X = positionEndAxes.getX(0);
meshText1.position.x = label1X + axisLength;
meshText1.position.y = 0;
meshText1.position.z = 0;
// Rotation of "X" label
//meshText1.rotation = zoomCamera.rotation;
meshText1.lookAt(zoomCamera.position);
// Add meshText to zoomScene
zoomScene.add(meshText1);
});
}
zoomCamera represents a PerspectiveCamera which is the camera of subwindow (i.e zoomScene) ;I add TextGeometry to zoomScene by doing :
zoomScene.add(meshText1);
What might be wrong in my code ? I wonder if I can make rotate the "X" label on itself, i.e the "X" label is rotating like axis but a self (local) orientation is applied as a function of rotation theta angle, so the label is always kept in face of user during camera rotation ?
You are probably looking for THREE.SPRITE. From the docs:
Object3D -> Sprite: A sprite is a plane in an 3d scene which faces always towards the camera.
Here's a simple example of how to use it:
var map = new THREE.TextureLoader().load( "sprite.png" );
var material = new THREE.SpriteMaterial( { map: map, color: 0xffffff, fog: true } );
var sprite = new THREE.Sprite( material );
scene.add( sprite );
Here's a working example of a similar scenario (3 scaled sprites with different positioning). You can find the code on github.

Three.js: Rotate Cylinder into Vector3 direction

I've already searched, but didn't find anything that helps:
I got an vector and a CylinderGeometry Mesh. I want to acchieve, that the cylinder is facing the point where the vector is showing. As input I got a position (c) and a direction (m) (like a line equation: y = mx + c):
function draw (m,c, _color) {
//... create the geometry and mesh
// set the position
line.position.x = c.x;
line.position.y = c.y;
line.position.z = c.z;
// i've tried something like this:
line.lookAt(c.add(m));
//.. and add to scene
}
But it looks like the direction is the direct opposite of what I want to acchieve.
I've also tried stuff like translation:
geometry.applyMatrix( new THREE.Matrix4().makeTranslation(0, length/2, 0));
and tried to get the rotation manually like line.rotation.x = direction.angleTo(vec3(1,0,0))* 180 / Math.PI;. But none of them worked like I needed.
This works for me:
// Make the geometry (of "distance" length)
var geometry = new THREE.CylinderGeometry( 0.6, 0.6, distance, 8, 1, true );
// shift it so one end rests on the origin
geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, distance / 2, 0 ) );
// rotate it the right way for lookAt to work
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( THREE.Math.degToRad( 90 ) ) );
// Make a mesh with the geometry
var mesh = new THREE.Mesh( geometry, material );
// Position it where we want
mesh.position.copy( from.sceneObject.position );
// And make it point to where we want
mesh.lookAt( to.sceneObject.position );

Three.js multiple spotlight performance

I'm doing some racing game on three.js and I stuck with the following problem...
I'm having 2 cars, so we need to render 4 spotlights (minimum) for rear car lights and front car lights for each car...
Also we need some lights on the road...
So i'm having this code:
//front car1 light
var SpotLight = new THREE.SpotLight( 0xffffff, 5, 300, Math.PI/2, 1 );
SpotLight.position.set( 50, 10, 700 );
SpotLight.target.position.set(50, 0, 800);
SpotLight.castShadow = true;
SpotLight.shadowCameraVisible = false;
SpotLight.shadowDarkness = 0.5;
scene.add(SpotLight);
//front car2 light
var SpotLight = new THREE.SpotLight( 0xffffff, 5, 300, -Math.PI/2, 1 );
SpotLight.position.set( -50, 10, 40 );
SpotLight.target.position.set(-50, 0, 100);
SpotLight.castShadow = true;
SpotLight.shadowCameraVisible = false;
SpotLight.shadowDarkness = 0.5;
scene.add(SpotLight);
//rear car1 light
var SpotLight = new THREE.SpotLight( 0xff0000, 2, 200, Math.PI/2, 2 );
SpotLight.position.set( 50, 20, 660 );
SpotLight.target.position.set(50, 0, 600);
SpotLight.castShadow = true;
SpotLight.shadowCameraVisible = false;
SpotLight.shadowDarkness = 0.5;
scene.add(SpotLight);
//rear car2 light
var SpotLight = new THREE.SpotLight( 0xff0000, 2, 100, Math.PI/2, 1 );
SpotLight.position.set( -50, 20, -35 );
SpotLight.target.position.set(-50, 0, -100);
SpotLight.castShadow = true;
SpotLight.shadowCameraVisible = false;
SpotLight.shadowDarkness = 0.5;
scene.add(SpotLight);
//some road light
var SpotLight = new THREE.SpotLight( 0x404040, 3, 500, Math.PI/2, 2 );
SpotLight.position.set( 0, 300, 0 );
SpotLight.target.position.set(0, 0, 0);
SpotLight.castShadow = true;
SpotLight.shadowCameraVisible = false;
SpotLight.shadowDarkness = 0.5;
scene.add(SpotLight);
Nothing special.. but performance dropped to 20-30 FPS and it's a little bit laggy :-1:
And if I add some lights in the future, the performance will be lifted even further ...
Has anyone encountered similar problems already? How to deal with this? Or maybe I'm doing something wrong?
Lights are a very consuming when doing realtime rendering. You'll need to find the cheapest approach that mimics the result you're after.
For instance, you could have a textured plane in front of your car with a texture that looks like the if there were spotlights aiming to the floor. It won't be right, but it will give the impression that is right and you will be saving 4 spotlights and your game will run at 60fps.
Shadows are most likely the culprit in this case - under the hood, the scene needs to be rendered from the point of view of each shadow-casting light. If possible, save them for the most important ones, disable shadows on other lights.
For many lights, you could try to use WebGLDeferredRenderer, it can handle multiple lights much better than the default renderer. It's experimental work in progress though, so you are likely to run into other problems. Also I'm not sure if it helps shadow mapping performance.
I had exactly same issue, beside mrdoob's & yaku's suggestions, which were really helpful, another approach is reducing number of segments & polygons in your geometries.
i.e If you have a simple cylinder in your scene, you can reduce number of segments by assigning heightSegments & radialSegments in initialization time:
As an very simple example, avoid doing something like this if you need to create a simple cylinder:
sampleCylinderGeo = new THREE.CylinderGeometry(2, 2, 5, 16, 32);
instead try:
sampleCylinderGeo = new THREE.CylinderGeometry(2, 2, 5, 8, 1);
Of course if you want smoother cylinder you can increase radial segments from 8 to something like 16 or more according to your needs, but for heightSegments its simply useless to have more than 1 segments in a simple cylinder.
So just adjust number of segments according to your needs so you will save lots of unnecessary segments and achieve a lot more FPS when working with lights, specially when you have lots of geometries in you scene.

cube texture is reversed in one of the cube faces

I use an image for the cube texture, the image is shown correctly in 3 of 4 faces, and looks reversed for the 4th face.
My relevant code is the following:
//dom
var container2=document.getElementById('share');
//renderer
var renderer2 = new THREE.CanvasRenderer();
renderer2.setSize(100,100);
container2.appendChild(renderer2.domElement);
//Scene
var scene2 = new THREE.Scene();
//Camera
var camera2 = new THREE.PerspectiveCamera(50,200/200,1,1000);
camera2.up=camera.up;
//
camera2.position.z = 90;
//
scene2.add(camera2);
//Axes
var axes2= new THREE.AxisHelper();
//Add texture for the cube
//Use image as texture
var img2 = new THREE.MeshBasicMaterial({ //CHANGED to MeshBasicMaterial
map:THREE.ImageUtils.loadTexture('img/fb.jpg')
});
img2.map.needsUpdate = true;
//
var cube = new THREE.Mesh(new THREE.CubeGeometry(40,40,40),img2);
scene2.add(cube);
The image size is 600*600 px. Any suggestion is appreciated, thanx in advance.
First off, it should be pointed out for others that you are trying to develop using the javascript library "three.js". The documentation can be found here: http://mrdoob.github.com/three.js/docs
The crux of the issue is that textures get mapped to Mesh objects based upon UV coordinates stored in the Geometry objects. The THREE.CubeGeometry object has its UV coordinates stored in the array faceVertexUvs.
It contains the following arrays of UV coordinate for the 4 vertices in each of the 6 faces:
{{0,1}, {0,0}, {1,0}, {1,1}}, // Right Face (Top of texture Points "Up")
{{0,1}, {0,0}, {1,0}, {1,1}}, // Left Face (Top of texture Points "Up")
{{0,1}, {0,0}, {1,0}, {1,1}}, // Top Face (Top of texture Points "Backward")
{{0,1}, {0,0}, {1,0}, {1,1}}, // Bottom Face (Top of texture Points "Forward")
{{0,1}, {0,0}, {1,0}, {1,1}}, // Front Face (Top of texture Points "Up")
{{0,1}, {0,0}, {1,0}, {1,1}} // Back Face (Top of texture Points "Up") **Culprit**
It is mapping UV coordinate to each of the faces which make up the cube, which are:
{0, 2, 3, 1}, // Right Face (Counter-Clockwise Order Starting RTF)
{4, 6, 7, 5}, // Left Face (Counter-Clockwise Order Starting LTB)
{4, 5, 0, 1}, // Top Face (Counter-Clockwise Order Starting LTB)
{7, 6, 3, 2}, // Bottom Face (Counter-Clockwise Order Starting LBF)
{5, 7, 2, 0}, // Front Face (Counter-Clockwise Order Starting LTF)
{1, 3, 6, 4} // Back Face (Counter-Clockwise Order Starting RTB)
The above numbers are indexes into the array of vertices, which for the THREE.CubeGeometry are stored in vertices, there are 8 of them:
{20, 20, 20}, // Right-Top-Front Vertex
{20, 20, -20}, // Right-Top-Back Vertex
{20, -20, 20}, // Right-Bottom-Front Vertex
{20, -20, -20}, // Right-Bottom-Back Vertex
{-20, 20, -20}, // Left-Top-Back Vertex
{-20, 20, 20}, // Left-Top-Front Vertex
{-20, -20, -20}, // Left-Bottom-Back Vertex
{-20, -20, 20} // Left-Bottom-Front Vertex
NOTE: All relative directions above are assuming the camera is placed along the positive z axis looking towards a cube centered on the origin.
So the real culprit is the back face which has the texture's top point upwards. In this case you want the texture's top to point downwards on the back face, so when the cube if flipped upside down due to the rotations and viewed the way you have it, the image appears as you expect. It needs to change as follows:
{{1,0}, {1,1}, {0,1}, {0,0}} // FIXED: Back Face (Top of texture Points "Down")
This change can be made in the code to change the coordinates to get the display you would like:
var cubeGeometry = new THREE.CubeGeometry(40, 40, 40);
cubeGeometry.faceVertexUvs[0][5] = [new THREE.UV(1, 0), new THREE.UV(1, 1), new THREE.UV(0, 1), new THREE.UV(0, 0)];
var cube = new THREE.Mesh(cubeGeometry, img2);
For further reading, I recommend the following link on Texture Mapping with UV coordinates http://www.rozengain.com/blog/2007/08/26/uv-coordinate-basics/.

Categories

Resources