gpt4 book ai didi

Three.js - 从另一个网格的某些面/顶点创建新网格

转载 作者:行者123 更新时间:2023-12-03 01:04:56 24 4
gpt4 key购买 nike

我已经在一个特定的 Three.js 问题上苦苦挣扎了好几天,但我找不到任何方法来解决它。这是我的情况:

1) 我有一个 float 网格,由几个三角形面形成。该网格是在使用 getAttribute('position') 获取其顶点和面后,根据加载器返回的几何图形创建的:How to smooth mesh triangles in STL loaded BufferGeometry

enter image description here

2)我现在想做的是将底面“投影”到地板上。

enter image description here

3)稍后,添加这个新面后,创建填充两个面的 3 个顶点之间空间的网格。

enter image description here

我在第 2 步中已经遇到了麻烦...要创建一个新面,我应该将其 3 个顶点添加到 Geometry.vertices 中。我做到了,克隆原始的面顶点。我使用 Geometry.vertices.push() 结果来了解它们的新索引,然后使用该索引 (-1) 最终创建新面。但它的形状很奇怪,位置和大小也很奇怪。我认为我没有正确理解世界/场景/矢量位置等价理论:P

我尝试应用这个,但没有成功: How to get the absolute position of a vertex in three.js? Converting World coordinates to Screen coordinates in Three.js using Projection http://barkofthebyte.azurewebsites.net/post/2014/05/05/three-js-projecting-mouse-clicks-to-a-3d-scene-how-to-do-it-and-how-it-works

我发现,如果我直接克隆完整的原始面并简单地将其添加到网格中,则会添加该面,但位置相同,因此我无法更改其顶点以将其放置在地板上(或者至少没有修改原始面顶点!)。我的意思是,我可以更改它们的 x、y、z 属性,但它们的尺寸非常小,与原始网格尺寸不匹配。

有人可以帮我正确理解这个概念吗?

编辑:源代码

            // Create geometry
var geo = new THREE.Geometry();
var geofaces = [];
var geovertices = [];

original_geometry.updateMatrixWorld();

for(var index in original_geometry.faces){
// Get original face vertexNormals to know its 3 vertices
var face = original_geometry[index];
var vertexNormals = face.vertexNormals;

// Create 3 new vertices, add it to the array and then create a new face using the vertices indexes
var vertexIndexes = [null, null, null];
for (var i = 0, l = vertexNormals.length; i < l; i++) {
var vectorClone = vertexNormals[i].clone();
vectorClone.applyMatrix4( original_geometry.matrixWorld );
//vectorClone.unproject(camera); // JUST TESTING
//vectorClone.normalize(); // JUST TESTING

var vector = new THREE.Vector3(vectorClone.x, vectorClone.z, vectorClone.y)
//vector.normalize(); // JUST TESTING
//vector.project(camera); // JUST TESTING
//vector.unproject(camera); // JUST TESTING
vertexIndexes[i] = geovertices.push( vector ) - 1;
}
var newFace = new THREE.Face3( vertexIndexes[0], vertexIndexes[1], vertexIndexes[2] );
geofaces.push(newFace);
}

// Assign filled arrays to the geometry
geo.faces = geofaces;
geo.vertices = geovertices;

geo.mergeVertices();
geo.computeVertexNormals();
geo.computeFaceNormals();

// Create a new mesh with resulting geometry and add it to scene (in this case, to the original mesh to keep the positions)
new_mesh = new THREE.Mesh( geo, new THREE.MeshFaceMaterial(material) ); // material is defined elsewhere
new_mesh.position.set(0, -100, 0);
original_mesh.add( new_mesh );

最佳答案

我创建了一个完全可操作的 JSFiddle 来尝试一些事情并更清楚地看到问题。使用这个 STL(比我本地的示例小),我什至看不到添加到场景中的严重克隆的面孔。也许它们太小或失焦。

看一下calculateProjectedMesh() 函数,这里是我尝试克隆和放置底面的地方(已检测到,因为它们具有不同的 Material 索引):

JSFiddle: https://jsfiddle.net/tc39sgo1/

var container;
var stlPath = 'https://dl.dropboxusercontent.com/s/p1xp4lhy4wxmf19/Handle_Tab_floating.STL';

var camera, controls, scene, renderer, model;

var mouseX = 0,
mouseY = 0;

var test = true;
var meshPlane = null, meshStl = null, meshCube = null, meshHang = null;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

/*THREE.FrontSide = 0;
THREE.BackSide = 1;
THREE.DoubleSide = 2;*/

var materials = [];
materials.push( new THREE.MeshPhongMaterial({color : 0x00FF00, side:0, shading: THREE.FlatShading, transparent: true, opacity: 0.9, overdraw : true, wireframe: false}) );
materials.push( new THREE.MeshPhongMaterial({color : 0xFF0000, transparent: true, opacity: 0.8, side:0, shading: THREE.FlatShading, overdraw : true, metal: false, wireframe: false}) );
materials.push( new THREE.MeshPhongMaterial({color : 0x0000FF, side:2, shading: THREE.FlatShading, overdraw : true, metal: false, wireframe: false}) );
var lineMaterial = new THREE.LineBasicMaterial({ color: 0x0000ff, transparent: true, opacity: 0.05 });

init();
animate();

function webglAvailable() {
try {
var canvas = document.createElement('canvas');
return !!(window.WebGLRenderingContext && (
canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
} catch (e) {
return false;
}
}

function init() {
container = document.createElement('div');
document.body.appendChild(container);

camera = new THREE.PerspectiveCamera(25, window.innerWidth / window.innerHeight, 0.1, 100000000);
camera.position.x = 1500;
camera.position.z = -2000;
camera.position.y = 1000;

controls = new THREE.OrbitControls(camera);

// scene
scene = new THREE.Scene();

var ambient = new THREE.AmbientLight(0x101030); //0x101030
scene.add(ambient);

var directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.position.set(0, 3, 0).normalize();
scene.add(directionalLight);

var directionalLight = new THREE.DirectionalLight(0xffffff, 2);
directionalLight.position.set(0, 1, -2).normalize();
scene.add(directionalLight);

if (webglAvailable()) {
renderer = new THREE.WebGLRenderer();
} else {
renderer = new THREE.CanvasRenderer();
}
renderer.setClearColor( 0xCDCDCD, 1 );

// renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);

document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);

createPlane(500, 500);
createCube(500);
loadStl();
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize(window.innerWidth, window.innerHeight);
}

function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}

function animate() {
requestAnimationFrame(animate);
render();
}

function render() {
renderer.render(scene, camera);
}

function createPlane(width, height) {
var planegeometry = new THREE.PlaneBufferGeometry(width, height, 0, 0);
var material = new THREE.MeshLambertMaterial({
color: 0xFFFFFF,
side: THREE.DoubleSide
});
planegeometry.computeBoundingBox();
planegeometry.center();

meshPlane = new THREE.Mesh(planegeometry, material);
meshPlane.rotation.x = 90 * (Math.PI/180);
//meshPlane.position.y = -height/2;
scene.add(meshPlane);
}

function createCube(size) {
var geometry = new THREE.BoxGeometry( size, size, size );
geometry.computeFaceNormals();
geometry.mergeVertices();
geometry.computeVertexNormals();
geometry.center();

var material = new THREE.MeshPhongMaterial({
color: 0xFF0000,
opacity: 0.04,
transparent: true,
wireframe: true,
side: THREE.DoubleSide
});
meshCube = new THREE.Mesh(geometry, material);
meshCube.position.y = size/2;
scene.add(meshCube);
}

function loadStl() {
var loader = new THREE.STLLoader();
loader.load( stlPath, function ( geometry ) {
// Convert BufferGeometry to Geometry
var geometry = new THREE.Geometry().fromBufferGeometry( geometry );

geometry.computeBoundingBox();
geometry.computeVertexNormals();
geometry.center();

var faces = geometry.faces;
for(var index in faces){
var face = faces[index];
var faceNormal = face.normal;
var axis = new THREE.Vector3(0,-1,0);
var angle = Math.acos(axis.dot(faceNormal));
var angleReal = (angle / (Math.PI/180));
if(angleReal <= 70){
face.materialIndex = 1;
}
else{
face.materialIndex = 0;
}
}

geometry.computeFaceNormals();
geometry.computeVertexNormals();

meshStl = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
meshStl.position.x = 0;
meshStl.position.y = 400;
scene.add( meshStl );

// Once loaded, calculate projections mesh
calculateProjectedMesh();
});
}

function calculateProjectedMesh(){
var geometry = meshStl.geometry;
var faces = geometry.faces;
var vertices = geometry.vertices;

var geometry_projected = new THREE.Geometry();
var faces_projected = [];
var vertices_projected = [];

meshStl.updateMatrixWorld();

for(var index in faces){
var face = faces[index];

// This are the faces
if(face.materialIndex == 1){

var vertexIndexes = [face.a, face.b, face.c];
for (var i = 0, l = vertexIndexes.length; i < l; i++) {
var relatedVertice = vertices[ vertexIndexes[i] ];
var vectorClone = relatedVertice.clone();
console.warn(vectorClone);
vectorClone.applyMatrix4( meshStl.matrixWorld );

////////////////////////////////////////////////////////////////
// TEST: draw line
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(vectorClone.x, vectorClone.y, vectorClone.z));
//geometry.vertices.push(new THREE.Vector3(vectorClone.x, vectorClone.y, vectorClone.z));
geometry.vertices.push(new THREE.Vector3(vectorClone.x, meshPlane.position.y, vectorClone.z));
var line = new THREE.Line(geometry, lineMaterial);
scene.add(line);
console.log("line added");
////////////////////////////////////////////////////////////////

vectorClone.y = 0;
var vector = new THREE.Vector3(vectorClone.x, vectorClone.y, vectorClone.z);
vertexIndexes[i] = vertices_projected.push( vector ) - 1;
}
var newFace = new THREE.Face3( vertexIndexes[0], vertexIndexes[1], vertexIndexes[2] );
newFace.materialIndex = 2;
faces_projected.push(newFace);
}
}
geometry_projected.faces = faces_projected;
geometry_projected.vertices = vertices_projected;
geometry_projected.mergeVertices();
console.info(geometry_projected);

meshHang = new THREE.Mesh(geometry_projected, new THREE.MeshFaceMaterial(materials));
var newY = -(2 * meshStl.position.y) + 0;
var newY = -meshStl.position.y;
meshHang.position.set(0, newY, 0);
meshStl.add( meshHang );
}

编辑:终于!!我得到了它!要克隆原始面,我必须使用“a”、“b”和“c”属性访问它们的 3 个原始顶点,这些属性是引用原始几何图形的“vertices”数组中的 Vector3 实例的索引。

我克隆了 3 个顶点,将 Z 位置展平为零,使用它们的新索引创建新面并将其添加到投影网格(蓝色)。

我还添加了线条作为两张脸之间的视觉结合。现在我已准备好执行第 3 步,但我认为这已经足够复杂,足以结束这个问题。

感谢您提供更新MatrixWorld的线索!实现我的目标至关重要;)

关于Three.js - 从另一个网格的某些面/顶点创建新网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35257728/

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