Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
463 views
in Technique[技术] by (71.8m points)

javascript - Paint cube faces as a whole, not the triangles that make up the face - three.js

Trying to paint each cube face with a different color, I found a thread that presents a way to achieve this:

var geometry = new THREE.BoxGeometry(5, 5, 5);
for (var i = 0; i < geometry.faces.length; i++) {
    geometry.faces[i].color.setHex(Math.random() * 0xffffff);
}

var material = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    vertexColors: THREE.FaceColors
});

But with three.js r86, I get the following result:

LeCube with painted triangles

Got the triangles that make up each face, painted individually.

To achieve the desirable effect, I used the following adaptation of the above code:

var geometry = new THREE.BoxGeometry(5, 5, 5);
for ( var i = 0; i < geometry.faces.length; i += 2 ) {
    var faceColor = Math.random() * 0xffffff;
    geometry.faces[i].color.setHex(faceColor);
    geometry.faces[i+1].color.setHex(faceColor);
}

var material = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    vertexColors: THREE.FaceColors
});

LeCube with painted faces as a whole

But this all seems a bit over worked!

'use strict';

var camera, scene, renderer, cube;

init();
render();

function init() {

  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

  // renderer

  renderer = new THREE.WebGLRenderer({
    alpha: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  camera.position.z = 12;

  // Mesh - cube

  var geometry = new THREE.BoxGeometry(5, 5, 5);
  for (var i = 0; i < geometry.faces.length; i += 2) {
    var faceColor = Math.random() * 0xffffff;
    geometry.faces[i].color.setHex(faceColor);
    geometry.faces[i + 1].color.setHex(faceColor);
  }

  var material = new THREE.MeshBasicMaterial({
    color: 0xffffff,
    vertexColors: THREE.FaceColors
  });

  cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  // Light

  var pointLight = new THREE.PointLight(0xFFFFFF);

  pointLight.position.x = 10;
  pointLight.position.y = 50;
  pointLight.position.z = 130;

  scene.add(pointLight);

}

function render() {

  cube.rotation.x = 16;
  cube.rotation.y = 4;
  cube.rotation.z -= 5;

  renderer.render(scene, camera);

}
body,
canvas {
  margin: 0;
  padding: 0;
}

body {
  overflow: hidden;
  background-color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.js"></script>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you switch to BufferGeometry you can use groups to control the material of sections of your geometry. Groups are based on the vertex indices, and allow you to define a material index, which will reference a material inside an array of materials.

Consider:

// start, count, material index
bufferGeometry.addGroup(12, 6, 2)

This tells the geometry to start a new group of triangles at indices index 12, and accounts for 6 indices (which reference 6 vertices). The final parameter tells the group of triangles to use material index 2 (index 2 of the array of materials you use to create the mesh).

In the example below, I've given each side of a cube a different color. You might think this is the same effect as setting face colors, but note that this is setting a material per group, not just a color, which can lead to creating some really cool effects.

var renderer, scene, camera, controls, stats, mesh;

var WIDTH = window.innerWidth,
  HEIGHT = window.innerHeight,
  FOV = 35,
  NEAR = 1,
  FAR = 1000;

function populateScene() {
  var bg = new THREE.BufferGeometry();
  bg.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
    // front
    -1, 1, 1, // 0
    -1, -1, 1, // 1
    1, 1, 1, // 2
    1, -1, 1, // 3
    // right
    1, 1, 1, // 4
    1, -1, 1, // 5
    1, 1, -1, // 6
    1, -1, -1, // 7
    // back
    1, 1, -1, // 8
    1, -1, -1, // 9
    -1, 1, -1, // 10
    -1, -1, -1, // 11
    // left
    -1, 1, -1, // 12
    -1, -1, -1, // 13
    -1, 1, 1, // 14
    -1, -1, 1, // 15
    // top
    -1, 1, -1, // 16
    -1, 1, 1, // 17
    1, 1, -1, // 18
    1, 1, 1, // 19
    // bottom
    -1, -1, 1, // 20
    -1, -1, -1, // 21
    1, -1, 1, // 22
    1, -1, -1 // 23
  ]), 3));
  bg.addAttribute("normal", new THREE.BufferAttribute(new Float32Array([
    // front
    0, 0, 1, // 0
    0, 0, 1, // 1
    0, 0, 1, // 2
    0, 0, 1, // 3
    // right
    1, 0, 0, // 4
    1, 0, 0, // 5
    1, 0, 0, // 6
    1, 0, 0, // 7
    // back
    0, 0, -1, // 8
    0, 0, -1, // 9
    0, 0, -1, // 10
    0, 0, -1, // 11
    // left
    -1, 0, 0, // 12
    -1, 0, 0, // 13
    -1, 0, 0, // 14
    -1, 0, 0, // 15
    // top
    0, 1, 0, // 16
    0, 1, 0, // 17
    0, 1, 0, // 18
    0, 1, 0, // 19
    // bottom
    0, -1, 0, // 20
    0, -1, 0, // 21
    0, -1, 0, // 22
    0, -1, 0 // 23
  ]), 3));
  bg.setIndex(new THREE.BufferAttribute(new Uint32Array([
    // front 0
    0, 1, 2,
    3, 2, 1,
    // right 6
    4, 5, 6,
    7, 6, 5,
    // back 12
    8, 9, 10,
    11, 10, 9,
    // left 18
    12, 13, 14,
    15, 14, 13,
    // top 24
    16, 17, 18,
    19, 18, 17,
    // bottom 30
    20, 21, 22,
    23, 22, 21
  ]), 1));
  
  bg.clearGroups();
  // start, count, material index
  bg.addGroup(0, 6, 0);
  bg.addGroup(6, 6, 1);
  bg.addGroup(12, 6, 2);
  bg.addGroup(18, 6, 3);
  bg.addGroup(24, 6, 4);
  bg.addGroup(30, 6, 5);
  
  var materials = [
    new THREE.MeshLambertMaterial({color:"red"}),
    new THREE.MeshLambertMaterial({color:"green"}),
    new THREE.MeshLambertMaterial({color:"blue"}),
    new THREE.MeshLambertMaterial({color:"cyan"}),
    new THREE.MeshLambertMaterial({color:"magenta"}),
    new THREE.MeshLambertMaterial({color:"yellow"})
  ];
  
  mesh = new THREE.Mesh(bg, materials);
  mesh.scale.set(5, 5, 5);
  
  scene.add(mesh);
}

function init() {
  document.body.style.backgroundColor = "slateGray";

  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;

  document.body.appendChild(renderer.domElement);
  document.body.style.overflow = "hidden";
  document.body.style.margin = "0";
  document.body.style.padding = "0";

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
  camera.position.z = 50;
  scene.add(camera);

  controls = new THREE.TrackballControls(camera, renderer.domElement);
  controls.dynamicDampingFactor = 0.5;
  controls.rotateSpeed = 3;

  var light = new THREE.PointLight(0xffffff, 1, Infinity);
  camera.add(light);

  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0';
  document.body.appendChild(stats.domElement);

  resize();
  window.onresize = resize;

  populateScene();

  animate();
}

function resize() {
  WIDTH = window.innerWidth;
  HEIGHT = window.innerHeight;
  if (renderer && camera && controls) {
    renderer.setSize(WIDTH, HEIGHT);
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
    controls.handleResize();
  }
}

function render() {
  renderer.render(scene, camera);
}

function animate() {
  mesh.rotation.x += 0.015;
  mesh.rotation.y += 0.017;
  mesh.rotation.z += 0.019;
  requestAnimationFrame(animate);
  render();
  controls.update();
  stats.update();
}

function threeReady() {
  init();
}

(function() {
  function addScript(url, callback) {
    callback = callback || function() {};
    var script = document.createElement("script");
    script.addEventListener("load", callback);
    script.setAttribute("src", url);
    document.head.appendChild(script);
  }

  addScript("https://threejs.org/build/three.js", function() {
    addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
      addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
        threeReady();
      })
    })
  })
})();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...