Threejs从入门到入门
前言
threejs官网:https://threejs.org/
github各个版本:https://github.com/mrdoob/three.js/tags
版本更迭很快,我用的时候还是r90秒秒钟r91出来了
刚入门的时候可以看看这个教程:http://www.hewebgl.com/article/articledir/1
初级教程是免费的,中高级是收费的,写的不是很枯燥,也不用跟着敲代码,有个相机,渲染器,场景,光源的概念就可以了。它适配的版本是比较旧的,我当时用新版本跟着写有些demo无法完成,新手更谈不上根据版本之间的差别找到问题,慢慢就失去兴趣了。
我的这个教程用的是r90版本,它有个比较好的地方是,当你使用高版本的threejs却使用低版本的语法时,浏览器console会有警告告诉你新的写法是什么样的。
我的DEMO下载
演示地址: 太穷了,带宽很小,加载卡顿请谅解(哭泣)
相机转动做的比较仓促没有考虑细节,导致鼠标拖拽或是放大缩小卡顿,emmm小问题暂时不想改了
https://www.hugeoyzy.top/threejs/src/demo1.html
https://www.hugeoyzy.top/threejs/src/demo2.html
下载:https://download.csdn.net/download/u010588262/10288776
开发工具
因为我主要是做java开发,所以就用idea了,因为idea写js也是有提示的,所以还挺方便,就建个Static Web项目就可以了: 
我的项目结构是这样的: 
调试需要做两点配置:
1. 浏览器路径: 
浏览器启动参数,因为threejs要加载本地的图片文件,obj文件之类的,看网上教程都说是不允许的,要部署在apache和tomcat之类的,我没试,看到说可以加启动参数就加了,调试没问题
–allow-file-access-from-files 
调试的时候就在html文件上鼠标移到右上角,点击相应的浏览器图标就可以了
如果修改了html的话直接保存文件在浏览器刷新就能看到效果了,但是修改了js的话就要关闭页面重新点击浏览器图标。
官方DEMO(肥肠重要)
我入门最快的时候就是找到了官方DEMO之后
一个是:http://stemkoski.github.io/Three.js/#hello-world
这里的demo很入门,很好理解,页面最上方有github地址,可以去下载。唯一不好的是使用的版本很老。r60版本的,不过对于初学者一开始最重要的是理解大概的使用,不用纠结于最新版本。
还有一个是:https://threejs.org/examples/#webgl_animation_cloth
这里的demo相比第一个是比较高大上的,源代码就在你下载的threejs包里的examples目录下
代码讲解
这一块针对初学者中的初学者了,只要看过前言中的初级教程之后再看我的demo应该没问题了,demo的代码也比较整洁。
demo中的css,fonts,images和objs基本都是从官方demo中搞过来的,页面上引用的js分别是什么作用也做了注释了:
util.js是我把公用的东西放在一起了,要看懂util.js需要对threejs基本的组件有一些了解。
threejs的三围坐标是这样的,比如你现在对着电脑屏幕吧,把你屏幕的左下角想象成二维坐标原点,那往右就是x正方向,网上就是y正方向,从屏幕往外直盖脸的就是z正方向了。
最上面的src()是用来初始化场景,相机和渲染器的,最开始的textureLoader = new THREE.TextureLoader();是用来加载图片材质的,在大多数教程里用的都是ImageUtils来加载的,这个是新版本的改动,我说一下我对这仨玩意儿的理解吧
场景:就是一个黑盒子呗,把你要展示的东西全往里面装,地板啊,天花板啊,盒子啊,球啊,货架啊,三D字体啊全塞进去。为什么是黑盒子?因为你看不见它,也不看不见塞进去的东西。场景的初始化很简答就一句话scene = new THREE.Scene();
相机:相机可以在任意的位置,任意的角度”拍摄”黑盒子里的场景,相机的初始化稍微复杂一些。
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = , ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT, NEAR = 0.1, FAR = ;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
scene.add(camera);
camera.position.set(, , );
cameraRadius = Math.sqrt(camera.position.x * camera.position.x + camera.position.z * camera.position.z);
camera.up.set(, , );
camera.lookAt(new THREE.Vector3(, , ));
关于相机比较难理解的是position,up和lookAt的关系。你可看看这个视频http://www.hewebgl.com/video/2,虽然我看完了也没怎么看懂。
尝试解释一下吧。
现在,把你的手机打开摄像头,正对着屏幕,想象它就像单反一样上面右边有个快门,这就是threejs中相机的初始方向,就是从z轴正方向看向z轴负方向。position是什么意思呢,现在把手机往右平移,意思是position.x在增加。lookAt也很容易,就是相机往哪儿拍呗。比较难理解的是up,好现在把手机位置固定,只能旋转哦,也就是说position固定了,好了现在把手机旋转镜头对着屏幕左下角,也就是咱们的三维坐标原点,也就是说lookAt也固定了。up的作用就是你现在可以旋转手机了,保持镜头对着屏幕左下角的方向,手机的中心点位置不要变,旋转手机,拍出来的画面就会是正的,或者斜着的,或者上下倒过来的。随着你旋转手机快门的朝向也在变是吧,默认快门是对着Y轴正方向的,也就是(0,1,0)如果把手机颠倒,up就变成了(0,-1,0),拍出来的画面也就是上下颠倒的,因为你虽然可以倒着手机拍,但是看照片的时候得把手机正过来看,画面也就是反的咯。
渲染器
可以看到相机的初始化过程中没有与场景绑定,他们俩就像在两个平行世界一样,看似在一起,其实没在一起,需要用渲染器把他们俩关联起来,这样,相机就拍到了场景里的东西,再通过渲染器展示在浏览器上被我们看到了。Decetor是通过Detector.js引入进来的东西,用于判断浏览器兼容性的。
if (Detector.webgl)
renderer = new THREE.WebGLRenderer({antialias: true});
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
container = document.getElementById('ThreeJS');
container.appendChild(renderer.domElement);
以地板为例怎么搞一个东西放在场景里,CSDN的代码注释没有这么详细,写博客的时候加的,对不住只下资源不看文章的朋友。PlaneGeometry就是一个平面,SphereGeometry就是一个球,CubeGeometry就是一个立方体…….感兴趣的可以百度多了解一下其他组件。材质就是各种Material,也有很多种,有受光照影响的,有不受光照影响的。把组件和材质组合起来就是一个完整的物体啦,就是THREE.Mesh这个方法把他们组合起来,第一个参数是组件,第二个参数是材质,材质还可以传入一个数组,你可能觉得设置多个有啥意义啊一个盖住一个的,材质是可以设置透明度的,明白了吧。
function addfloor() {
// 加载图片作为地板材质
var floorTexture = textureLoader.load('images/checkerboard.jpg');
// 沿x方向和Y方向都重复填充
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
// x方向和y方向各重复几次,不理解的话改改这个值看看效果就知道了
floorTexture.repeat.set(, );
// 将材质包装成表面材料,设置正反两面都要铺上
var floorMaterial = new THREE.MeshBasicMaterial({map: floorTexture, side: THREE.DoubleSide});
// 平面对象
var floorGeometry = new THREE.PlaneGeometry(, , , );
// 把对象和材料包装成Mesh
floor = new THREE.Mesh(floorGeometry, floorMaterial);
// 设置位置放入场景啦
floor.position.y = -0.5;
floor.rotation.x = Math.PI / ;
scene.add(floor);
}
others()方法里是一些可有可无的辅助,看注释就明白了。
animate()就是开始持续渲染,渲染就是通过renderer.render(scene, camera);把渲染器搞到的东西放在浏览器上给你看,持续渲染就是通过重复调用方法本身可以实现动画的效果requestAnimationFrame(animate);,除了这两个东西还调用了update();方法,update方法里就是慢慢的移动组件或者刷新其他需要更新得组件。requestAnimationFrame方法是比较平滑的动画,我之前想用Tween.js实现相机转动的效果,很卡顿,不流畅。
woodycube()就是封装了获得木箱,因为两个demo里都用到了木头箱子。
后面有空再说一下demo中的代码
2018年3月16日
更新了一下util.js中的代码,把鼠标点击选中事件和getMeshed方法从demo2中移到util里面了
点击事件
document.addEventListener("mousedown", onDocumentMouseDown, false);
function onDocumentMouseDown(e) {
e.preventDefault();
// 点击页面时停止相机旋转,因为相机旋转的时候无法选中物体,这个问题没有解决,有点麻烦
rotate = false;
//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义
var mouse = {};
mouse.x = (e.clientX / window.innerWidth) * - ;
mouse.y = -(e.clientY / window.innerHeight) * + ;
//新建一个三维单位向量 假设z方向就是0.5
//根据照相机,把这个向量转换到视点坐标系
var vector = new THREE.Vector3(mouse.x, mouse.y, 0.5).unproject(camera);
var sub = vector.sub(camera.position);=
var param2 = sub.normalize();
var raycaster = new THREE.Raycaster(camera.position, param2);
//射线和模型求交,选中一系列直线,getMeshs方法用于获得场景中可以被选中的所有Mesh
var intersects = raycaster.intersectObjects(getMeshs());
if (intersects.length > ) {
// outlineMesh是物体边框组件,每次只会有一个物体被选中,就把这个东西定义为全局的
// 每次选中另一个物体之前先删除,相当于取消前一个物体的选中
scene.remove(outlineMesh);
//选中第一个射线相交的物体
var SELECTED = intersects[].object;
var outlineMaterial2 = new THREE.MeshBasicMaterial({color: 0x00ff00, side: THREE.BackSide});
outlineMesh = new THREE.Mesh(SELECTED.geometry.clone(), outlineMaterial2);
outlineMesh.position.set(SELECTED.position.x, SELECTED.position.y, SELECTED.position.z);
outlineMesh.scale.multiplyScalar(1.05);
scene.add(outlineMesh);
}
}
Threejs从入门到入门的更多相关文章
- babel从入门到入门
babel从入门到入门 来源 http://www.cnblogs.com/gg1234/p/7168750.html 博客讲解内容如下: 1.babel是什么 2.javascript制作规范 3. ...
- Android视频录制从不入门到入门系列教程(一)————简介
一.WHY Android SDK提供了MediaRecorder帮助开发者进行视频的录制,不过这个类很鸡肋,实际项目中应该很少用到它,最大的原因我觉得莫过于其输出的视频分辨率太有限了,满足不了项目的 ...
- Android视频录制从不入门到入门系列教程(三)————视频方向
运行Android视频录制从不入门到入门系列教程(二)————显示视频图像中的Demo后,我们应该能发现视频的方向是错误的. 由于Android中,Camera给我们的视频图片的原始方向是下图这个样子 ...
- springboot + kafka 入门实例 入门demo
springboot + kafka 入门实例 入门demo 版本说明 springboot版本:2.3.3.RELEASE kakfa服务端版本:kafka_2.12-2.6.0.tgz zooke ...
- springboot + mybatisPlus 入门实例 入门demo
springboot + mybatisPlus 入门实例 入门demo 使用mybatisPlus的优势 集成mybatisplus后,简单的CRUD就不用写了,如果没有特别的sql,就可以不用ma ...
- spring入门--spring入门案例
spring是一个框架,这个框架可以干很多很多的事情.感觉特别吊.但是,对于初学者来说,很难理解spring到底是干什么的.我刚开始的时候也不懂,后来就跟着敲,在后来虽然懂了,但是依然说不明白它到底是 ...
- 《图说VR入门》——入门汇总
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/53818922 作者:car ...
- 09Vue.js快速入门-Vue入门之Vuex实战
9.1. 引言 Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其Vue组件设计的就是,父组件通过子组件的prop进 ...
- Python该怎么入门?Python入门教程(非常详细)
Python要学多久可以学会,达到精通呢? 任何知识都是基础入门比较快,达到通晓的程序是需求时日的,这是一个逐渐激烈的进程. 通晓任何一门编程语言,都需求通过大量的实践来积累经验,解决遇到的各种疑难问 ...
随机推荐
- JavaWeb----Cookie&Session
## 会话技术 1.会话:一次会话中包含多次请求和响应. * 第一次会话:浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止. 2.功能:再一次会话的范围内的多次请求间,共享数据 3. ...
- MySQL----多表操作
##多表之间的关系 1.一对一(了解) * 如:人和身份证 * 分析:一个人只有一个身份证,一个身份证只能对应一个人. 2.一对多(多对一) * 如:部门和员工 * 分析:一个部门有多个员工,一个员工 ...
- 题解 P1748 【H数】
我来讲讲 \(dp\) 的做法 前言 昨天 \(PHY\) 大佬问我,这题怎么做?考虑到他没学过 \(set\) . \(priority_queue\) 和 \(queue\) .之后,我就想到了可 ...
- leetcode 每日签到 409. 最长回文串
题目: 最长回文串 给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串. 在构造过程中,请注意区分大小写.比如 "Aa" 不能当做一个回文字符串. 注意: ...
- Attention-based Extraction of Structured Information from Street View Imagery:基于注意力的街景图像提取结构化信息
基于注意力的街景图像提取结构化信息 一种用于真实图像文本提取问题的TensorFlow模型. 该文件夹包含在FSNS数据集数据集上训练新的注意OCR模型所需的代码,以在法国转录街道名称. 您还可以使用 ...
- SVM | 支持向量机原理讲解(二)
一.线性可分的支持向量机存在的问题 在支持向量机一中,我们介绍了当数据集是线性可分的时候,我们可以使用线性可分的支持向量机将数据进行分类(由于隔了很长时间才更新,因此忘记了支持向量机一的读者可以回看支 ...
- PHP7内核:源码分析的环境与工具
本文主要介绍分析源码的方式,其中包含环境的搭建.分析工具的安装以及源码调试的基本操作. 一.工具清单 PHP7.0.12 GDB CLion 二.源码下载及安装 $ wget http://php.n ...
- JAVA——桌球游戏(动画)
跟着视频敲得 ,虽然不是自己的思路 ,不过对代码多了一点了解:涉及到继承类 主函数:创建一个BallGame对象,调用一个launchFrame函数 : launchFrame函数:严格来说是方法 , ...
- coding++:maven根据不同的运行环境,打包不同的配置文件
1.使用maven管理项目中的依赖,非常的方便.同时利用maven内置的各种插件,在命令行模式下完成打包.部署等操作,可方便后期的持续集成使用. 2.但是每一个maven工程(比如web项目),开发人 ...
- linux 中的页缓存和文件 IO
本文所述是针对 linux 引入了虚拟内存管理机制以后所涉及的知识点.linux 中页缓存的本质就是对于磁盘中的部分数据在内存中保留一定的副本,使得应用程序能够快速的读取到磁盘中相应的数据,并实现不同 ...