0

Somewhat new to Three.js and 3d libraries in general.

I merged two geometries (a quarter cylinder and a plane) using this code:

  var planeGeo = new THREE.PlaneGeometry(planeW, planeD / 2, 199, 399);
  var planeMesh = new THREE.Mesh(planeGeo);
  planeMesh.updateMatrix();

  var cylinderGeo = new THREE.CylinderGeometry(100, 100, planeW, 199, 399, true, 0, Math.PI / 2);
  cylinderGeo.rotateZ(Math.PI / 2).translate(0, 200, -100);
  var cylinderMesh = new THREE.Mesh(cylinderGeo);
  cylinderMesh.updateMatrix();

  var singleGeometry = new THREE.Geometry();
  singleGeometry.merge(planeMesh.geometry, planeMesh.matrix);
  singleGeometry.merge(cylinderMesh.geometry, cylinderMesh.matrix);

  var testmaterial = new THREE.MeshPhongMaterial({ color: 0x666666 });
  mesh = new THREE.Mesh(singleGeometry, testmaterial);
  scene.add(mesh);

Merged geometries

I then would like to use a single material (png) over the entire thing. This code doesn't work:

textureLoader.load('data/test.png', function (texture) {
  material = new THREE.MeshLambertMaterial({
    map: texture
  });
});

Later in the block with the merging...

mesh = new THREE.Mesh(singleGeometry, material);
scene.add(mesh);

This results in:

Merged geometries, but material doubled

I would like the end result to be a single draped png over the entire merged geometry, but I can't find anything that suggests this is a normal thing to do. Is there a better way to achieve that result than merging geometries? Or am I just looking in the wrong places?

Josh
  • 3,385
  • 5
  • 23
  • 45
  • Each vertex has uv-coordinate attribute, which is interpolated and used then for texture lookup. These geometries have they own sets of uv coordinates is same constrains which you are leaving unmodified. So to get desired result you could modify uv's when you are merging or change usage of uvs in shader program. I think that modifying uv coords fits better to "merging" (if it could be done once - no need to do it real time). There are great tools for doing such things in 3d modelling software (3ds max, maya, etc). – Ramil Kudashev Aug 26 '16 at 18:48

1 Answers1

1

A poor-mans solution to achieve this, using the shape supplied in your post, is the following: https://jsfiddle.net/87wg5z27/44/

Using code from this answer: https://stackoverflow.com/a/20774922/4977165 It sets the UVs based on the bounding box of the geometry, leaving out the z-coordinate (=0). Thats why the texture is a little bit stretched at the top, you can correct that manually or maybe its sufficent for you.

geometry.computeBoundingBox();

var max = geometry.boundingBox.max,
    min = geometry.boundingBox.min;
var offset = new THREE.Vector2(0 - min.x, 0 - min.y);
var range = new THREE.Vector2(max.x - min.x, max.y - min.y);
var faces = geometry.faces;

geometry.faceVertexUvs[0] = [];

for (var i = 0; i < faces.length ; i++) {

  var v1 = geometry.vertices[faces[i].a], 
      v2 = geometry.vertices[faces[i].b], 
      v3 = geometry.vertices[faces[i].c];

  geometry.faceVertexUvs[0].push([
      new THREE.Vector2((v1.x + offset.x)/range.x ,(v1.y + offset.y)/range.y),
      new THREE.Vector2((v2.x + offset.x)/range.x ,(v2.y + offset.y)/range.y),
      new THREE.Vector2((v3.x + offset.x)/range.x ,(v3.y + offset.y)/range.y)
  ]);
}
geometry.uvsNeedUpdate = true;
Community
  • 1
  • 1
Falk Thiele
  • 4,424
  • 2
  • 17
  • 44
  • This gets me most of the way there. I'll need to do some manual correction, but this is a great start. Thanks. – Josh Aug 29 '16 at 18:09