如何解决用 ThreeJS 替换空间中的平面
我想将 ThreeJS 中的平面替换为特定的 Z 值。
我创建了一个 shapeBufferGeometry,其形状包含包含 x y 和 z 值的 Vector3s。
这是我的代码和我得到的。我希望白色平面与浅绿色线的位置相匹配。
下面的代码允许我用我的平面渲染场景中的不同点和它周围的顶点。
我知道我可以使用 translate 来移动飞机,但我不知道如何正确使用它。以及我如何知道应该根据我的矢量值在哪个轴上平移我的几何体。
<!DOCTYPE html>
<html>
<head>
<Meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<canvas id="c" width="800" height="500"></canvas>
<script>
</script>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,1,2000);
camera.position.set(0,20,40);
camera.lookAt(scene.position);
var renderer = new THREE.Webglrenderer({
antialias: true
});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new OrbitControls(camera,renderer.domElement);
controls.target = new THREE.Vector3(10,10);
controls.update();
var grid = new THREE.GridHelper(50,50,0x808080,0x202020); // xy-grid
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);
var points = [ // all of them are on the xz-plane
// new THREE.Vector3(5,5),// new THREE.Vector3(25,15),// new THREE.Vector3(15,25),// new THREE.Vector3(5,5)
new THREE.Vector3(199.2353333,7.6714966,32),new THREE.Vector3(199.0974316,276.6667291,new THREE.Vector3(75.2343077,276.6715748,232.6714966,new THREE.Vector3(101.1792999,194.6807462,194.6714966,new THREE.Vector3(199.2353333,32)
]
var geom = new THREE.BufferGeometry().setFromPoints(points);
var pointsObj = new THREE.Points(geom,new THREE.PointsMaterial({
color: "red"
}));
scene.add(pointsObj);
var line = new THREE.LineLoop(geom,new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(line);
// normals
var normal = new THREE.Vector3(0,1); // I already kNow the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal,new THREE.Vector3(10,10),5,0xffff00)); //yellow
var normalZ = new THREE.Vector3(0,1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ,scene.position,'#FF001F' )); // aqua
// 1 quaternions
var quaternion = new THREE.Quaternion().setFromunitVectors(normal,normalZ);
var quaternionBack = new THREE.Quaternion().setFromunitVectors(normalZ,normal);
// 2 make it parallel to xy-plane
points.forEach(p => {
p.applyQuaternion(quaternion)
});
// 3 create shape and shapeGeometry
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
shapeGeom.computeFacenormals();
shapeGeom.computeVertexnormals();
// 4 put our points back to their origins
points.forEach(p => {
p.applyQuaternion(quaternionBack)
});
// 5 assign points to .vertices
shapeGeom.vertices = points;
var shapeMesh = new THREE.Mesh(shapeGeom,new THREE.MeshBasicMaterial({
color: '#FF001F ',side: THREE.DoubleSide
}));
scene.add(shapeMesh);
// scene.add( new THREE.FacenormalsHelper( shapeMesh ) );
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene,camera);
}
</script>
</body>
</html>
解决方法
不需要添加最后一个点来闭合轮廓。
并且您的步骤 // 5 assign points to .vertices
需要通过 points
检查 ShapeUtils
的 CCW。将 Vector3 数组分配给缓冲区几何的 .vertices
是无用的,因为该类型的几何没有该属性,因此您正在使用缓冲区属性。调用 shapeGeom.computeFaceNormals();
也是没用的。
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/controls/OrbitControls.js';
import {GUI} from 'https://threejsfundamentals.org/threejs/../3rdparty/dat.gui.module.js';
import { ConvexGeometry } from 'https://threejsfundamentals.org/threejs/resources/threejs/r127/examples/jsm/geometries/ConvexGeometry.js'
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60,window.innerWidth / window.innerHeight,1,2000);
camera.position.set(0,20,40).setLength(500).add(new THREE.Vector3(150,150,0));
camera.lookAt(150,0);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new OrbitControls(camera,renderer.domElement);
controls.target = new THREE.Vector3(10,10);
controls.update();
var grid = new THREE.GridHelper(50,50,0x808080,0x202020); // xy-grid
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);
var points = [ // all of them are on the xz-plane
// new THREE.Vector3(5,5),// new THREE.Vector3(25,15),// new THREE.Vector3(15,25),// new THREE.Vector3(5,5)
new THREE.Vector3(199.2353333,7.6714966,32),new THREE.Vector3(199.0974316,276.6667291,new THREE.Vector3(75.2343077,276.6715748,232.6714966,new THREE.Vector3(101.1792999,194.6807462,194.6714966,32)/*,new THREE.Vector3(199.2353333,32)*/
]
var geom = new THREE.BufferGeometry().setFromPoints(points);
var pointsObj = new THREE.Points(geom,new THREE.PointsMaterial({
color: "red"
}));
scene.add(pointsObj);
var line = new THREE.LineLoop(geom,new THREE.LineBasicMaterial({
color: "aqua"
}));
scene.add(line);
// normals
var normal = new THREE.Vector3(0,1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal,new THREE.Vector3(10,10),5,0xffff00)); //yellow
var normalZ = new THREE.Vector3(0,1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ,scene.position,'#FF001F' )); // aqua
// 1 quaternions
var quaternion = new THREE.Quaternion().setFromUnitVectors(normal,normalZ);
var quaternionBack = new THREE.Quaternion().setFromUnitVectors(normalZ,normal);
// 2 make it parallel to xy-plane
points.forEach(p => {
p.applyQuaternion(quaternion)
});
// 3 create shape and shapeGeometry
var shape = new THREE.Shape(points);
var shapeGeom = new THREE.ShapeBufferGeometry(shape);
shapeGeom.computeFaceNormals();
shapeGeom.computeVertexNormals();
// 4 put our points back to their origins
points.forEach(p => {
p.applyQuaternion(quaternionBack)
});
// 5 assign points to .vertices
if (!THREE.ShapeUtils.isClockWise(points)) points.reverse(); // CCW order
points.forEach((p,idx) => {
shapeGeom.attributes.position.setXYZ(idx,p.x,p.y,p.z);
});
console.log(points.length,shapeGeom.attributes.position.count);
var shapeMesh = new THREE.Mesh(shapeGeom,new THREE.MeshBasicMaterial({
color: "#FF001F",//side: THREE.DoubleSide
}));
scene.add(shapeMesh);
// scene.add( new THREE.FaceNormalsHelper( shapeMesh ) );
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene,camera);
}
</script>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。