在 Three.js 中对圆柱体进行纹理处理

发布于 2024-12-18 15:20:30 字数 684 浏览 0 评论 0原文

我已经关注这个很久了。 我只是在任何地方都找不到任何解决方案。 我正在尝试在圆柱体上应用 3 种不同的纹理(2 个盖子和侧面) 但我完全不知道如何实现这一目标。 你能给我指路吗? 这就是我现在正在做的事情:

var coin1_geo = new THREE.CylinderGeometry( 100, 100, 10, 100, 100, false );
var coin1_texture = THREE.ImageUtils.loadTexture("./assets/avers.png");
var coin1_mat = new THREE.MeshLambertMaterial({map:coin1_texture});
var coin1 = new THREE.Mesh( coin1_geo, coin1_mat );
coin1.rotation.x = 20;
coin1.position.set(0,0,0);
coin1.castShadow = true;
coin1.receiveShadow = false;
scene.add( coin1 );

正如您所看到的,我只在所有面上应用一种纹理。 但即使在帽子上,它也没有真正显示出来,我只有整个圆圈的一部分。 请帮忙,如果你不明白的话,我正在获得一枚硬币。 即使您只是给我一个教程的链接,我也会非常感激。 我找不到任何东西,而且我在 3D/OpenGL 编程方面的知识也非常有限。 多谢。

I'm looking after this for a long time now.
I just can't find any solution, anywhere.
I'm trying to apply 3 different textures on a cylinder (2 caps, and side)
But I have absolutely no idea on how to achieve this.
Can you orient me?
Here's what I'm doing for now :

var coin1_geo = new THREE.CylinderGeometry( 100, 100, 10, 100, 100, false );
var coin1_texture = THREE.ImageUtils.loadTexture("./assets/avers.png");
var coin1_mat = new THREE.MeshLambertMaterial({map:coin1_texture});
var coin1 = new THREE.Mesh( coin1_geo, coin1_mat );
coin1.rotation.x = 20;
coin1.position.set(0,0,0);
coin1.castShadow = true;
coin1.receiveShadow = false;
scene.add( coin1 );

As you can see here, I only apply one texture on all faces.
But even on caps, it's not really displaying, I only have a piece of the full circle.
Please help, I'm achieving a coin, if you didn't figure out.
Even if you just give me a link to a tutorial I would be really thanksfull.
I can't find anything, and my knowledge in 3D/OpenGL programming is quite limited.
Thanks a lot.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蹲墙角沉默 2024-12-25 15:20:30

[编辑] 三个圆柱体不起作用,因为帽 UV 是假的。
您需要滚动自己的帽子几何形状。工作量不大,只是烦人。以下是使用定制盖制作无盖气缸的方法:

var coin_sides_geo =
  new THREE.CylinderGeometry( 10.0, 10.0, 1.0, 100.0, 10.0, true );
var coin_cap_geo = new THREE.Geometry();
var r = 10.0;
for (var i=0; i<100; i++) {
  var a = i * 1/100 * Math.PI * 2;
  var z = Math.sin(a);
  var x = Math.cos(a);
  var a1 = (i+1) * 1/100 * Math.PI * 2;
  var z1 = Math.sin(a1);
  var x1 = Math.cos(a1);
  coin_cap_geo.vertices.push(
    new THREE.Vertex(new THREE.Vector3(0, 0, 0)),
    new THREE.Vertex(new THREE.Vector3(x*r, 0, z*r)),
    new THREE.Vertex(new THREE.Vector3(x1*r, 0, z1*r))
  );
  coin_cap_geo.faceVertexUvs[0].push([
    new THREE.UV(0.5, 0.5),
    new THREE.UV(x/2+0.5, z/2+0.5),
    new THREE.UV(x1/2+0.5, z1/2+0.5)
  ]);
  coin_cap_geo.faces.push(new THREE.Face3(i*3, i*3+1, i*3+2));
}
coin_cap_geo.computeCentroids();
coin_cap_geo.computeFaceNormals();

var coin_sides_texture =
  THREE.ImageUtils.loadTexture("./coin_sides.png");
var coin_cap_texture =
  THREE.ImageUtils.loadTexture("./coin_face.png");

var coin_sides_mat =
  new THREE.MeshLambertMaterial({map:coin_sides_texture});
var coin_sides =
  new THREE.Mesh( coin_sides_geo, coin_sides_mat );

var coin_cap_mat = new THREE.MeshLambertMaterial({map:coin_cap_texture});
var coin_cap_top = new THREE.Mesh( coin_cap_geo, coin_cap_mat );
var coin_cap_bottom = new THREE.Mesh( coin_cap_geo, coin_cap_mat );
coin_cap_top.position.y = 0.5;
coin_cap_bottom.position.y = -0.5;
coin_cap_top.rotation.x = Math.PI;

var coin = new THREE.Object3D();
coin.add(coin_sides);
coin.add(coin_cap_top);
coin.add(coin_cap_bottom);

[edit] Three cylinders didn't work since the cap UVs are bogus.
You need to roll your own cap geometries. Not a lot of work, just annoying. Here's how to do an uncapped cylinder with custom caps:

var coin_sides_geo =
  new THREE.CylinderGeometry( 10.0, 10.0, 1.0, 100.0, 10.0, true );
var coin_cap_geo = new THREE.Geometry();
var r = 10.0;
for (var i=0; i<100; i++) {
  var a = i * 1/100 * Math.PI * 2;
  var z = Math.sin(a);
  var x = Math.cos(a);
  var a1 = (i+1) * 1/100 * Math.PI * 2;
  var z1 = Math.sin(a1);
  var x1 = Math.cos(a1);
  coin_cap_geo.vertices.push(
    new THREE.Vertex(new THREE.Vector3(0, 0, 0)),
    new THREE.Vertex(new THREE.Vector3(x*r, 0, z*r)),
    new THREE.Vertex(new THREE.Vector3(x1*r, 0, z1*r))
  );
  coin_cap_geo.faceVertexUvs[0].push([
    new THREE.UV(0.5, 0.5),
    new THREE.UV(x/2+0.5, z/2+0.5),
    new THREE.UV(x1/2+0.5, z1/2+0.5)
  ]);
  coin_cap_geo.faces.push(new THREE.Face3(i*3, i*3+1, i*3+2));
}
coin_cap_geo.computeCentroids();
coin_cap_geo.computeFaceNormals();

var coin_sides_texture =
  THREE.ImageUtils.loadTexture("./coin_sides.png");
var coin_cap_texture =
  THREE.ImageUtils.loadTexture("./coin_face.png");

var coin_sides_mat =
  new THREE.MeshLambertMaterial({map:coin_sides_texture});
var coin_sides =
  new THREE.Mesh( coin_sides_geo, coin_sides_mat );

var coin_cap_mat = new THREE.MeshLambertMaterial({map:coin_cap_texture});
var coin_cap_top = new THREE.Mesh( coin_cap_geo, coin_cap_mat );
var coin_cap_bottom = new THREE.Mesh( coin_cap_geo, coin_cap_mat );
coin_cap_top.position.y = 0.5;
coin_cap_bottom.position.y = -0.5;
coin_cap_top.rotation.x = Math.PI;

var coin = new THREE.Object3D();
coin.add(coin_sides);
coin.add(coin_cap_top);
coin.add(coin_cap_bottom);
谁许谁一生繁华 2024-12-25 15:20:30

在现代 Three.js 中,您可以使用 3 种材质的数组创建一个圆柱体:

const materials = [
  sideMaterial,
  topMaterial,
  bottomMaterial
]
const geometry = new THREE.CylinderGeometry(5, 5, 0.5, 100)
const mesh= new THREE.Mesh(geometry, materials)

In modern Three.js you can create a cylinder with an array of 3 materials:

const materials = [
  sideMaterial,
  topMaterial,
  bottomMaterial
]
const geometry = new THREE.CylinderGeometry(5, 5, 0.5, 100)
const mesh= new THREE.Mesh(geometry, materials)
各空 2024-12-25 15:20:30

TypeScript 函数变体,创建具有 3 个网格的 Object3D:side、topCap 和 BottomCap。
适用于 lib 版本:
“三”:“0.102.1”

 import capTop from './textures/capTopTexture.png';
 import capBottom from './textures/capBottomTexture.png';
 import capSide from './textures/sideTexture.png';

 function createCylinder (
        radiusTop: number,
        radiusBottom: number,
        height: number,
        radialSegments: number,
        heightSegments: number,
    ): Object3D {
        const cylinder = new THREE.Object3D();

        const sidesGeo = new THREE.CylinderGeometry(
            radiusTop,
            radiusBottom,
            height,
            radialSegments,
            heightSegments,
            true,
        );
        const sideTexture = new THREE.TextureLoader().load(capSide, this.reRender);
        const sidesMat =
            new THREE.MeshLambertMaterial({map: sideTexture});
        const sidesMesh =
            new THREE.Mesh( sidesGeo, sidesMat );
        cylinder.add(sidesMesh);

        const capTopGeo = new THREE.CircleGeometry(radiusTop, radialSegments);
        const capTopTexture = new THREE.TextureLoader().load(capTop, this.reRender);
        const capTopMat =
            new THREE.MeshLambertMaterial({map: capTopTexture});
        const capTopMesh =
            new THREE.Mesh( capTopGeo, capTopMat );
        capTopMesh.position.y = height / 2;
        capTopMesh.rotation.x = - Math.PI / 2;
        cylinder.add(capTopMesh);

        const capBottomGeo = new THREE.CircleGeometry(radiusBottom, radialSegments);
        const capBottomTexture = new THREE.TextureLoader().load(capBottom, this.reRender);
        const capBottomMat =
            new THREE.MeshLambertMaterial({map: capBottomTexture});
        const capBottomMesh =
            new THREE.Mesh( capBottomGeo, capBottomMat );
        capBottomMesh.position.y = -height / 2;
        capBottomMesh.rotation.x = Math.PI / 2;
        cylinder.add(capBottomMesh);

        return cylinder;
    };


TypeScript function variant, that creates Object3D with 3 meshes: side, topCap and bottomCap.
Works with lib version:
"three": "0.102.1"

 import capTop from './textures/capTopTexture.png';
 import capBottom from './textures/capBottomTexture.png';
 import capSide from './textures/sideTexture.png';

 function createCylinder (
        radiusTop: number,
        radiusBottom: number,
        height: number,
        radialSegments: number,
        heightSegments: number,
    ): Object3D {
        const cylinder = new THREE.Object3D();

        const sidesGeo = new THREE.CylinderGeometry(
            radiusTop,
            radiusBottom,
            height,
            radialSegments,
            heightSegments,
            true,
        );
        const sideTexture = new THREE.TextureLoader().load(capSide, this.reRender);
        const sidesMat =
            new THREE.MeshLambertMaterial({map: sideTexture});
        const sidesMesh =
            new THREE.Mesh( sidesGeo, sidesMat );
        cylinder.add(sidesMesh);

        const capTopGeo = new THREE.CircleGeometry(radiusTop, radialSegments);
        const capTopTexture = new THREE.TextureLoader().load(capTop, this.reRender);
        const capTopMat =
            new THREE.MeshLambertMaterial({map: capTopTexture});
        const capTopMesh =
            new THREE.Mesh( capTopGeo, capTopMat );
        capTopMesh.position.y = height / 2;
        capTopMesh.rotation.x = - Math.PI / 2;
        cylinder.add(capTopMesh);

        const capBottomGeo = new THREE.CircleGeometry(radiusBottom, radialSegments);
        const capBottomTexture = new THREE.TextureLoader().load(capBottom, this.reRender);
        const capBottomMat =
            new THREE.MeshLambertMaterial({map: capBottomTexture});
        const capBottomMesh =
            new THREE.Mesh( capBottomGeo, capBottomMat );
        capBottomMesh.position.y = -height / 2;
        capBottomMesh.rotation.x = Math.PI / 2;
        cylinder.add(capBottomMesh);

        return cylinder;
    };


~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文