Three.js texture for mesh with custom geometry - javascript

I am trying to create a house geometry and attach different textures to the faces of the geometry. I am using r55. The problem is that faces with material created from a texture just don't appear. Faces with a simple color material do however appear. If I replace the material generated from my roofTexture with a simple color material, the faces using that material do appear correctly as well.
Here is the relevant part of my code:
var geom = new THREE.Geometry();
// Load the roof texture
var roofTexture = new THREE.ImageUtils.loadTexture('gfx/textures/roof.jpg');
// Let the roof texture repeat itself
roofTexture.wrapS = roofTexture.wrapT = THREE.RepeatWrapping;
roofTexture.repeat.set(10, 10);
// Materials
var materialArray = [];
materialArray.push(new THREE.MeshLambertMaterial({color: 0xD3E3F0 }));
materialArray.push(new THREE.MeshLambertMaterial({map: roofTexture}));
// Base edges
var edge0 = new THREE.Vector2(obj.ridgeLength/2, -obj.buildingDepth/2);
var edge1 = new THREE.Vector2(obj.ridgeLength/2, obj.buildingDepth/2);
var edge2 = new THREE.Vector2(-obj.ridgeLength/2, obj.buildingDepth/2);
var edge3 = new THREE.Vector2(-obj.ridgeLength/2, -obj.buildingDepth/2);
// Floor
geom.vertices.push(new THREE.Vector3(edge0.x, -1, edge0.y));
geom.vertices.push(new THREE.Vector3(edge1.x, -1, edge1.y));
geom.vertices.push(new THREE.Vector3(edge2.x, -1, edge2.y));
geom.vertices.push(new THREE.Vector3(edge3.x, -1, edge3.y));
// Eave
geom.vertices.push(new THREE.Vector3(edge0.x, obj.eaveHeight, edge0.y));
geom.vertices.push(new THREE.Vector3(edge1.x, obj.eaveHeight, edge1.y));
geom.vertices.push(new THREE.Vector3(edge2.x, obj.eaveHeight, edge2.y));
geom.vertices.push(new THREE.Vector3(edge3.x, obj.eaveHeight, edge3.y));
// Ridge
geom.vertices.push(new THREE.Vector3(obj.ridgeLength/2, obj.ridgeHeight, 0));
geom.vertices.push(new THREE.Vector3(-obj.ridgeLength/2, obj.ridgeHeight, 0));
// Ground
geom.faces.push( new THREE.Face4(0, 0, 0, 0) );
// Front
geom.faces.push( new THREE.Face4(0, 3, 7, 4) );
// Left side
geom.faces.push( new THREE.Face4(0, 4, 5, 1) );
// Back
geom.faces.push( new THREE.Face4(1, 5, 6, 2) );
// Right side
geom.faces.push( new THREE.Face4(2, 6, 7, 3) );
// Left triangle
geom.faces.push( new THREE.Face3(4, 8, 5));
// Right triangle
geom.faces.push( new THREE.Face3(6, 9, 7));
// Front roof
geom.faces.push( new THREE.Face4(7, 9, 8, 4) );
// Back roof
geom.faces.push( new THREE.Face4(5, 8, 9, 6) );
// Assign materials to the faces
geom.faces[0].materialIndex = 0;
geom.faces[1].materialIndex = 0;
geom.faces[2].materialIndex = 0;
geom.faces[3].materialIndex = 0;
geom.faces[4].materialIndex = 0;
geom.faces[5].materialIndex = 0;
geom.faces[6].materialIndex = 0;
geom.faces[7].materialIndex = 1;
geom.faces[8].materialIndex = 1;
geom.computeFaceNormals();
obj.house = new THREE.Mesh( geom, new THREE.MeshFaceMaterial(materialArray) );
obj.house.doubleSided = true;
obj.house.castShadow = true;
obj.sun.shadowDarkness = 1.0;
obj.scene.add(obj.house);
What am I doing wrong?

You are missing UV coordinates on your geometry. UV coords go from 0 to 1 so since you are creating the geometry yourself you can assign at your lower left corner UVs (0.0, 0.0) on your lower right (1.0, 0.0), top left (0.0, 1.0) and top right (1.0, 1.0). You can look at the PlaneGeometry.js file to see how UVs are assigned.

Related

THREE JS geometry verticles set by known angle

I want to draw a triangle and i know only all angles (Alpha,Beta,Gamma) and all side length (10).
For drawing a triangle i need to set 3 vertices to geometry with absolute Vector3 values.
Is in THREE.js any integrated tool or practice fit for this?
geometry.vertices.push(
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( -10, -10, 0 ),
new THREE.Vector3( 10, -10, 0 ),
);
geometry.faces.push( new THREE.Face3( 0, 1, 2 ));
var material = new THREE.MeshBasicMaterial( { color: 0xffff00, side: THREE.DoubleSide } );
var mesh = new THREE.Mesh( geometry, material );
Only THREE method i can imagine is to create a 2 vector geometry with vector distance of side lengths, use matrix translation to set rotation pivot on vector[0] and change its position and rotation, each time set globalToWorld() for its vector[1]. But I think this is not a good solution.
I used this:
var length = 10;
var aplpha = 0.3;//rad
var beta= 1;//rad
geometry.vertices.push(
new THREE.Vector3(),
new THREE.Vector3(length ,0,0).applyAxisAngle(new THREE.Vector3(0,1,0),aplpha ),
new THREE.Vector3(length ,0,0).applyAxisAngle(new THREE.Vector3(0,1,0),beta ),
new THREE.Vector3(),
);
https://threejs.org/docs/#api/en/math/Vector3
THREE.JS r 96

MeshNormalMaterial not working on a three.js custom geometry: the geometry renders as black

I am trying to construct a cube manually using three.js by declaring its vectors and faces; I am able to do it using the code below, however, the material does not seem to be working as expected, instead the cube is rendering in a solid black color.
var geom = new THREE.Geometry();
var v1 = new THREE.Vector3( -1, 1, 0.1 ),
v2 = new THREE.Vector3( 1, 1, 0.1 ),
v3 = new THREE.Vector3( 1, -1, 0.1 ),
v4 = new THREE.Vector3( -1, -1, 0.1 ),
v5 = new THREE.Vector3( -1, 1, 2 ),
v6 = new THREE.Vector3( 1, 1, 2 ),
v7 = new THREE.Vector3( 1, -1, 2 ),
v8 = new THREE.Vector3( -1, -1, 2 );
geom.vertices.push(v1,v2,v3,v4,v5,v6,v7,v8);
geom.faces.push(
new THREE.Face3(0,1,3),
new THREE.Face3(1,2,3),
new THREE.Face3(4,5,7),
new THREE.Face3(5,6,7),
new THREE.Face3(1,4,5),
new THREE.Face3(0,1,4),
new THREE.Face3(2,3,7),
new THREE.Face3(2,6,7),
new THREE.Face3(0,3,7),
new THREE.Face3(0,4,7),
new THREE.Face3(1,2,5),
new THREE.Face3(2,5,6)
);
var mat = new THREE.MeshNormalMaterial();
mat.side = THREE.DoubleSide;
var cube = new THREE.Mesh( geom, mat);
scene.add(cube);
If I render the cube normally, using the code that follows, the cube renders as expected.
cube = new THREE.Mesh(new THREE.CubeGeometry(2, 2, 2), new THREE.MeshNormalMaterial());
scene.add(cube);
You haven't specified vertex normals. For something quick, compute face normals, like so:
geom.computeFaceNormals();
but you should learn how to set vertex normals in your custom geometry.
Also, face "winding order" should be counter-clockwise. You are not consistently doing that.
If you define faces correctly, you can remove side = THREE.DoubleSide.
three.js r.90

Updating DecalGeometry vertices, UVs,

I am currently playing with ThreeJS decals. I have been able to put a beautiful stain on my sphere.
Here is the piece of code I use to "apply" the decal on my sphere. (I have some custom classes, but don't worry about this.
// Create sphere
var mainMesh = new THREE.Mesh(
new THREE.SphereGeometry(7, 16, 16),
new THREE.MeshBasicMaterial({ color: 0x00a1fd })
);
// Declare decal material
var decalMaterial = new THREE.MeshPhongMaterial({
color : 0xff0000,
specular : 0x444444,
map : TextureLoader.instance.getTexture('http://threejs.org/examples/textures/decal/decal-diffuse.png'),
normalMap : TextureLoader.instance.getTexture('http://threejs.org/examples/textures/decal/decal-normal.jpg'),
normalScale : new THREE.Vector2( 1, 1 ),
shininess : 30,
transparent : true,
depthTest : true,
depthWrite : false,
polygonOffset : true,
polygonOffsetFactor : -4,
wireframe : false
});
// Create decal itself
var decal = new THREE.Mesh(
new THREE.DecalGeometry(
mainMesh,
new THREE.Vector3(0, 2.5, 3),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(8, 8, 8),
new THREE.Vector3(1, 1, 1)
),
decalMaterial.clone()
);
// Add mesh + decal + helpers
scene.add(
mainMesh,
new THREE.HemisphereLight(0xffffff, 0, 1),
decal,
new THREE.WireframeHelper(decal, 0xffff00)
);
decal.add(new THREE.BoxHelper(decal, 0xffff00));
Now, I woud like to move this stain on my sphere, and thus, update the geometry of my decal.
Unfortunately, when I call decal.geometry.computeDecal(), the mesh of the decal does not update. I can't find any solution about this.
function moveDecal()
{
decal.translateX(1);
decal.geometry.computeDecal();
};
According to the DecalGeometry class, the function computeDecal already set to true various members required to update vertices, colors, UVs, ....
this.computeDecal = function() {
// [...]
this.verticesNeedUpdate = true;
this.elementsNeedUpdate = true;
this.morphTargetsNeedUpdate = true;
this.uvsNeedUpdate = true;
this.normalsNeedUpdate = true;
this.colorsNeedUpdate = true;
};
Thank you for your help ! :D
PS : ThreeJS r80
You are trying to update vertices of your geometry.
You can change the value of a vertex componnent,
geometry.vertices[ 0 ].x += 1;
but you can't add new veritices
geometry.vertices.push( new THREE.Vector3( x, y, z ) ); // not allowed
or assign a new vertex array
geometry.vertices = new_array; // not allowed
after the geometry has been rendered at least once.
Similalry, for other attributes, such as UVs.
For more info, see this answer: verticesNeedUpdate in Three.js.
three.js r.80

How to create a custom mesh in Babylon.js?

I'm using the babylonjs 3D WebGL library.
It's great library, but I can't find the same, which exists in THREE.JS library.
For example, I have 2D polygons in database, I'm fetching the polygon data from it and then create a custom mesh and extruding it.
With the THREE.JS, there isn't any problem, I can add to some array:
...
points.push( new THREE.Vector2( part.x, -part.y ) );
...
var shape = new THREE.Shape( points );
var extrusion = {
amount: building.height,
bevelEnabled: false
};
var geometry = new THREE.ExtrudeGeometry( shape, extrusion );
var mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({
ambient: 0xbbbbb,
color: 0xff0000
});
...
scene.add( mesh );
It's very simple. How to do the same, I couldn't find.
I've found only some information here:
http://www.html5gamedevs.com/topic/4530-create-a-mesh-from-a-list-of-vertices-and-faces/
http://blogs.msdn.com/b/eternalcoding/archive/2013/06/27/babylon-js-a-complete-javascript-framework-for-building-3d-games-with-html-5-and-webgl.aspx
With such an example (from msdn by Ctrl + F -> You can also create a mesh from a list of vertices and faces):
var plane = new BABYLON.Mesh(name, scene);
var indices = [];
var positions = [];
var normals = [];
var uvs = [];
// Vertices
var halfSize = size / 2.0;
positions.push(-halfSize, -halfSize, 0);
normals.push(0, 0, -1.0);
uvs.push(0.0, 0.0);
positions.push(halfSize, -halfSize, 0);
normals.push(0, 0, -1.0);
uvs.push(1.0, 0.0);
positions.push(halfSize, halfSize, 0);
normals.push(0, 0, -1.0);
uvs.push(1.0, 1.0);
positions.push(-halfSize, halfSize, 0);
normals.push(0, 0, -1.0);
uvs.push(0.0, 1.0);
// Indices
indices.push(0);
indices.push(1);
indices.push(2);
indices.push(0);
indices.push(2);
indices.push(3);
plane.setVerticesData(positions, BABYLON.VertexBuffer.PositionKind);
plane.setVerticesData(normals, BABYLON.VertexBuffer.NormalKind);
plane.setVerticesData(uvs, BABYLON.VertexBuffer.UVKind);
plane.setIndices(indices);
return plane;
But's it's rather not the same as with the THREE.JS. For example I need to count index buffer manually where in THREE.JS I don't need it, also it's a sample with plane only and I didn't find any info about extruding exactly.
So... Maybe, there are some easy ways in BabylonJS?
There is no support for extrusion right now but this could be a great feature to add :) I will definitely add it to our roadmap. If you would like to discuss the issue further please ask on the babylon.js forum.
EDIT:
Have ability to create custom shapes now.
http://doc.babylonjs.com/tutorials/parametric_shapes#extrusion
Update 2019 PolygonMeshBuilder allows to create custom mesh from the collection of vertexes
Please note that the PolygonMeshBuilder uses Earcut, so, in non
playground projects, you will have to add a reference to their cdn or
download their npm package
Add Earcut as dependency in your index HTML
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
Now you can use Pramaetric shapes to extrude polygon and punch holes.
//Polygon shape in XoZ plane
var shape = [
new BABYLON.Vector3(4, 0, -4),
new BABYLON.Vector3(2, 0, 0),
new BABYLON.Vector3(5, 0, 2),
new BABYLON.Vector3(1, 0, 2),
new BABYLON.Vector3(-5, 0, 5),
new BABYLON.Vector3(-3, 0, 1),
new BABYLON.Vector3(-4, 0, -4),
new BABYLON.Vector3(-2, 0, -3),
new BABYLON.Vector3(2, 0, -3)
];
//Holes in XoZ plane
var holes = [];
holes[0] = [ new BABYLON.Vector3(1, 0, -1),
new BABYLON.Vector3(1.5, 0, 0),
new BABYLON.Vector3(1.4, 0, 1),
new BABYLON.Vector3(0.5, 0, 1.5)
];
holes[1] = [ new BABYLON.Vector3(0, 0, -2),
new BABYLON.Vector3(0.5, 0, -1),
new BABYLON.Vector3(0.4, 0, 0),
new BABYLON.Vector3(-1.5, 0, 0.5)
];
var polygon = BABYLON.MeshBuilder.ExtrudePolygon("polygon",{
shape:shape,
holes:holes,
depth: 2,
sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene);
Result:
See this playground for reference:
https://playground.babylonjs.com/#4G18GY#7
Advance usage
building Staircases:
https://www.babylonjs-playground.com/#RNCYVM#74

How do I rotate an object to another object's up/normal/facing vectors

If I have a custom plane geometry like so:
planeGeometry.vertices[0] = new THREE.Vector3(0, 10, 0);
planeGeometry.vertices[1] = new THREE.Vector3(10, 10, 0);
planeGeometry.vertices[2] = new THREE.Vector3(0, 0, 0);
planeGeometry.vertices[3] = new THREE.Vector3(10, 0, 0);
// faceUVs, mesh etc omitted
var right = planeGeometry.vertices[0].clone().sub(planeGeometry.vertices[1]);
var up = planeGeometry.vertices[1].clone().sub(planeGeometry.vertices[3]);
var up = up.normalize();
var normal = up.clone().cross(right).normalize();
How can I rotate another Object3D (CSS3DObject in my case) to have this facing normal and up vector? Can I create a quaternion or rotation matrix to do this?

Categories

Resources