ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

three.js入门一:入门demo讲解

2022-01-20 15:00:31  阅读:240  来源: 互联网

标签:入门 geometry demo THREE three window points new camera


环境:

  • threejs:129 (在浏览器的控制台下输入: window.__THREE__即可查看版本)
  • vscode
  • window
  • edge

关于threejs:
开源web3d引擎

github:https://github.com/mrdoob/three.js/
官网:https://threejs.org/
中文教程:http://www.yanhuangxueyuan.com/WebGL/

1. 入门Demo

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="js/three.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>

<body>

    <script>
        //基础准备
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 设置为51,发现z轴的箭头被切掉一部分
        // const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 51, 1000);
        // var aspectratio = window.innerWidth / window.innerHeight;//1920/969=1.98
        //const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
        camera.position.set(0, 0, 100);

        // 相机的up值在这里设置生效
        // camera.up.x = 0;
        // camera.up.y = 1;
        // camera.up.z = 0;

        camera.lookAt(0, 0, 0);
        console.log(camera);
        const renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setSize(window.innerWidth, window.innerHeight);
        // renderer.setSize(500, 500);
        document.body.appendChild(renderer.domElement);


        // 轴线
        //x轴线 红色
        var material = new THREE.LineBasicMaterial({ color: 0xff0000 });
        var points = [];
        points.push(new THREE.Vector3(0, 0, 0));
        points.push(new THREE.Vector3(50, 0, 0));
        var geometry = new THREE.BufferGeometry().setFromPoints(points);
        var line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头1
        points = [];
        points.push(new THREE.Vector3(50, 0, 0));
        points.push(new THREE.Vector3(48, 2, 0));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头2
        points = [];
        points.push(new THREE.Vector3(50, 0, 0));
        points.push(new THREE.Vector3(48, -2, 0));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);

        //y轴线 绿色
        material = new THREE.LineBasicMaterial({ color: 0x00ff00 });
        points = [];
        points.push(new THREE.Vector3(0, 0, 0));
        points.push(new THREE.Vector3(0, 50, 0));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头1
        points = [];
        points.push(new THREE.Vector3(0, 50, 0));
        points.push(new THREE.Vector3(2, 48, 0));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头2
        points = [];
        points.push(new THREE.Vector3(0, 50, 0));
        points.push(new THREE.Vector3(-2, 48, 0));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);

        //z轴线 蓝色
        material = new THREE.LineBasicMaterial({ color: 0x0000ff });
        // material = new THREE.LineBasicMaterial({ color: 0x000000 });
        points = [];
        points.push(new THREE.Vector3(0, 0, 0));
        points.push(new THREE.Vector3(0, 0, 50));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头1
        points = [];
        points.push(new THREE.Vector3(0, 0, 50));
        points.push(new THREE.Vector3(2, 0, 48));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);
        //箭头2
        points = [];
        points.push(new THREE.Vector3(0, 0, 50));
        points.push(new THREE.Vector3(-2, 0, 48));
        geometry = new THREE.BufferGeometry().setFromPoints(points);
        line = new THREE.Line(geometry, material);
        scene.add(line);


        //立方体
        geometry = new THREE.BoxGeometry(40, 40, 40);
        material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        cube = new THREE.Mesh(geometry, material);
        cube.position.set(0, 0, 0);
        scene.add(cube);

        var lookX = 0, lookY = 0, lookZ = 0;
        const animate = function () {
            requestAnimationFrame(animate);

            // 相机的位置
            camera.position.x += 0.1;
            camera.position.y += 0.1;
            camera.position.z += 0.1;

            // 立方体的旋转
            // cube.rotation.x += 0.01;
            // cube.rotation.y += 0.01;
            // cube.rotation.z += 0.01;

            // 立方体的位置
            // cube.position.set(cube.position.x + 0.01, cube.position.y, cube.position.z);
            // cube.position.set(cube.position.x, cube.position.y + 0.01, cube.position.z);
            // cube.position.set(cube.position.x, cube.position.y, cube.position.z + 0.01);

            // 相机的摆放姿势(在这里设置无效)
            // camera.up.x=1;
            // camera.up.y=0;
            // camera.up.z=0;

            // 相机的lookAt
            // camera.lookAt(lookX += 0.01, lookY += 0.01, lookZ += 0.01)
            // camera.lookAt(lookX += 1, lookY, lookZ)
            renderer.render(scene, camera);
        };

        animate();
    </script>
</body>

</html>

效果图如下:
在这里插入图片描述

2. 坐标系

threejs使用的是右手坐标系,即:
在这里插入图片描述
默认情况下,threejs中的坐标轴如上所示:x轴在屏幕上从左到右,y轴在屏幕上从下到上,z轴穿透屏幕从内到外;我们也可以修改相机的参数(相机方向)使这个坐标系发生旋转,但无论怎么旋转都是右手坐标系。

可以将坐标系打印出来如下:
在这里插入图片描述

坐标系旋转操作:

旋转时需要确定轴方向以及轴上一点。
对于上图中立方体的旋转,我们控制它绕x轴旋转,则代码如下:

// 立方体的旋转
cube.rotation.x += 0.01;

这样旋转时,立方体就以经过它中心点(即立方体的position,这里将它设为(0,0,0))的x轴旋转,此时,立方体的旋转方向也符合右手螺旋定则(可以这么理解),即:大拇指指向x轴正方向,其他4指弯曲的方向是旋转的正方向。

3. 相机参数

1. 相机位置:
这个即观察者的位置,最易理解,示例代码:

camera.position.set(0, 0, 100);

2. 观察目标位置:
即眼睛看向哪里。可以看向坐标原点,也可以看向其他点,看的方向不同,自然得到的效果不同,示例代码:

camera.lookAt(0, 0, 0);

3. 相机方向:
即我们是站着看,还是躺着看,还是侧着身看,不同的姿势观察的效果不同,比如,我们侧着身子看到的东西是歪着的,倒过来看到的东西也是倒着的,示例代码:

 // 一般不需要修改此参数,注意此代码的位置,我在animate函数中设置不起作用,放在外面就可以
 camera.up.x = 0;
 camera.up.y = 1;
 camera.up.z = 0;

4. 相机的视场角(FOV)
即:眼睛看到的角度范围,如下图:
在这里插入图片描述
我们可以设置不同的值,观察效果,它的取值范围应该是(0,180),threejs给的demo是75度,一般取这个值没问题:
在这里插入图片描述
示例代码如下:

//视场角设置为75度
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

5. 相机的 aspect ratio
这个参数和图像的宽高比有关,一般我们将它设置为 window.innerWidth / window.innerHeight
它可以和渲染器的窗口大小配合使用,当它们宽高比一致时正常显示,否则渲染会发生变形,如下示例代码:

//将相机的aspect ratio宽高比设置为使用浏览器窗口(我的浏览器是:1920/769=1.98)
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
//...
const renderer = new THREE.WebGLRenderer({antialias: true});
//渲染的窗口宽高比和相机的aspect ratio值相同,正常显示不变形
renderer.setSize(window.innerWidth, window.innerHeight);
//渲染窗口设置为500*500,导致渲染的宽高比和相机的aspect ratio值不同,发生形变,此时可以将相机的aspect ratio调整为"1"
//renderer.setSize(500, 500);

6. 相机的near 和 far
这个参数表示,在距离相机[near,far]范围内的图形可显示,超出的内容要被剪切掉,可以理解为前后各切一刀。
注意:可以用这个参数提高渲染性能。

//设置为 距离相机[0.1,1000]范围内的图形可显示
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 下面将 near设置为51,因为设置的箭头有两个线段的坐标为:(0, 0, 50)->(2, 0, 48)  (0, 0, 50)->(-2, 0, 48),而相机的位置在(0,0,100) 所以near设置为51后可以看到被切断的箭头
// const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 51, 1000);

在这里插入图片描述

最后示例代码:

https://download.csdn.net/download/u010476739/76901892

标签:入门,geometry,demo,THREE,three,window,points,new,camera
来源: https://blog.csdn.net/u010476739/article/details/122597958

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有