Reputation: 21
I want to set colors according to the height of my model, which is a .obj file. I want the colors to go from green to red, depending on the height, green for the minimum point, red for the maximum. This is my code currently:
loader.load(nombreMapa, function (object) {
loader.setMaterials(material);
escena.add(object);
object.position.y = -10;
if (object instanceof THREE.Object3D)
{
object.traverse (function (mesh)
{
if (! (mesh instanceof THREE.Mesh)) return;
mesh.material = new THREE.MeshNormalMaterial();
mesh.material.side = THREE.DoubleSide;
var geometry = new THREE.EdgesGeometry( mesh.geometry );
var material1 = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 1000 } );
var edges = new THREE.LineSegments( geometry, material1 );
mesh.add( edges );
});
}});
Upvotes: 2
Views: 384
Reputation: 17586
You can do this trick, using THREE.Box3()
and .lerp()
method of THREE.Color()
for setting colors of each vertex in each child's mesh's geometry.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 60, 250);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target.set(0, 60, 0);
controls.update();
var mat = new THREE.MeshBasicMaterial({
wireframe: true,
vertexColors: THREE.VertexColors
}); // the same material for all the children of the object
var loader = new THREE.OBJLoader();
loader.load('https://threejs.org/examples/models/obj/male02/male02.obj', function(obj) {
var size = new THREE.Vector3();
var box3 = new THREE.Box3().setFromObject(obj);
box3.getSize(size);
console.log(size);
var v3 = new THREE.Vector3(); // for re-use
var c = [
new THREE.Color(0x00ff00),
new THREE.Color(0xff0000)
];
var cTemp = new THREE.Color(); // for re-use
obj.traverse(child => {
if (child.isMesh) {
let colors = []; // array for color values of the current mesh's geometry
let pos = child.geometry.attributes.position;
for(let i = 0; i < pos.count; i++){
v3.fromBufferAttribute(pos, i);
obj.localToWorld(v3); // box3 is in world coords so we have to convert coortinates of the vertex from local to world
let a = (v3.y - box3.min.y) / size.y; // find the value in range 0..1
cTemp.copy(c[0]).lerp(c[1], a); // lerp the colors
colors.push(cTemp.r, cTemp.g, cTemp.b); // save values in the array
child.geometry.addAttribute("color", new THREE.BufferAttribute(new Float32Array(colors), 3)); // add a buffer attribute for colors
child.material = mat;
}
}
});
scene.add(obj);
})
renderer.setAnimationLoop(() => {
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>
<script src="https://threejs.org/examples/js/loaders/OBJLoader.js"></script>
Also, take a look at this SO answer about other options of how to apply gradient.
Upvotes: 2