第2章 还记得点、线、面吗(二)

2022-06-28 10:12:53 浏览数 (1)

gltf,glb,fbx,usdz模型下载

我们下面会学习使用直线画一个网格出来,为了更好的理解这个网格在空间中的位置,我们是时候,讲一讲空间坐标系了。

1、右手坐标系

Threejs使用的是右手坐标系,这源于opengl默认情况下,也是右手坐标系。下面是右手坐标系的图例,如果对这个概念不理解,可以百度一下,我保证你伸出手比划的那一瞬间你就明白了,如果不明白请给作者留言,我会尽快补上关于坐标系的知识。

图中右边那个手对应的坐标系,就是右手坐标系。在Threejs中,坐标和右边的坐标完全一样。x轴正方向向右,y轴正方向向上,z轴由屏幕从里向外。

5、线条的深入理解

在Threejs中,一条线由点,材质和颜色组成。

点由THREE.Vector3表示,Threejs中没有提供单独画点的函数,它必须被放到一个THREE.Geometry形状中,这个结构中包含一个数组vertices,这个vertices就是存放无数的点(THREE.Vector3)的数组。这个表示可以如下图所示:

为了绘制一条直线,首先我们需要定义两个点,如下代码所示:

var p1 = new THREE.Vector3( -100, 0, 100 );

var p2 = new THREE.Vector3( 100, 0, -100 );

请大家思考一下,这两个点在坐标系的什么位置,然后我们声明一个THREE.Geometry,并把点加进入,代码如下所示:

var geometry = new THREE.Geometry();

geometry.vertices.push(p1);

geometry.vertices.push(p2);

geometry.vertices的能够使用push方法,是因为geometry.vertices是一个数组。这样geometry 中就有了2个点了。

然后我们需要给线加一种材质,可以使用专为线准备的材质,THREE.LineBasicMaterial。

最终我们通过THREE.Line绘制了一条线,如下代码所示:

var line = new THREE.Line( geometry, material, THREE.LinePieces );

ok,line就是我们要的线条了。

6、画高中时深爱的坐标平面

我还深爱着高中时的那个坐标平面,它勾起了我关于前排同学的细细长发的回忆…

这个平面的效果如下所示,截图不完整哦:

它横竖分别绘制了20条线段,在摄像机的照射下,就形成了这般模样。你可以在[初级教程chapter22-2.html]发现这些代码:

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<title>Three框架</title>

<script src="js/Three.js"></script>

<style type="text/css">

div#canvas-frame {

border: none;

cursor: pointer;

width: 100%;

height: 600px;

background-color: #EEEEEE;

}

</style>

<script>

var renderer;

function initThree() {

width = document.getElementById('canvas-frame').clientWidth;

height = document.getElementById('canvas-frame').clientHeight;

renderer = new THREE.WebGLRenderer({

antialias : true

});

renderer.setSize(width, height);

document.getElementById('canvas-frame').appendChild(renderer.domElement);

renderer.setClearColor(0xFFFFFF, 1.0);

}

var camera;

function initCamera() {

camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);

camera.position.x = 0;

camera.position.y = 1000;

camera.position.z = 0;

camera.up.x = 0;

camera.up.y = 0;

camera.up.z = 1;

camera.lookAt({

x : 0,

y : 0,

z : 0

});

}

var scene;

function initScene() {

scene = new THREE.Scene();

}

var light;

function initLight() {

light = new THREE.DirectionalLight(0xFF0000, 1.0, 0);

light.position.set(100, 100, 200);

scene.add(light);

}

var cube;

function initObject() {

var geometry = new THREE.Geometry();

geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );

geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );

for ( var i = 0; i <= 20; i ) {

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.z = ( i * 50 ) - 500;

scene.add( line );

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.x = ( i * 50 ) - 500;

line.rotation.y = 90 * Math.PI / 180;

scene.add( line );

}

}

function threeStart() {

initThree();

initCamera();

initScene();

initLight();

initObject();

renderer.clear();

renderer.render(scene, camera);

}

</script>

</head>

<body onload="threeStart();">

<div id="canvas-frame"></div>

</body>

</html>

画网格关键之处initObject函数中,我们不浪费纸,但是浪费一些电,在下面重复一下上面的代码:

var cube;

function initObject() {

var geometry = new THREE.Geometry();

// B begin

geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );

geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );

// B end

for ( var i = 0; i <= 20; i ) {

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.z = ( i * 50 ) - 500;

scene.add( line );

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.x = ( i * 50 ) - 500;

line.rotation.y = 90 * Math.PI / 180;

scene.add( line );

}

}

思路:我们要画一个网格的坐标,那么我们就应该找到线的点。把网格虚拟成正方形,在正方形边界上找到几个等分点,用这些点两两连接,就能够画出整个网格来。

1、定义2个点

在x轴上定义两个点p1(-500,0,0),p2(500,0,0)。

geometry.vertices.push( new THREE.Vector3( - 500, 0, 0 ) );

geometry.vertices.push( new THREE.Vector3( 500, 0, 0 ) );

2、算法

这两个点决定了x轴上的一条线段,将这条线段复制20次,分别平行移动到z轴的不同位置,就能够形成一组平行的线段。

同理,将p1p2这条线先围绕y轴旋转90度,然后再复制20份,平行于z轴移动到不同的位置,也能形成一组平行线。

经过上面的步骤,就能够得到坐标网格了。代码如下:

for ( var i = 0; i <= 20; i ) {

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.z = ( i * 50 ) - 500;

scene.add( line );

var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ) );

line.position.x = ( i * 50 ) - 500;

line.rotation.y = 90 * Math.PI / 180; // 旋转90度

scene.add( line );

}

好了,本节课讲完了,感觉自己写了好久好久。要兼顾深度和初学者,确实有些困难。最后,希望您喜欢。

0 人点赞