gpt4 book ai didi

javascript - Three.js:自定义几何体不会被纹理化

转载 作者:行者123 更新时间:2023-11-28 06:33:02 26 4
gpt4 key购买 nike

我制作了两个自定义几何图形:Box2GeometryStaticTestPentagonPlaneGeometry

第一个纹理效果很好,如 Box2Geometry JSFiddle 所示。 。第二个不会纹理化,如 StaticTestPentagonPlaneGeometry JSFiddle 中所示。(请注意, fiddle 加载有点慢)。除了几何形状不同之外,这两个 fiddle 基本相同。 StaticTestPentagonPlaneGeometry 的 Material 已被指定为 emissive: 0xffffff 作为参数,但删除此属性并不能解决问题。

为了完整起见,我还制作了 third fiddle ,旨在同时展示两种几何形状的作用。然而,这个 fiddle 无法渲染任何东西,我想计算之神现在肯定在笑。

Box2Geometry fiddle 的渲染输出:

Output of Box2 fiddle

StaticTestPentagonPlaneGeometry fiddle 的渲染输出:

Rendering from StaticTestPentagonPlaneGeometry fiddle

来自 Box2Geometry fiddle 的表现良好的代码:

"use strict";

// make DOM elements:
var container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
container.appendChild( info );

// create scene:
var scene = new THREE.Scene();

// make the 'Box2' geometry, and its corresponding texture and mesh:
var loader = new THREE.TextureLoader();
loader.crossOrigin = "";
loader.load("http://mrdoob.github.io/three.js/examples/textures/crate.gif",
function ( texture ) {
var myBox2geom = new THREE.Box2Geometry( 100, 100, 100, 10, 10, 10 ); // args: x,y,z-dimensions and width of their segments
texture.minFilter = THREE.NearestFilter;
var material = new THREE.MeshLambertMaterial( { map: texture, side: THREE.DoubleSide } );
var myBox2mesh = new THREE.Mesh(myBox2geom, material);
scene.add( myBox2mesh );
},
function () {}, // onProgress function
function ( error ) { console.log( error ) } // no error gets logged
);

// make light:
var light = new THREE.PointLight( 0xffffff );
light.position.set(0, 0, 300);
light.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene.add( light );

// make camera:
var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0, 0, 300);
camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene.add( camera );

// make renderer:
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

// aaaand render, continuously!
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();


THREE.Box2Geometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {

THREE.Geometry.call( this );

this.parameters = {
width: width,
height: height,
depth: depth,
widthSegments: widthSegments,
heightSegments: heightSegments,
depthSegments: depthSegments
};

this.widthSegments = widthSegments || 1;
this.heightSegments = heightSegments || 1;
this.depthSegments = depthSegments || 1;

var constructee = this; // constructee = the instance currently being constructed by the Box2Geometry constructor

var width_half = width / 2; // width = the distance along x in the absolute 3D space
var height_half = height / 2; // height = the distance along y in the absolute 3D space
var depth_half = depth / 2; // depth = the distance along z in the absolute 3D space

buildPlane( 'z', 'y', -1, -1, depth, height, width_half, 0 ); // px
buildPlane( 'z', 'y', 1, -1, depth, height, -width_half, 1 ); // nx
buildPlane( 'x', 'z', 1, 1, width, depth, height_half, 2 ); // py
buildPlane( 'x', 'z', 1, -1, width, depth, -height_half, 3 ); // ny
buildPlane( 'x', 'y', 1, -1, width, height, depth_half, 4 ); // pz
buildPlane( 'x', 'y', -1, -1, width, height, -depth_half, 5 ); // nz

function buildPlane( u, v, uDir, vDir, uDist, vDist, wDist_half, materialIndex ) {

var w, iu, iv,
segU = constructee.widthSegments, // number of segments along u // width = x
segV = constructee.heightSegments, // number of segments along v // height = y
uDist_half = uDist / 2, // the extent of the plane along u, divided by two
vDist_half = vDist / 2, // the extent of the plane along v, divided by two
offset = constructee.vertices.length;

if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {

w = 'z';

} else if ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {

w = 'y';
segV = constructee.depthSegments;

} else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {

w = 'x';
segU = constructee.depthSegments;

}

var segUi = segU + 1, // i = inc = incremented (by one)
segVi = segV + 1, // i = inc = incremented (by one)
segmentDist_u = uDist / segU,
segmentDist_v = vDist / segV,
normal = new THREE.Vector3();

normal[ w ] = wDist_half > 0 ? 1 : -1;

for ( iv = 0; iv < segVi; iv++ ) {

for ( iu = 0; iu < segUi; iu++ ) {

var vertex = new THREE.Vector3();
vertex[ u ] = ( iu * segmentDist_u - uDist_half ) * uDir;
vertex[ v ] = ( iv * segmentDist_v - vDist_half ) * vDir;
vertex[ w ] = wDist_half;

constructee.vertices.push( vertex );

}

}

for ( iv = 0; iv < segV; iv++ ) {

for ( iu = 0; iu < segU; iu++ ) {

var a = iu + segUi * iv;
var b = iu + segUi * ( iv + 1 );
var c = ( iu + 1 ) + segUi * ( iv + 1 );
var d = ( iu + 1 ) + segUi * iv;

var uva = new THREE.Vector2( iu / segU, 1 - iv / segV );
var uvb = new THREE.Vector2( iu / segU, 1 - ( iv + 1 ) / segV );
var uvc = new THREE.Vector2( ( iu + 1 ) / segU, 1 - ( iv + 1 ) / segV );
var uvd = new THREE.Vector2( ( iu + 1 ) / segU, 1 - iv / segV );

var face1 = new THREE.Face3( a + offset, b + offset, d + offset );
face1.normal.copy( normal );
face1.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
face1.materialIndex = materialIndex;

constructee.faces.push( face1 );
constructee.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );

var face2 = new THREE.Face3( b + offset, c + offset, d + offset );
face2.normal.copy( normal );
face2.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
face2.materialIndex = materialIndex;

constructee.faces.push( face2 );
constructee.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );

}

}

}

this.mergeVertices();
};
THREE.Box2Geometry.prototype = Object.create( THREE.Geometry.prototype );
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.js"></script>
<script src="main.js"></script>
</body>
</html>

来自 StaticTestPentagonPlaneGeometry fiddle 的功能失调代码:

"use strict";

// make DOM elements:
var container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
container.appendChild( info );

// create scene:
var scene = new THREE.Scene();

// make the 'PentagonPlane' geometry, and its corresponding texture and mesh:
var loader = new THREE.TextureLoader();
loader.crossOrigin = "";
loader.load("http://mrdoob.github.io/three.js/examples/textures/crate.gif",
function ( texture ) {
var myStaticTestPentagonPlane_geometry = new THREE.StaticTestPentagonPlaneGeometry();
texture.minFilter = THREE.NearestFilter;
var material = new THREE.MeshLambertMaterial( { map: texture, side: THREE.DoubleSide, emissive: 0xffffff } ); // removing 'emissive' doesn't solve the problem
var myStaticTestPentagonPlane_mesh = new THREE.Mesh(myStaticTestPentagonPlane_geometry, material);
scene.add( myStaticTestPentagonPlane_mesh );
},
function () {}, // onProgress function
function ( error ) { console.log( error ) } // no error gets logged
);

// make light:
var light = new THREE.PointLight( 0xffffff );
light.position.set(0, 0, 300);
light.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene.add( light );

// make camera:
var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(0, 0, 300);
camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );
scene.add( camera );

// make renderer:
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

// aaaand render, continuously!
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();


THREE.StaticTestPentagonPlaneGeometry = function () {

THREE.Geometry.call(this);

var quintuplet = // static vertices of the PentagonPlaneGeometry
[
new THREE.Vector3(-50, -50, 51 ),
new THREE.Vector3(-50, 50, 51 ),
new THREE.Vector3( 50, 50, 51 ),
new THREE.Vector3( 70, 0, 51 ),
new THREE.Vector3( 50, -50, 51 )
];

var constructee = this; // constructee = the instance currently being constructed by the StaticTestPentagonPlaneGeometry constructor

// Vertices must always be ordered clockwise, seen from outside the quadPlane

var q = quintuplet;

// populate the vertex array:
constructee.vertices.push(q[0]);
constructee.vertices.push(q[1]);
constructee.vertices.push(q[2]);
constructee.vertices.push(q[3]);
constructee.vertices.push(q[4]);

// previously calculated, and since manually pasted, faceVertexUvs:
var uv0 = new THREE.Vector2(0, 0);
var uv1 = new THREE.Vector2(0, 0.8333333333333334);
var uv2 = new THREE.Vector2(0.8333333333333334, 0.8333333333333334);
var uv3 = new THREE.Vector2(1, 0.4166666666666667);
var uv4 = new THREE.Vector2(0.8333333333333334, 0.8333333333333334);

// construct faces:

var q0 = 0, q1 = 1, q2 = 2, q3 = 3, q4 = 4;

// make plane normal:
var planeVec1 = q[0].clone().sub(q[1]);
var planeVec2 = q[0].clone().sub(q[2]);
var normal = planeVec1.cross(planeVec2).normalize();

// create faces:
var face1 = new THREE.Face3(q0, q4, q3);
constructee.faceVertexUvs[ 0 ].push([ uv0, uv4, uv3 ]); // alt: a d e
face1.normal.copy( normal );
face1.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone(), normal.clone() );

var face2 = new THREE.Face3(q0, q3, q1);
constructee.faceVertexUvs[ 0 ].push([ uv0.clone(), uv3.clone(), uv1 ]);
face2.normal.copy( normal );
face2.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone(), normal.clone() );

var face3 = new THREE.Face3(q1, q3, q2);
constructee.faceVertexUvs[ 0 ].push([ uv1.clone(uv1), uv3.clone(), uv2 ]);
face3.normal.copy( normal );
face3.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone(), normal.clone() );

constructee.faces.push(face1);
constructee.faces.push(face2);
constructee.faces.push(face3);

this.mergeVertices();
};
THREE.StaticTestPentagonPlaneGeometry.prototype = Object.create(THREE.Geometry.prototype);
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.js"></script>
<!-- <script src="three.js"></script> -->
<script src="main.js"></script>
</body>
</html>

最佳答案

您的脸部法线指向错误的方向 (0, 0, -1)。因此,您可以像这样更正正常计算:

normal.z *= -1;

或者作为更通用的解决方案,您可以互换 .cross 函数调用的参数。这段代码:

var normal    = planeVec1.cross(planeVec2).normalize();

然后变成这样:

var normal    = planeVec2.cross(planeVec1).normalize();

最后,您可以简单地要求 Three.js 为您计算面部法线:

constructee.computeFaceNormals ();

您需要删除发射组件才能使其正常工作。

关于javascript - Three.js:自定义几何体不会被纹理化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34532931/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com