Threejs PlaneBufferGeometry: color attribute does not show - three.js

When i create a PBG with:
var geometry = new THREE.PlaneBufferGeometry(gs,gs, size - 1, size - 1);
geometry.rotateX(-Math.PI / 2);
var vertices = geometry.attributes.position.array;
for (var i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
vertices[j + 1] = data.map[0][i];
}
I dont have a color property:
Don't know if the warnings have something to do or i'm missing something. For what i can see in the code, PlaneBufferGeometry extends from BufferAttribute and should have color.
Tips?
Thanks!
Edit: Material:
var material = new THREE.MeshPhongMaterial({
color: 0xaaaaff,
vertexColors: THREE.FaceColors,
shading: THREE.FlatShading,
side: THREE.DoubleSide
});

Related

How to reduce load on CPU/GPU while producing multiple squares in ThreeJs?

function createPlane() {
for (let i = -77; i < 78; i++) {
for (let j = -38; j < 39; j++) {
const geometry = new THREE.BoxGeometry(1, 1, 0.1);
const material = new THREE.MeshBasicMaterial({
color: 0xffff00,
});
const plane = new THREE.Mesh(geometry, material);
plane.position.set(i, j, 0);
scene.add(plane);
}
}
}
createPlane();
so I have like 12k boxes to draw on my screen which comprises of a plane all together, but doing so takes like a second or 2 to load and further process I have to do on these boxes(like change their color on touch) lags and some boxes do not change color due to that lag.
How can I fix that?
I suggest you reuse the geometry and material which should noticeably decrase the execution time of createPlane(). Try it like so:
function createPlane() {
const geometry = new THREE.BoxGeometry(1, 1, 0.1);
const material = new THREE.MeshBasicMaterial({
color: 0xffff00,
});
for (let i = -77; i < 78; i++) {
for (let j = -38; j < 39; j++) {
const plane = new THREE.Mesh(geometry, material);
plane.position.set(i, j, 0);
scene.add(plane);
}
}
}
createPlane();

Can not get uniform speed when camera move along the curve

I want to make camera move along the curve,it works, but when pass the turning corner,camera speed changed,looks like slowly.
curve = new THREE.CatmullRomCurve3(vectors);
curve.type = 'catmullrom';
curve.tension = 0.2;
this.MKY.Camera.current = this.roamCamera;
cameraWrap.add(this.roamCamera);
this.MKY.scene.add(cameraWrap);
this.MKY.update.push(roam);
function roam() {
if(!isAutoRoam){return}
if(progress>1 || progress==1){
progress = 0;
return
}
progress += 0.0005;
var position = curve.getPointAt(progress);
position.y += 1.5;
var tangent = curve.getTangentAt(progress);
cameraWrap.position.copy(position);
cameraWrap.lookAt(position.sub(tangent));
};
getPointAt returns a vector for point at a relative position in curve according to arc length. I think if progress not change ,i will get the average speed,but it is not. I do not understend.
There is the approach, using .getUtoTmapping() method of THREE.Curve() (in the example, it's THREE.CatmullRomCurve3).
The documentation says:
.getUtoTmapping ( u, distance )
Given u in the range ( 0 .. 1 ), returns t also in the range ( 0 .. 1 ). u and t can then be used to give you points which are equidistant from the ends of the curve, using .getPoint.
So, when you provide the second parameter in this method, then, if I got it correctly from the source code, it ignores the first parameter, thus you can find the point on your curve by the distance on it.
In the given picture:
small yellow points - points, taken with .getPoints() method;
big maroon points - points, whose distance between each other along the curve is 1 unit;
The code for the maroon points:
var unitPoints = [];
for (let i = 0; i < spline.getLength(); i++){
let p = spline.getUtoTmapping(0, i);
let p1 = spline.getPoint(p);
unitPoints.push(p1);
}
var unitPointsGeometry = new THREE.Geometry();
unitPointsGeometry.vertices = unitPoints;
var units = new THREE.Points(unitPointsGeometry, new THREE.PointsMaterial({size: .125, color: "maroon"}));
scene.add(units);
Look at the source code of the code snippet and pay attention to the getProgress() function.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, .1, 1000);
camera.position.set(0, 1.5, 3);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x181818);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(4, 8));
var spline = new THREE.CatmullRomCurve3(
[
new THREE.Vector3(-2, 0, 0),
new THREE.Vector3(-1.9, .1, .1),
new THREE.Vector3(1, 1, 1),
new THREE.Vector3(0, -1, -2),
new THREE.Vector3(2, 0, 1)
]
);
spline.closed = true;
var splinePoints = spline.getPoints(200);
var lineGeom = new THREE.Geometry();
lineGeom.vertices = splinePoints;
var line = new THREE.Line(lineGeom, new THREE.LineBasicMaterial({
color: "orange"
}));
scene.add(line);
var sPoints = new THREE.Points(lineGeom, new THREE.PointsMaterial({
size: .0312,
color: "yellow"
}));
scene.add(sPoints);
var unitPoints = [];
for (let i = 0; i < spline.getLength(); i++) {
let p = spline.getUtoTmapping(0, i);
let p1 = spline.getPoint(p);
unitPoints.push(p1);
}
var unitPointsGeometry = new THREE.Geometry();
unitPointsGeometry.vertices = unitPoints;
var units = new THREE.Points(unitPointsGeometry, new THREE.PointsMaterial({
size: .125,
color: "maroon"
}));
scene.add(units);
var marker = new THREE.Mesh(new THREE.SphereGeometry(0.125, 4, 2), new THREE.MeshBasicMaterial({
color: "red",
wireframe: true
}));
marker.geometry.translate(0, 0, 0.0625);
marker.geometry.vertices[2].z = 0.25;
marker.geometry.vertices[4].z = 0;
scene.add(marker);
var markerLineGeometry = new THREE.Geometry();
markerLineGeometry.vertices.push(new THREE.Vector3(), new THREE.Vector3());
var line = new THREE.Line(markerLineGeometry, new THREE.LineBasicMaterial({
color: "white"
}));
scene.add(line);
var clock = new THREE.Clock();
var progress = 0;
var totalLength = spline.getLength();
var speed = .66; // unit a second
var ratio = speed / totalLength;
var shift = 0;
var basePoint = 0;
var lookAtPoint = 0;
var oldPosition = spline.getPoint(0);
var speedVector = new THREE.Vector3();
function setProgress(delta) {
if (progress > totalLength) progress = 0;
shift = progress + speed * 2;
shift = shift > totalLength ? shift - totalLength : shift;
basePoint = spline.getUtoTmapping(0, progress);
lookAtPoint = spline.getUtoTmapping(0, shift);
line.geometry.vertices[0].copy(spline.getPoint(basePoint));
line.geometry.vertices[1].copy(spline.getPoint(lookAtPoint));
line.geometry.verticesNeedUpdate = true;
marker.position.copy(line.geometry.vertices[0]);
marker.lookAt(line.geometry.vertices[1]);
progress += speed * delta;
}
render();
function render() {
requestAnimationFrame(render);
setProgress(clock.getDelta());
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Converting multiple BoxGeometries into a single BufferedGeometry

Question:
How can I merge N number of THREE.BoxGeometry objects into a single THREE.BufferedGeometry?
Right now I have something like this:
var buffer = new THREE.BufferGeometry();
for (var i = 0; i < meshList.length; ++i) {
var item = meshList[i];
var geometry = <THREE.BoxGeometry>item.geometry;
buffer.fromGeometry(geometry);
}
buffer.computeBoundingSphere();
var buffer_material = new THREE.MeshPhongMaterial({
color: 0x999999,
specular: 0x333333,
shininess: 50,
side: THREE.DoubleSide,
vertexColors: THREE.VertexColors,
shading: THREE.SmoothShading
});
var buffer_mesh = new THREE.Mesh(buffer, buffer_material);
this.Scene.add(buffer_mesh);
Unfortunately this doesn't totally work. I only see 1 box (instead of many boxes). Do I need to specify 'position'? If so, how can I do this?
Thanks!
You can merge THREE.Geometrys, and then convert the result to a THREE.BufferGeometry using a pattern like this:
var geometry = new THREE.Geometry();
for ( var count = 0; count < 10; count ++ ) {
var geo = new THREE.BoxGeometry( 5, 5, 5 );
geo.translate( THREE.Math.randFloat( - 5, 5 ), THREE.Math.randFloat( - 5, 5 ), THREE.Math.randFloat( - 5, 5 ) );
geometry.merge( geo );
}
geometry = new THREE.BufferGeometry().fromGeometry( geometry );
three.js r.75

Texture appears black on custom mesh but transparency is right

I created a mesh with vertices and uvs from another geometry like this:
var geom = mesh.geometry;
var projectGeometry = new THREE.Geometry();
var faces = [];
for(var i = 0; i < geom.faces.length; i++){
var verts = [geom.faces[i].a, geom.faces[i].b, geom.faces[i].c];
var uvs = [geom.faceVertexUvs[0][i][0], geom.faceVertexUvs[0][i][1], geom.faceVertexUvs[0][i][2]];
var pts = [];
var uvpts = {};
var uv = [];
var vec = geom.vertices[verts[v]].clone();
for(var n = 0; n < 3; n++){
uv.push(new THREE.Vector2( (vec[n].x + 1) / 2, (vec[n].y + 1) / 2));
uvpts = { x: 2*geom.faceVertexUvs[0][i][n].x - 1, y: 2*geom.faceVertexUvs[0][i][n].y - 1, z: 0};
projectGeometry.vertices.push( uvpts );
}
projectGeometry.faceVertexUvs[0].push(uv);
var newFace = geom.faces[i].clone();
newFace.a = decalGeometry.vertices.length - 3;
newFace.b = decalGeometry.vertices.length - 2;
newFace.c = decalGeometry.vertices.length - 1;
var newUvFace = new THREE.Face3( newFace.a, newFace.b, newFace.c );
newUvFace.normal = {x: 0, y: 0, z: 1};
newUvFace.color = {r: 1, g: 1, b: 1};
newUvFace.vertexNormals.push({x: 0, y: 0, z: 1});
newUvFace.vertexNormals.push({x: 0, y: 0, z: 1});
newUvFace.vertexNormals.push({x: 0, y: 0, z: 1});
projectGeometry.faces.push(newUvFace);
}
The I added the mesh to the scene like this:
var mesh = new THREE.Mesh(projectGeometry, material.clone());
scene.add(mesh);
With a material defined like this:
texture = THREE.ImageUtils.loadTexture("tex.png");
material: new THREE.MeshPhongMaterial({
side: THREE.DoubleSide,
color: 0xffffff,
map: texture,
polygonOffset: true,
polygonOffsetFactor: -4,
transparent: true,
depthWrite: false,
shininess: 150,
specular: 0xffffff
});
The texture has some transparency, so I can see that the "shape" of the texture is right but no color is applied. It is all black.
It was a light problem. As I have transparency in my texture material, I used the PhongMaterial. I configured a DirectionalLight to illuminate the scene. For some reason the texture colors were rendered black. I changed the light to AmbientLight and everything was rendered fine.

BufferGeometry : Vertex Colors changed, but not updated visually

while using Three.js i met a problem connected with vertexes colors.
I created BufferGeometry , which consists of squares made by 2 triangles.
var geometry = new THREE.BufferGeometry();
// filling positions and colors
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3));
var material = new THREE.MeshPhongMaterial(
{
side: THREE.OneSide, vertexColors: THREE.VertexColors
});
GridFloor = new THREE.Mesh(geometry, material);
GridFloor.rotation.x = Math.PI / 2;
GridFloor.geometry.dynamic = true;
GridFloor.geometry.__dirtyColors = true;
scene.add(GridFloor);
Everything works fine, until i change vertex colors. I am changing them , trying to update , but nothing happens...
var newColor = new THREE.Color(0xff0000);
var colors = GridFloor.geometry.attributes.color.array;
for (var i = 0, j = 0; i < 4; i++, j += 3) {
var index = INTERSECTED.indices[i % 3] * 3;
colors[index] = newColor.r;
colors[index + 1] = newColor.g;
colors[index + 2] = newColor.b;
}
GridFloor.geometry.colorsNeedUpdate = true;
INTERSECTED.colorsNeedUpdate = true;
Thank you for your help.
Here is how you set the needsUpdate flag for BufferGeometry.
bufferGeometry.attributes.attributeName.needsUpdate = true;
three.js r.68

Resources