如何解决Three.js从3个坐标创建人脸
我已经准备好使用Vue.js
和Three.js
创建加载,渲染和显示STL对象的代码。
我想渲染一个新的面孔来代替我当前正在投射的飞机。我已经找到一种方法来获取覆叠(单击)的脸(aVertex
,bVertex
,cVertex
)的3个顶点。
现在,我想在此位置渲染一个三角形(使用不同的颜色),但是老实说,我不知道该怎么做。我曾尝试使用谷歌搜索,但是还没有运气(我对3d和总体渲染非常陌生)。有人可以朝正确的方向推动我吗?
<template>
<div id="scene-container" ref="sceneContainer" class="scene-container"></div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { STLLoader } from "three/examples/jsm/loaders/STLLoader";
export default {
name: "HelloWorld",data() {
return {
container: null,scene: null,camera: null,controls: null,renderer: null,stats: null,mouse: null,raycaster: null,objName: "testobj",};
},methods: {
init() {
// set container
this.container = this.$refs.sceneContainer;
// add raycaster
this.raycaster = new THREE.Raycaster();
this.mouse = new THREE.Vector2();
const onMouseClick = (event) => {
event.preventDefault();
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// update the picking ray with the camera and mouse position
};
window.addEventListener("mousedown",onMouseClick,false);
// add camera
const fov = 60; // Field of view
const aspect = this.container.clientWidth / this.container.clientHeight;
// const near = 0.1; // the near clipping plane
// const far = 3000; // the far clipping plane
const camera = new THREE.PerspectiveCamera(fov,aspect);
camera.position.set(0,20,75);
this.camera = camera;
// create scene
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xdddddd);
// add lights
const ambientLight = new THREE.HemisphereLight(
0xffffff,// bright sky color
0x222222,// dim ground color
1 // intensity
);
const mainLight = new THREE.DirectionalLight(0xffffff,4.0);
mainLight.position.set(10,10,10);
this.scene.add(ambientLight,mainLight);
let hlight = new THREE.AmbientLight(0xffffff,1.3);
this.scene.add(hlight);
//Add some point lights to simulate real lights
let light = new THREE.PointLight(0xffffff,1,1000);
light.position.set(0,300,500);
this.scene.add(light);
// add controls
this.controls = new OrbitControls(this.camera,this.container);
// create renderer
this.renderer = new THREE.WebGLRenderer({ antialias: true });
this.renderer.setSize(
this.container.clientWidth,this.container.clientHeight
);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.gammaFactor = 2.2;
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.physicallyCorrectLights = true;
document
.getElementById("scene-container")
.appendChild(this.renderer.domElement);
// set aspect ratio to match the new browser window aspect ratio
this.camera.aspect =
this.container.clientWidth / this.container.clientHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(
this.container.clientWidth,this.container.clientHeight
);
let me = this;
let loader = new STLLoader();
let mesh = new THREE.Object3D();
loader.load("/three-assets/RobotExpressive.stl",function (geometry) {
// console.log(geometry);
let material = new THREE.MeshLambertMaterial({
color: 0x1313,wireframe: false,transparent: false,vertexColors: false,});
mesh = new THREE.Mesh(geometry,material);
mesh.rotation.x = -0.5 * Math.PI;
mesh.position.set(0,0);
mesh.name = me.objName;
me.scene.add(mesh);
});
window.addEventListener("resize",onWindowResize,false);
function onWindowResize() {
me.camera.aspect = window.innerWidth / window.innerHeight;
me.camera.updateProjectionMatrix();
me.renderer.setSize(window.innerWidth,window.innerHeight);
}
this.renderer.setAnimationLoop(() => {
this.render();
});
},render() {
this.raycaster.setFromCamera(this.mouse,this.camera);
this.intersects = this.raycaster.intersectObjects(this.scene.children);
// window.addEventListener( 'mousemove',onMouseMove,false );
if (this.intersects.length > 1) {
// this.intersects[0].object.material.color.set(0xff);
for (let i = 0; i < this.intersects.length; i++) {
if (this.intersects[i].object.name == "testobj") {
let positionAttribute = this.intersects[i].object.geometry
.attributes["position"];
let intersection = this.intersects[i];
let aVertex = new THREE.Vector3(
positionAttribute.getX(intersection.face.a),positionAttribute.getY(intersection.face.a),positionAttribute.getZ(intersection.face.a)
);
let bVertex = new THREE.Vector3(
positionAttribute.getX(intersection.face.b),positionAttribute.getY(intersection.face.b),positionAttribute.getZ(intersection.face.b)
);
let cVertex = new THREE.Vector3(
positionAttribute.getX(intersection.face.c),positionAttribute.getY(intersection.face.c),positionAttribute.getZ(intersection.face.c)
);
console.log(aVertex,bVertex,cVertex);
}
}
}
this.renderer.render(this.scene,this.camera);
},},mounted() {
this.init();
},};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
#scene-container {
height: 99.8%;
}
</style>
解决方法
示例(用于使用BufferGeometry拾取网格)
// initital setup:
let lineGeometry = new THREE.BufferGeometry();
let linePositionAttribute = new THREE.BufferAttribute(new Float32Array(4 * 3),3);
lineGeometry.addAttribute('position',linePositionAttribute);
let lineMaterial = new THREE.LineBasicMaterial(
{
color: 0xff0000
});
var intersectionFaceEdge = new THREE.Line(lineGeometry,lineMaterial);
scene.add(intersectionFaceEdge);
// ... on each raycasting:
let face = intersection.face;
let obj = intersection.object;
let positionAttribute = obj.geometry.attributes['position'];
linePositionAttribute.copyAt(0,positionAttribute,face.a);
linePositionAttribute.copyAt(1,face.b);
linePositionAttribute.copyAt(2,face.c);
linePositionAttribute.copyAt(3,face.a);
lineGeometry.applyMatrix(obj.matrixWorld);
我建议使用GPU选择而不是简单的光线投射
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。