首页 > 解决方案 > 基于 .obj 模型的颜色

问题描述

我想根据我的模型的高度设置颜色,这是一个 .obj 文件。我希望颜色从绿色变为红色,具体取决于高度,最小点为绿色,最大点为红色。这是我目前的代码:

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 );
    });
}});

标签: javascripthtmlthree.js

解决方案


您可以使用THREE.Box3().lerp()方法THREE.Color()来设置每个子网格几何体中每个顶点的颜色。

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>

另外,请查看有关如何应用渐变的其他选项的SO answer 。


推荐阅读