J'essaie de faire une boîte en TROIS qui représente une boîte de 2x4 Legos, 24 pièces de large par 48 pièces de long et un nombre arbitraire de pièces de haut. J'ai généré une texture qui montre ce motif en utilisant des couleurs aléatoires:

enter image description here

Je dois montrer les deux côtés de ce cube, mais les textures doivent être alignées de sorte que les pièces sur les bords soient de la même couleur, comme cela (généré dans Blender):

enter image description here

Je préférerais vraiment ne pas faire six images pour une CubeTexture, d'autant plus que quatre ne sont pas visibles. Est-il possible d'inverser la texture d'un côté pour qu'elles semblent s'aligner? (Nous allons juste pour un effet visuel ici.)

De plus, tous les rectangles 3D ne seront pas des cubes, mais je n'arrive pas à comprendre comment définir les texture.repeat.x et texture.repeat.y pour que le x soit mis à l'échelle correctement et le y à la même échelle, mais coupe juste quand la hauteur de l'objet se termine, comme ceci:

enter image description here

Merci!

0
Chris Wilson 11 avril 2018 à 21:45

3 réponses

Meilleure réponse

Vous pouvez retourner une image en retournant les UV.

Vous devrez déterminer quels UV correspondent à la face que vous essayez de refléter et dans quelle direction les inverser (vous ne savez pas comment votre géométrie est créée).

Voici un exemple utilisant un BoxBufferGeometry de base et modifiant son uv attribut. (Le visage sur la droite est le visage inversé en miroir par UV.)

var textureURL = "https://upload.wikimedia.org/wikipedia/commons/0/02/Triangular_hebesphenorotunda.png";
// attribution and license here: https://commons.wikimedia.org/wiki/File:Triangular_hebesphenorotunda.png

var renderer = new THREE.WebGLRenderer({antialias:true});
document.body.appendChild(renderer.domElement);
renderer.setSize(500, 500);

var textureLoader = new THREE.TextureLoader();

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
camera.position.set(50, 25, 50);
camera.lookAt(scene.position);
scene.add(camera);

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

var cubeGeo = new THREE.BoxBufferGeometry(20, 20, 20);
var uvs = cubeGeo.attributes.uv;
// originally:
// [0] = 0,1
// [1] = 1,1
// [2] = 0,0
// [3] = 1,0
// convert to:
// [0] = 1,1
// [1] = 0,1
// [2] = 1,0
// [3] = 0.0
uvs.setX(0, 1);
uvs.setY(0, 1);
uvs.setX(1, 0);
uvs.setY(1, 1);
uvs.setX(2, 1);
uvs.setY(2, 0);
uvs.setX(3, 0);
uvs.setY(3, 0);
uvs.needsUpdate = true;

var mat = new THREE.MeshLambertMaterial({
  color: "white",
  map: textureLoader.load(textureURL, function(){
    animate();
  })
});
var mesh = new THREE.Mesh(cubeGeo, mat);
scene.add(mesh);

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

function animate() {
  requestAnimationFrame(animate);
  render();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
3
Chris Wilson 12 avril 2018 à 09:37

Vous pouvez créer six PlaneBufferGeometries affecter le même matériau, puis les positionner pour former un cube. Faites-les pivoter par incréments de 90 degrés jusqu'à ce que vous atteigniez le résultat souhaité. Pour des raisons de performances, vous pouvez les fusionner en un seul BufferGeometry.

1
pailhead 11 avril 2018 à 18:52

Vous pouvez exporter le modèle que vous avez créé dans Blender, en utilisant l'exportateur json THREE.js ou un format comme OBJ ou GLTF, et le charger et le rendre directement.

Ce dont vous parlez, c'est simplement de disposer les UV comme vous les avez dans le mélangeur .. donc si vous avez besoin de ce niveau de contrôle .. il est probablement plus facile de simplement charger le modèle au lieu d'essayer de le générer.

Si vous utilisez three.js .json ou .gltf, les deux exportateurs ont la possibilité d'incorporer les textures directement dans l'exportation. Cela peut faciliter le travail plus rapidement, au détriment d'un stockage éventuellement moins efficace.

0
manthrax 11 avril 2018 à 21:32