threejs 学习之
主要内容: 使用 threejs 创建 20x20 的网格,鼠标移动时,方块跟随移动,点击时在网格任意位置放置方块,按 shift 时,删除当前位置方块。
流程如下:
- 创建网格
- 创建一个与网格同样尺寸的平面
- 创建一个方块 mesh_1 与网格同样的尺寸
- 一个与网格同样的方块 geometry_2 , 不加入 scene 中
- 三个事件:
- 鼠标移动事件,随着鼠标移动,更改 mesh_1 位置,并重新渲染
- 鼠标点击事件,在交点位置,创建新 mesh, 若是相交对象不为 平面,则删除当前对象
- keydown, keyup, 更改是否删除的状态
详细代码如下:
import * as THREE from './build/three.module'
import { stat } from 'fs';
var camera, scene, renderer;
var moveMesh, staticGeo,staticMat, plane;
var objects = [];
var raycaster, mouse;
var isShiftDown = false;
function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(500, 800, 1300);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
// lights
var light = new THREE.AmbientLight(0x606060);
scene.add(light);
// grids
var grid = new THREE.GridHelper(1000, 20);
scene.add(grid);
// plane, 辅助碰撞检测
var planeGeo = new THREE.PlaneBufferGeometry(1000, 1000);
var planMat = new THREE.MeshBasicMaterial({color: 0xffff00, visible : true});
plane = new THREE.Mesh(planeGeo, planMat);
plane.rotateX(-Math.PI /2);
scene.add(plane);
objects.add(plane);
// 射线 raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
// moveCube;
var moveGeo = new THREE.BoxBufferGeometry(50, 50, 50);
var moveMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true });
moveMesh = new THREE.Mesh(moveGeo, moveMaterial);
scene.add(moveMesh);
// static cube
staticGeo = new THREE.BoxBufferGeometry(50, 50, 50);
staticMat = new THREE.MeshLambertMaterial({ color: 0xfeb74c, map: new THREE.TextureLoader().load('textures/square-outline-textured.png') });
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
document.body.addEventListener('mousemove', onDocuementMouseMove, false);
document.body.addEventListener('mousedown', onDocumentMouseDown, false);
document.body.addEventListener('keydown', onDocuementKeyDown, false);
document.body.addEventListener('keyup', onDocuementKeyUp, false);
window.addEventListener('resize', onWindowResize, false);
}
function onDocumentMouseDown(event) {
event.preventDefault();
// 鼠标位置归一化
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 通过摄像机与鼠标更新射线
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
if(intersects.length > 0) {
var intersect = intersects[0];
if (isShiftDown) {
if(intersect.object !== plane) {
scene.remove(intersect.object);
objects.splice(objects.indexOf(intersect.object), 1);
}
}
else
{
var staticMesh = new THREE.Mesh(staticGeo, staticMat);
staticMesh.position.copy(intersect.point).add(intersect.face.normal);
staticMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
scene.add(staticMesh);
objects.push(staticMesh);
}
}
}
function onDocuementMouseMove(event) {
event.preventDefault();
// 鼠标位置归一化
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 通过摄像机与鼠标更新射线
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects);
if(intersects.length > 0) {
intersect = intersects[0];
// 移动位置到目标点
moveMesh.position.copy(intersect.point).add(intersect.face.normal);
// 计算具体方格
moveMesh.position.divideScalar(50).floor().multiplyScalar(50).addScalar(25);
}
render();
}
function onDocuementKeyDown(event) {
switch (event.keyCode) {
case 16: isShiftDown = true; break;
}
}
function onDocuementKeyUp(event) {
switch (event.keyCode) {
case 16: isShiftDown = false; break;
}
}
function onWindowResize() {
camera.aspect = window.innerWidth/ window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function render()
{
renderer.render(scene, camera);
}
threejs 学习之的更多相关文章
- ThreeJS学习6_几何体相关(BufferGeometry)
ThreeJS学习6_几何体相关(BufferGeometry) 使用 BufferGeometry 可以有效减少向 GPU 传输几何体相关数据所需的开销 可以自定义顶点位置, 面片索引, 法向量, ...
- # ThreeJS学习7_裁剪平面(clipping)
ThreeJS学习7_裁剪平面(clipping) 目录 ThreeJS学习7_裁剪平面(clipping) 1. 裁剪平面简介 2. 全局裁剪和局部裁剪 3. 被多个裁剪平面裁剪后 4. 被多个裁剪 ...
- WebGL和ThreeJs学习6--射线法确定3D空间中所选物体
一.在 threejs 中如何确定下图3D空间中鼠标点击位置的 object 对象? 二.射线法确定步骤及代码 //Three.js提供一个射线类Raycaster来拾取场景里面的物体.更方便的使用鼠 ...
- WebGL和ThreeJs学习5--ThreeJS基本功能控件
Threejs 2017年6月6日 15:06 Stats: new Stats();性能监视器,性能测试的方法,引入 Stats.js http://www.hewebgl.com ...
- threejs学习笔记(二)
THREE.WebGLRenderer THREE.Scene THREE.OrthographicCamera正交相机 THREE.PerspectiveCamera透视相机 renderer.se ...
- threejs学习笔记(一)
得到webgl的渲染管线
- threejs和3d各种效果的学习
写给即将开始threejs学习的自己,各种尝试,各种记忆.不要怕,灰色的年华终会过去. 一个技术学习的快慢,以及你的深刻程度,还有你的以后遇到这个东西的时候的反应速度,很大程度上,取决于你的博客的深刻 ...
- 初识webgl--我的webgl学习第一课(基于threeJs)
一,我为什么要学习webgl 一个偶然的机会,在和朋友的聊天过程中,听说了webgl,也许过去也看到过,但是没有特别在意过.原来,JavaScript也可以很好的渲染并在网页上显示三维动画,不用借助插 ...
- gis和threejs的学习资料
*********************************** 基础知识/名词 瓦片/矢量瓦片GeoJson - 绘制GeoJson看数据, geojson规范, 中文版 ********** ...
随机推荐
- JAVA开发第一步 - JDK安装与配置
JDK的安装与环境变量配置是JAVA开发之路的第一步,很多新人在这一步上就卡了很久,浪费了很多时间,甚至有些人就轻易地“从入门到放弃”了.今天我们就来一步步教你如何打倒这第一只拦路虎. 1.JDK下载 ...
- [POI2007]洪水pow 题解
[POI2007]洪水pow 时间限制: 5 Sec 内存限制: 128 MB 题目描述 AKD市处在一个四面环山的谷地里.最近一场大暴雨引发了洪水,AKD市全被水淹没了.Blue Mary,AKD ...
- <float.h>中DBL_TRUE_MIN的定义和作用
搬运自己2016年11月22日于SegmentFault发表的文章.链接:https://segmentfault.com/a/1190000007565915 在学习C Prime Plus的过程中 ...
- 洛谷P2299 Mzc和体委的争夺战 题解
题目 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁. mzc很生气,决定与其决斗,但cat的体 ...
- Node.js socket 双向通信
使用场景: 聊天室:大量数据常驻交互: 技术栈: Node.js, Vue.js || 原生JS 服务端代码: const app = require('http').createServe ...
- MD5的简单用法
非常简单的MD5加密和解密(即用即copy) 点击帮助灯泡引用就可使用 //生成MD5帮助文件文件 public class MD5Help{ ///MD5加密 方法类 public static s ...
- C#3.0新增功能09 LINQ 标准查询运算符 02 查询表达式语法
连载目录 [已更新最新开发文章,点击查看详细] 某些使用更频繁的标准查询运算符具有专用的 C# 语言关键字语法,使用这些语法可以在查询表达式中调用这些运算符. 查询表达式是比基于方法的等效项更具 ...
- [WPF自定义控件库]自定义Expander
1. 前言 上一篇文章介绍了使用Resizer实现Expander简单的动画效果,运行效果也还好,不过只有展开/折叠而缺少了淡入/淡出的动画(毕竟Resizer模仿Expander只是附带的功能).这 ...
- mysqli_query 的定义和用法
定义和用法 mysqli_query() 函数执行某个针对数据库的查询. 语法 mysqli_query(connection,query,resultmode); 参数 描述 connecti ...
- hdu3416+hdu6582(最短路+最大流)
题意 hdu3416: 给一个图,边不能重复选,问有多少个最短路 hdu6582: 给一个图,问最少删除边权多少的边后,最短路长度增加 分析 边不能重复选这个条件可以想到边权为1,跑最大流,所以我们可 ...