three.js 叉乘判断物体在人前左,前右,后左、后右

效果:

代码:

<template><div><el-container><el-main><div class="box-card-left"><div id="threejs"></div><div style="padding: 10px;text-align: left;">叉乘判断物体在人左前、右前还是左后,右后方向<div style="margin: 10px;"><el-button @click="judge">开始判断</el-button><div v-for="(item,index) in this.positon_arr" :key="index" style="line-height: 28px;">{{ item }}</div></div></div></div></el-main></el-container></div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import {CSS3DSprite,CSS3DRenderer,
} from "three/examples/jsm/renderers/CSS3DRenderer.js";
export default {data() {return {scene: null, // 场景对象camera: null, // 相机对象group: null, // 组对象person: null, // 人对象renderer: null, // 渲染器对象css3DRenderer: null, // 渲染器对象a: new this.$three.Vector3(0, 0, 1),// b: new this.$three.Vector3(30, 0, 30),meshPosition:[],positon_arr:[],};},created() {},mounted() {this.name = this.$route.query.name;this.init();},methods: {goBack() {this.$router.go(-1);},/*** 如何判断物体是在人的前方还是后方* 思路:借助两个单位向量的点乘结果来判断的;*/init() {// 创建场景对象this.scene = new this.$three.Scene();// 创建辅助坐标轴对象const axesHelper = new this.$three.AxesHelper(10);this.scene.add(axesHelper);// 创建环境光对象const ambientLight = new this.$three.AmbientLight(0xffffff, 10);this.scene.add(ambientLight);// 创建相机对象this.camera = new this.$three.PerspectiveCamera(60,1,0.01,2000);this.camera.position.set(-4,5,-5);this.camera.lookAt(0,0,0);this.css3DRenderer = new CSS3DRenderer();this.css3DRenderer.setSize(1000,800);this.css3DRenderer.render(this.scene, this.camera);this.css3DRenderer.domElement.style.position = 'absolute';this.css3DRenderer.domElement.style.top = 0;this.css3DRenderer.domElement.style.pointerEvents = 'none';this.css3DRenderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.css3DRenderer.domElement);this.createMesh(0xffaadd, new this.$three.Vector3(3,0,3), '球1');this.createMesh(0xddcc11, new this.$three.Vector3(-3,0,3), '球2');this.createMesh(0x1199dd, new this.$three.Vector3(3,0,-3), '球3');this.createMesh(0xbbaadd, new this.$three.Vector3(-3,0,-3), '球4');this.createArrow(this.a);// 创建渲染器对象this.renderer = new this.$three.WebGLRenderer();this.renderer.setSize(1000,800);// 创建gltfLoader加载器对象const gltfLoader = new GLTFLoader();gltfLoader.load("/models/gltf/person2/scene.gltf", gltf => {console.log(gltf);gltf.scene.children[0].scale.set(2,2,2);this.scene.add(gltf.scene);this.renderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.renderer.domElement);const controls = new OrbitControls(this.camera, this.renderer.domElement);controls.addEventListener("change", () => {this.renderer.render(this.scene, this.camera);})this.renderFun();})},// 创建箭头用于显示人前方的单位向量 this.acreateArrow(dir, l=2, color=0xffffff) {let arrow = new this.$three.ArrowHelper(dir, new this.$three.Vector3(0,0,0), l, color);this.scene.add(arrow);},// 创建模型的方法createMesh(color, position, name) {// 创建球缓冲几何体const geometry = new this.$three.SphereGeometry(1,32,16);// 创建材质对象const material = new this.$three.MeshBasicMaterial({color: color});const mesh = new this.$three.Mesh(geometry, material);mesh.name = name;mesh.position.set(position.x, position.y, position.z);this.meshPosition.push({name: name, position: mesh.position});let dom = this.createDom(name);mesh.add(dom);this.scene.add(mesh);this.createArrow(mesh.position, mesh.position.length()*0.7,color);},createDom(name) {let dom = document.createElement("div");dom.innerText = name;let css3DObject = new CSS3DSprite(dom);css3DObject.scale.set(0.03,0.03,0.03);return css3DObject;},renderFun() {this.css3DRenderer.render(this.scene, this.camera);requestAnimationFrame(this.renderFun); // 一定要设置这一句,否则,不渲染},/*** 人前方的单位向量a 与 物体到原点的向量m 叉乘后,* 可以通过叉乘结果的y值判断物体是在人左侧还是右侧* */judge() {if(this.meshPosition) {this.positon_arr = [];this.meshPosition.forEach(item => {let c = this.a.clone().cross(item.position);let p_str = "";if(c.y > 0) {p_str += item.name +"在人左";p_str += this.dotDeg(item.position);} else {p_str += item.name +"在人右";p_str += this.dotDeg(item.position);}this.positon_arr.push(p_str);})}},// 点乘判断两个向量的夹角dotDeg(meshPosition) {let c = this.a.clone().dot(meshPosition.clone().normalize());let cos = Math.acos(c);let deg = this.$three.MathUtils.radToDeg(cos);console.log(deg);let pos = "";if(deg > 0 && deg < 90) {pos = "前";} else if (deg == 90) {pos = "平行";} else {pos = "后";}return pos;}},
};
</script>
<style lang="less" scoped>
.box-card-left {display: flex;align-items: flex-start;flex-direction: row;width: 100%;.box-right {img {width: 500px;user-select: none;}}
}
</style>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/505259.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合SpringSecurity

什么是SpringSecurity&#xff1f; Spring Security是Spring提供的一套web的应用安全性的完整解决方案。 SpringSecurity采用责任式链的设计模式&#xff0c;它的核心是一组过滤器链。 主要包括&#xff1a; 认证&#xff08;Authentication&#xff09;&#xff1a;什么是…

【递归】【回溯】Leetcode 112. 路径总和 113. 路径总和 II

【递归】【回溯】Leetcode 112. 路径总和 113. 路径总和 II 112. 路径总和解法&#xff1a;递归 有递归就有回溯 记得return正确的返回上去 113. 路径总和 II解法 递归 如果需要搜索整棵二叉树&#xff0c;那么递归函数就不要返回值 如果要搜索其中一条符合条件的路径&#xff…

vue中将某个不太规则的json转成对象,或者将对象转成json字符串

vue中将某个不太规则的json转成对象&#xff0c;或者将对象转成json字符串 以我自己做的项目某个不规则的json为例 将json对象转成json字符串&#xff1a; JSON.stringify(jsonData); 将不规则json字符串转成对象并获取对应的属性的值&#xff1a; JSON.parse(jsonData).Name…

详细了解C++中的namespace命名空间

键盘敲烂&#xff0c;月薪过万&#xff0c;同学们&#xff0c;加油呀&#xff01; 目录 键盘敲烂&#xff0c;月薪过万&#xff0c;同学们&#xff0c;加油呀&#xff01; 一、命名空间的理解 二、&#xff1a;&#xff1a;作用域运算符 三、命名空间&#xff08;namespace&…

双周回顾#007 - 前端与后端

前端的问题不是难&#xff0c;而是它面对最终用户。只要用户的喜好和口味发生变化&#xff0c;前端就必须跟上。 这导致前端不得不快速变化&#xff0c;因为用户的口味正在越来越快地改变。 后端不需要面对最终用户&#xff0c;需要解决的都是一些经典的计算机科学问题&#…

第16章-DNS

目录 1. 域名 1.1 产生背景 1.2 概述 1.3 域名的树形层次化结构 2. DNS 2.1 概述 2.2 工作机制 3. DNS查询模式 3.1 递归查询&#xff1a; 3.2 迭代查询&#xff1a; 4. 相关知识点 4.1 集中式DNS 4.2 国内通用DNS 4.3 配置DNS代理 1. 域名 1.1 产生背景 ① IP…

DataIntegrityViolationException异常产生原因及解决方案

DataIntegrityViolationException异常产生原因及解决方案 01 异常的发生场景 在我新写了一个接口之后出现的 //org.springframework.dao.DataIntegrityViolationException日志报错的意思是参数设置了一个错误的值 02 异常的产生及其原因 我最开始认为是MySQL数据库表设计…

JMeter性能测试基本过程及示例

jmeter 为性能测试提供了一下特色&#xff1a; jmeter 可以对测试静态资源&#xff08;例如 js、html 等&#xff09;以及动态资源&#xff08;例如 php、jsp、ajax 等等&#xff09;进行性能测试 jmeter 可以挖掘出系统最大能处理的并发用户数 jmeter 提供了一系列各种形式的…

Acwing 每日一题 空调 差分 贪心

&#x1f468;‍&#x1f3eb; 空调 &#x1f468;‍&#x1f3eb; 参考题解 import java.util.Scanner;public class Main {static int N (int) 1e5 10;static int[] a new int[N];static int n;public static void main(String[] args){Scanner sc new Scanner(System.…

07 编译器

目录 编译过程编译器查看详解函数库自动化构建工具进度条程序 1. 编译过程 预处理: a. 去注释 b.宏替换 c.头文件展开 d.条件编译 编译: 汇编 汇编: 可重定向二进制目标文件 链接: 链接多个.o, .obj合并形成一个可执行exe gcc编译c程序, g编译c程序 2. 编译器查看 输入gcc …

ABAP - SALV教程04 添加状态栏

CL_SALV_TABLE中提供了 GET_FUNCTIONS方法.GET_FUNCTIONS方法返回的是一个CL_SALV_FUNCTIONS_LIST类型的实例对象. 类CL_SALV_FUNCTIONS_LIST两个方法(SET_ALL、SET_DEFAULT)可以添加标准状态栏 实现步骤: 定义SET_STATUS私有方法. PRIVATE SECTION.METHODS:set_status CHA…

Revit-二开之创建墙-(6)

Revit API窗间墙 protected override Result OnExecute(ExternalCommandData commandData, ref string message, ElementSet elements) {try{// 获取当前活动的文档