简单例子

这个例子,是在一个视图中,看到照相机的辅助线,也就是,一个照相机的观察访问

这样,就需要两个照相机,一个是主照相机,一个是加有辅助线的照相机(有两种,正交和透视,这里辅助的使用的是正交的)

设置两个照相机位置:注意,辅助的子照相机要在主照相机里面,这样才能在主照相机的镜头下看到辅助照相机的观察范围

 //场景、摄像机、渲染器、实体
var scene, camera, renderer, cameraHelper;
var cube, controls;
//在页面加载完,进行绘制渲染页面
window.onload = function() {
init(); //数据初始化
setSize(); //设置大小画布
cube(); //绘制实体
animate(); //动画渲染
};
//初始化摄像机,场景,渲染器,以及一些工具,比如摄像机辅助线,控制器
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(
,
window.innerWidth / window.innerHeight,
0.1, );
camera.position.set(, , );
camera.lookAt(new THREE.Vector3(, , ));
//正交投影照相机
camera2 = new THREE.OrthographicCamera(-, , , -, , );
renderer = new THREE.WebGLRenderer({ alpha: true });
camera2.position.set(, , );
camera2.lookAt(new THREE.Vector3(, , ));
//renderer = new THREE.WebGLRenderer();
//camera.position.z = 10;
controls = new THREE.OrbitControls(camera);
controls.autoRotate = true; //照相机帮助线
cameraHelper = new THREE.CameraHelper(camera2);
scene.add(cameraHelper);
}
//设置画布大小,这个设置为整个视图,就不需要剪切了
function setSize() {
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
//普通的四方体
function cube() {
var geometry = new THREE.BoxGeometry(, , );
var material = new THREE.MeshNormalMaterial({ color: 0x00ff00 });
cube = new THREE.Mesh(geometry, material);
//设置位置
cube.position.set(, , -1.5);
scene.add(cube);
}
function animate() {
requestAnimationFrame(animate); //一帧帧动画
cube.rotation.x += 0.005;
cube.rotation.y += 0.005;
cube.rotation.z += 0.005;
camera.updateProjectionMatrix();
controls.update();
cameraHelper.update();
renderer.render(scene, camera); //渲染
}

看完简单的例子,看看复杂的,

左边是一个视图,用一个小的照相机渲染出来的就是右边辅助线的照相机,

右边是两个照相机渲染出来的,右边,外面有个大的照相机,看到里面有个小的照相机,并且通过辅助线看到里面照相机的观察区域。

html部分:是,一个Canvas ,然后拆分为左右两个视图

<canvas id="c"></canvas>
<div class="split">
<div id="view1" tabindex="1"></div>
<div id="view2" tabindex="2"></div>
</div>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>

css

html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
.split {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
display: flex;
}
.split>div {
width: 100%;
height: 100%;
}

js,他是有两个照相机,

1.一个透视作为主照相机,

2.一个正交作为辅助照相机,

在正交照相机加上辅助线,然后把辅助线弄到场景里面,

这样我们就可以在一个照相机(主照相机下)下看到另一个照相机(另一个有辅助线的照相机)的作用范围(辅助线范围)

var renderer,
scene,
camera,
camera2,
cameraHelper,
canvas,
view1Elem,
view2Elem;
function init() {
renderer = new THREE.WebGLRenderer({ canvas });
const size = 1;
const near = 5;
const far = 50;
//正交投影照相机
camera = new THREE.OrthographicCamera(-size, size, size, -size, near, far);
//透视投影照相机
camera2 = new THREE.PerspectiveCamera(
60, // fov
2, // aspect
0.1, // near
500 // far
);
//照相机帮助线
cameraHelper = new THREE.CameraHelper(camera);
scene = new THREE.Scene();
scene.background = new THREE.Color("black");
scene.add(cameraHelper);
} function setCarema() {
camera.zoom = 0.2;
camera.position.set(0, 10, 20); //旋转控制器
const controls = new THREE.OrbitControls(camera, view1Elem);
controls.target.set(0, 5, 0);
controls.update(); camera2.position.set(16, 28, 40);
camera2.lookAt(0, 5, 0); //旋转控制器
const controls2 = new THREE.OrbitControls(camera2, view2Elem);
controls2.target.set(0, 5, 0);
controls2.update();
} function drawObj() {
//面的绘制 {
const planeSize = 40; const loader = new THREE.TextureLoader();
const texture = loader.load(
"https://threejsfundamentals.org/threejs/resources/images/checker.png"
);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.magFilter = THREE.NearestFilter;
const repeats = planeSize / 2;
texture.repeat.set(repeats, repeats); const planeGeo = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const planeMat = new THREE.MeshPhongMaterial({
map: texture,
side: THREE.DoubleSide
});
const mesh = new THREE.Mesh(planeGeo, planeMat);
mesh.rotation.x = Math.PI * -0.5;
scene.add(mesh);
}
//正方体的绘制
{
const cubeSize = 4;
const cubeGeo = new THREE.BoxBufferGeometry(cubeSize, cubeSize, cubeSize);
const cubeMat = new THREE.MeshPhongMaterial({ color: "#8AC" });
const mesh = new THREE.Mesh(cubeGeo, cubeMat);
mesh.position.set(cubeSize + 1, cubeSize / 2, 0);
scene.add(mesh);
}
//球体的绘制
{
const sphereRadius = 3;
const sphereWidthDivisions = 32;
const sphereHeightDivisions = 16;
const sphereGeo = new THREE.SphereBufferGeometry(
sphereRadius,
sphereWidthDivisions,
sphereHeightDivisions
);
const sphereMat = new THREE.MeshPhongMaterial({ color: "#CA8" });
const mesh = new THREE.Mesh(sphereGeo, sphereMat);
mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0);
scene.add(mesh);
}
//光线的设置
{
const color = 0xffffff;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(0, 10, 0);
light.target.position.set(-5, 0, 0);
scene.add(light);
scene.add(light.target);
}
}
//重新渲染 渲染器的大小,如果canvas的大小不是renderer的大小,就重新设置大小 canvas的大小,这个是因为
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}

//剪刀,用来切割canvas 到两个view中,通过view切割计算,找到view的位置,然后进行渲染
function setScissorForElement(elem) {
const canvasRect = canvas.getBoundingClientRect(); //包围盒的正方体
const elemRect = elem.getBoundingClientRect(); // compute a canvas relative rectangle
const right = Math.min(elemRect.right, canvasRect.right) - canvasRect.left;
const left = Math.max(0, elemRect.left - canvasRect.left);
const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canvasRect.top;
const top = Math.max(0, elemRect.top - canvasRect.top); const width = Math.min(canvasRect.width, right - left);
const height = Math.min(canvasRect.height, bottom - top); // setup the scissor to only render to that part of the canvas
const positiveYUpBottom = canvasRect.height - bottom;
renderer.setScissor(left, positiveYUpBottom, width, height);
renderer.setViewport(left, positiveYUpBottom, width, height); // return the aspect
return width / height;
} function render() {
resizeRendererToDisplaySize(renderer); // turn on the scissor 开启剪刀,可以进行切割
renderer.setScissorTest(true); // render the original view
{
const aspect = setScissorForElement(view1Elem); // update the camera for this aspect
camera.left = -aspect;
camera.right = aspect;
camera.updateProjectionMatrix();
cameraHelper.update(); // don't draw the camera helper in the original view
cameraHelper.visible = false; scene.background.set(0x000000);
renderer.render(scene, camera);
} // render from the 2nd camera
{
const aspect = setScissorForElement(view2Elem); // update the camera for this aspect
camera2.aspect = aspect;
camera2.updateProjectionMatrix(); // draw the camera helper in the 2nd view
cameraHelper.visible = true; scene.background.set(0x000040);
renderer.render(scene, camera2);
} requestAnimationFrame(render);
} window.onload = function() {
canvas = document.querySelector("#c");
view1Elem = document.querySelector("#view1");
view2Elem = document.querySelector("#view2");
init();
setCarema();
drawObj();
requestAnimationFrame(render);
};

上面这个例子有点小复杂,因为涉及到,剪刀进行切割视图的计算

threejs CameraHelper 查看照相机的观察范围的更多相关文章

  1. 科学计算三维可视化---TVTK管线与数据加载(用IVTK根据观察管线)

    一:用IVTK根据观察管线 (一)引入该工具 from tvtk.tools import ivtk 可能需要安装pygments pip3 install pygments (二)使用ivtk显示立 ...

  2. 一、threejs————灯光阴影

    threejs设置阴影有三个注意点 1.只有支持阴影的灯光才可以 pointLight,spotlight,directionallight 2.添加摄像机辅助器 THREE.CameraHelper ...

  3. kvm 使用入门详解

    kvm 是虚拟化技术的一个典型实现,功能非常强大,使用很方便.kvm 本身主要实现对 CPU 的虚拟化,内存和IO的虚拟化使用了开源软件 qemu,qemu 是纯软件层面的虚拟化,其实就是个模拟器.k ...

  4. 【Win 10 应用开发】三维变换

    所谓三维变换,其实是在二维平面上产生三维的视觉效果.前面老周简单提了一下透视效果,如果透视效果不能满需求,那可以考虑用三维变换. UIElement类有一个属性叫Transform3D,它定义的类型为 ...

  5. IL接口和类的属性

    上一篇文章学习了IL的入门,接下来我们再通过两个例子来了解下类的属性.构造函数以及接口的使用 一.类的属性.构造函数 1.先看下我们要构建的类的C#代码,然后再进行IL的实现,示例代码如下: [Ser ...

  6. hadoop中遇到的一些问题

    1.验证词统计程序.----无法加载本地库 出现错误: WARN util.NativeCodeLoader: Unable to load native-hadoop library for you ...

  7. OpenGL投影矩阵

    概述 透视投影 正交投影 概述 计算机显示器是一个2D平面.OpenGL渲染的3D场景必须以2D图像方式投影到计算机屏幕上.GL_PROJECTION矩阵用于该投影变换.首先,它将所有定点数据从观察坐 ...

  8. Git学习笔记(1)——安装,配置,创建库,文件添加到库

    初次接触git,为了记忆深刻,把学习的简单流程记录下来. 本文记录了Git在Ubuntu上的安装,配置,以及创建版本库和往库中添加文件的过程. 1.Git的安装:(Ubuntu-Linux非常友好的安 ...

  9. 如何调试Android Framework?

    Linus有一句名言广为人知:Read the fucking source code. 但其实,要深入理解某个软件.框架或者系统的工作原理,仅仅「看」代码是远远不够的.就拿Android Frame ...

随机推荐

  1. vs 设置护眼背景颜色

    工具 —> 选项 —> 环境 —> 字体和颜色 —> 纯文本(显示项中) —> 项目背景 —> 自定义—> 色调位85.饱和度123.亮度205,保存即可.测 ...

  2. Dart中的mixins

    /* mixins的中文意思是混入,就是在类中混入其他功能. 在Dart中可以使用mixins实现类似多继承的功能,with关键字 因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Da ...

  3. 解决 service iptables save 报错 please try to use systemctl

    本文档根据 service iptables save 报错 please try to use systemctl 提供解决方案.报错 [root@Jaking ~]# service iptabl ...

  4. WebSocket始终保持连接的办法

    在项目中,后台为了其实把处理结果主动推送个前端,因此使用了WebSocket. 但是问题来了,页面每跳转一次,socket都要重新关闭建立连接.这个资源消耗是很大的,而且线上环境随着并发量的增加会报错 ...

  5. CGI = MCC + MNC + LAC + CI

    CGI = MCC + MNC + LAC + CI 摘自:http://www.360doc.com/content/19/0801/10/65611272_852334484.shtml CGI是 ...

  6. mysql quick query row count using sql

    1. command show table status like '{table-name}'; 2. sample mysql> use inventory; Database change ...

  7. redis八大应用场景

    1.缓存 缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力.Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓 ...

  8. 如何修改WAMPServer默认的网站路径地址

    通常,我们安装WAMPServer集成的PHP开发环境之后,默认的网站路径地址是其安装目录下子文件夹:"wamp/www/".那么我们怎么修改网站地址到自己指定的路径呢?本篇经验将 ...

  9. node.js http-server 搭建本地服务器

    使用vue-cli创建的项目,能够实现浏览器中自动刷新,实时查看项目效果,其中的原理在于,webpack在本地启动了一个本地服务器,将本机当作一台服务器: 打包后的文件是一个html静态页面,在本地文 ...

  10. docker之容器日志存储位置及把运行日志记录至文件

    参考:https://www.cnblogs.com/YatHo/p/7866029.html docker启动后日志会在以下位置 /var/lib/docker/containers/容器ID/容器 ...