I'm trying to write a component that:
- copies the geometry of a plane to a new custom mesh
- colors the vertices in the new mesh based on the height of the vertex.
- changes the new mesh to layer(1) so only a secondary camera can view it.
//PRE: This component must be attached to a plane.
// this.el.maxElevation, this.el.minElevation are defined and contain
// the min and max elevation of the plane
// add-second-camera is attached to the scene, and emits 'secondary-camera-completed' when done
// #secondarycam and #primarycam are cameras in the scene
AFRAME.registerComponent("elevation-coloring-for-second-cam", {
init: function(){
if (this.el.sceneEl.components["add-second-camera"] && this.el.sceneEl.components["add-second-camera"].hasFinished) {
console.log("add-second-camera.finished = true. Starting component...");
this.startComponent();
}
else {
console.log("add-second-camera.finished != true. Attaching a listener for 'secondary-camera-completed'");
this.el.addEventListener("secondary-camera-completed", () => {
this.startComponent();
});
}
},
startComponent:function(){
console.log("startComponent begins here...");
const scene = this.el.sceneEl;
const planeEl = this.el;
const origMesh = planeEl.getObject3D("mesh");
const sCam = document.querySelector("#secondarycam").getObject3D("camera");
const pCam = document.querySelector("#primarycam").getObject3D("camera");
const newMesh = this.shallowCopyGeometryAndMeshTransform(origMesh.geometry, origMesh);
this.heightBasedColoring(newMesh.geometry);
newMesh.layers.set(1);
scene.object3D.add(newMesh);
pCam.layers.disable(1);
sCam.layers.enable(1);
sCam.layers.disable(0);
//Test cube. Ignore this.
const testMesh = new THREE.Mesh(
new THREE.BoxGeometry(10, 10, 10),
new THREE.MeshBasicMaterial({ color: 'red' })
);
testMesh.position.set(0, 800, 0);
testMesh.layers.set(1);
scene.object3D.add(testMesh);
//testend
console.log("elevation-coloring-for-second-cam done.");
},
//CREATES SHALLOW COPY OF origMesh properties.
shallowCopyGeometryAndMeshTransform:function(geometry,origMesh){
const newGeom = geometry.clone();
const newMesh = new THREE.Mesh(newGeom, new THREE.MeshBasicMaterial({
vertexColors: true,
}) );
newMesh.position = origMesh.position;
newMesh.rotation = origMesh.rotation;
newMesh.scale = origMesh.scale;
return newMesh;
},
heightBasedColoring: function(newGeom){
const vertices = newGeom.attributes.position.array;
const colors = [];
for (let i = 0; i < vertices.length; i += 3) {
const y = Math.abs(vertices[i + 1]);
const hue = ((this.el.maxElevation-y)/(this.el.maxElevation - this.el.minElevation))*0.7;
const col = new THREE.Color();
col.setHSL(hue, 1.0, 0.5);
colors.push(col.r, col.g, col.b);
}
newGeom.setAttribute('color', new THREE.Float32BufferAttribute(new Float32Array(colors), 3));
newGeom.attributes.color.needsUpdate = true;
}
});
The mesh just never renders. I can see the test block in the secondary-camera, so I know the camera is watching the correct layer. Even more confusing, whenever i slightly edit the code and the page hot reloads, then the mesh renders fine. As soon as I reload the page, it disappears again. I assumed its a async timing issue, but I've set up logs throughout my code and everything seems to be happening in the right order. When this.startComponent() begins, the plane is loaded and both cameras are defined. I'm new to aframe and three.js so I might just be overlooking something simple.