用 ThreeJS 替换 space 中的平面
Replace plane in space with ThreeJS
我想将ThreeJS中的一个平面替换为特定的Z值
我创建了一个 shapeBufferGeometry 形状,其中包含包含 x y 和 z 值的 Vector3。
这是我的代码和我得到的。我想让白色平面与水色线的位置相匹配。
下面的代码允许我用我的平面渲染场景中的不同点和它周围的顶点。
我知道我可以使用平移来移动飞机,但我不知道如何正确使用它。我怎么知道应该根据我的矢量值在哪个轴上平移我的几何图形。
<!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, 0, 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, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32),
new THREE.Vector3(199.2353333,7.6714966, 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, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#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
需要通过 ShapeUtils
检查 points
的 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, 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, 0, 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, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32)/*,
new THREE.Vector3(199.2353333,7.6714966, 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, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#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>
我想将ThreeJS中的一个平面替换为特定的Z值
我创建了一个 shapeBufferGeometry 形状,其中包含包含 x y 和 z 值的 Vector3。
这是我的代码和我得到的。我想让白色平面与水色线的位置相匹配。
下面的代码允许我用我的平面渲染场景中的不同点和它周围的顶点。
我知道我可以使用平移来移动飞机,但我不知道如何正确使用它。我怎么知道应该根据我的矢量值在哪个轴上平移我的几何图形。
<!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, 0, 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, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32),
new THREE.Vector3(199.2353333,7.6714966, 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, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#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
需要通过 ShapeUtils
检查 points
的 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, 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, 0, 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, 0, 5),
// new THREE.Vector3(25, 0, 5),
// new THREE.Vector3(25, 0, 15),
// new THREE.Vector3(15, 0, 15),
// new THREE.Vector3(15, 0, 25),
// new THREE.Vector3(5, 0, 25),
// new THREE.Vector3(5, 0, 5)
new THREE.Vector3(199.2353333,7.6714966, 32),
new THREE.Vector3(199.0974316,276.6667291, 32),
new THREE.Vector3(75.2343077,276.6715748, 32),
new THREE.Vector3(75.2343077,232.6714966, 32),
new THREE.Vector3(101.1792999,232.6714966, 32),
new THREE.Vector3(101.1792999,194.6807462, 32),
new THREE.Vector3(75.2343077,194.6714966, 32),
new THREE.Vector3(75.2343077,7.6714966, 32)/*,
new THREE.Vector3(199.2353333,7.6714966, 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, 0, 1); // I already know the normal of xz-plane ;)
scene.add(new THREE.ArrowHelper(normal, new THREE.Vector3(10, 0, 10), 5, 0xffff00)); //yellow
var normalZ = new THREE.Vector3(0, 0, 1); // base normal of xy-plane
scene.add(new THREE.ArrowHelper(normalZ, scene.position, 5,'#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>