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

1、 学会画点、画线、画面的知识

2、 学会绘制复杂的图形

4、知识补充:坐标系

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

1、右手坐标系

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

three.js坐标系

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

5、线条的深入理解

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

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

three.js向量

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

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、画高中时深爱的坐标平面

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

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

three.js画坐标系

它横竖分别绘制了20条线段,在摄像机的照射下,就形成了这般模样。你可以在[初级教程\chapter2\2-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 );

}


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

给WebGL中文网团队的女程序员"小果妹妹"发一个鸡腿吧,微信扫一扫赞赏,感谢。

亲爱的读者,如果你觉得WebGL中文网的课程不错,您可以购买《WebGL中文网视频课程》 课程支持我们哦,购买后记得给我们好评哦!我们强烈建议您不要在iphone上的网易云课堂软件中购买,这样苹果会收取31%左右的服务费,虽然这是明码标价,我们也表示认可和理解,具体选择权在您自己了。

感谢大家的支持,下面是课程的截图之一

[1楼] mayi** 2016-06-12 23:20

老师,我看不懂算法这部分(

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

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

WebGL中文网老师回答:

不明白问题的意思。 注意相机的up方向,本课并不是y轴。

[2楼] dibi** 2016-06-23 13:55

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
});
老师,您好!

1.up & position & lookAt的区别是什么?相机默认位置面向Z轴,camera.up.z = 1之后发现面向X轴了,不太明白。

2.camera.lookAt({ x : 0, y : 0, z : 0 });这句的意思应该是重置当前位置为相机的初始位置,这里是将position设置为初始位置还是将up设置为初始位置?

3.请问,camera.lookAt({ x : 0, y : 0, z : 0 });重置之后,是否相机面向还是Z还是新设定的位置呢?

谢谢!

WebGL中文网老师回答:

首先要说的是up、position、lookat在初级视频课程中有详细的讲解,不明白可以看,是免费的。

再说position,不用说也知道是相机的位置。如果吧人头比作相机,那么就是人头的中心的位置

up是头顶的方向,大多数时候,是朝天空的。少部分时候,是朝床头的

lookat是眼睛,看的方向,或者说是眼睛的聚焦点,不要告诉我,你眼睛可以同时聚焦2个点。

最后要说明的是 up 和lookat这两个方向必须垂直,无论怎么设置,他们必须互相垂直。不然相机看到的结果无法预知。

上面的问题很误导人,position在英文中是位置的意思,所以不要怀疑up是位置

另外,相机没有朝向的说法,只有lookat,就是它看到的那一个聚焦点,就像眼睛看到的聚焦点一样。

[3楼] mr.t** 2016-06-24 15:17

camera.position.y 的值从1000到1208之间,值越大锯齿网格上线多出来的东西越少;

超过1208就没有多出的部分,我不确定是相机视角的问题还是其他的问题。

WebGL中文网老师回答:

这个和图片放得越大,越不清晰一个道理,可以尝试设置WebGLRenderer的参数来抗锯齿。代码如下:

new THREE.WebGLRenderer({antialias:true})

相机距离网格越近看到的细节就越多,锯齿感也就越来越严重。相片放得的越大会发现越不清晰,锯齿也就越多,也是这个道理。antialias:true可以弱化锯齿就像PS中的羽化效果一样。

[4楼] Mang** 2016-07-12 11:21

THREE.Line在google中出现警告,google测试提示,让更换成LineSegments,不过两种都可以显示

WebGL中文网老师回答:

新旧版本的three.js版本更更换,说明在未来的版本中,该类会被删除

[5楼] fion** 2016-07-19 11:03

老师你好,请问一下

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

这里表示围绕着y轴旋转90度,那么改为围绕着z轴旋转90度的话,

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

看到的效果不应该是20个相隔的点吗,为什么效果是两条中间有间隙的直线呢,不太懂这个旋转的方向。。。

___________    ___________

[6楼] gera** 2016-07-27 10:22

关于这个地方,我发表下自己的看法,看对不对:

console.log("正常的右手坐标系是x向右,y向上,z向屏幕外");
console.log("分析横线的画法可以得出当前坐标系:x向左,y向屏幕外,z向上");
console.log("分析竖线的画法可以得出:绕y轴旋转90°,方向是逆时针");

不知道是不是这样呢?

[7楼] sher** 2016-08-04 17:42

老师,我一直不明白这个坐标原点具体是在哪里?或者以照相机为参照,照相机是原点吗?

WebGL中文网老师回答:

坐标原点指定的是世界坐标,不是计算机的屏幕中心,与显示器无关。是我们脑海中的一个世界坐标,相机放在世界坐标中的一个位置。而相机的中心与世界坐标无关,相机只是世界坐标中一个特殊的物体而已。这个问题,如果想通的人很简单,想不通的,很难。你可以看一下视频课程(hewebgl.com/paytip),课程上百集,已经足够你深入学习了,课程介绍了很多图形学的知识,可以少走弯路。

[8楼] sunr** 2016-08-04 21:29

初级免费教程的压缩包有密码?

WebGL中文网老师回答:

密码是网站域名 www.hewebgl.com

[9楼] Medi** 2016-08-16 18:34

这个地方我看过教程之后发现,可能坐标的描述是有问题的,屏幕向右是x的正方向,垂直屏幕向外是y轴正方向,沿屏幕向上是z轴正方向,点的描述中点的坐标表示为THREE.Vector3(x,y,z),个人觉得基本是这样的。

WebGL中文网老师回答:

在相机在z轴正方向位置,lookat指向(0,0,0)点的时候,x右边是正,y向上,z从屏幕里面到外面。当相机位置变了,那么所谓的世界坐标就变了,另外,最好不要把世界坐标和屏幕的关系绑在一起,不然很难理解。

[10楼] syla** 2016-08-18 11:49

其实我也跟9楼一样的问题,坐标系究竟是怎样的,为什么网格是z轴位移的?是不是跟1楼提问的关系有关?摄像机究竟怎样摆放

WebGL中文网老师回答:

建议用实际的模型在现实生活中摆一下就明白了。 要有空间的感觉。实在不明白,请看视频课程,100多集,这些一定能搞懂。

[11楼] bool** 2016-09-01 23:14

其实我觉得如下设置camera更容易理解(y向上,x向右坐标系):

      function initCamera() {

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

                camera.position.x = 0;

                camera.position.y = 0;

                camera.position.z = 1000;

                camera.up.x = 0;

                camera.up.y = 1; 

                camera.up.z = 0;

                camera.lookAt({

                    x : 0,

                    y : 0,

                    z : 0

                });

            }

因为屏幕2D空间大多数程序都是这样设置的,相应修正initObject:

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 <= 1; i ++ ) {

        var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 1.0 } ) );
        line.position.y = ( 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.z = 90 * Math.PI / 180;
        scene.add( line );
    }
}

不知道老师为什么喜欢用z向上的坐标系呢?

WebGL中文网老师回答:

是的,如果能把我的理解了,那么其他的也就理解了。

[12楼] cgh2** 2016-09-07 11:26

给5楼,你的想法是对的,你说的两条线其实是就是中间两个点的侧面,但因为相机离平面太近你只看到两条线在你左右。

[13楼] xiao** 2016-09-21 14:12

尝试了简化 initObject() :

function initObject() {
    var material = new THREE.LineBasicMaterial({
        color: 'black'
    });

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

    var createLine = function (x,z,isVertical) {
                    var line = new THREE.Line( geometry, material );
                    if (x) {
                        line.position.x = x;
                    }
                    if (z) {
                        line.position.z = z;
                    }
                    if (isVertical) {
                        line.rotation.y = 90 * Math.PI / 180;
                    }
                    scene.add( line );
    }
    for (var i = 1, length = 22, half = length / 2; i < length; i++) {
        createLine(0, (i - half) * 50);
        createLine((i - half) * 50, 0, true);
    }
}

[14楼] shuh** 2016-11-25 14:33

总感觉相机camera.up.z=1有些别扭——相当于头顶朝向屏幕外面往下看,但咱们开发者都是看向屏幕里面,低头往下看的话也是头顶朝向屏幕内,感觉z=-1更舒服些...

[15楼] woni** 2016-12-03 21:16

老师你好,我想问的是为什么横线只有17根,明明设置的是21根嘛。我调试过好多次,而且您这个网页上贴的图也是只有17根,我数过了的。

WebGL中文网老师回答:

哈哈,是21根,截图的时候没有截完,不要太学究了。

[16楼] woni** 2016-12-03 21:18

画出来的网格并不是正方形的,是长<高的长方形。为什么不是20*20个正方形呢?

[17楼] woni** 2016-12-03 21:32

额。。。18楼19楼的问题解决了:是因为camera.position.y的值设置小了,这好比就是相机的视野小了,所以上下分别有两根竖线在视野之外,相机看不到。因此只需要把camera.position.y设置大一点(1208以上)就可以了。

[18楼] gaog** 2017-01-04 19:00

老师我是初学者 ,我想知道怎么增加网格??

[19楼] haha** 2017-05-12 10:46

请问在已经生成线体之后能否改变线的两个端点的坐标呢,还是只能修改线本身的坐标位置

[20楼] heya** 2017-05-25 16:12

看来还是有很多人不明白坐标系,老师把up.z设为1是按照现实生活来的,把地面作为xy平面,那么高度就由z轴确定了,我理解了一下,你把显示器屏幕朝上举着,眼睛从显示器右边水平看过去就是这种情况了,具体可以看一下http://www.cnblogs.com/heyach/p/6902948.html,写的不好请各位大佬多多指教。

[21楼] king** 2017-06-28 16:50

老师绘制出来的网格是长20宽20 , 大家看到的是17个原因是相机距离网格太近,大家把源码里的camera.position.y = 1000 (改为1500) ;  正方形就完整的呈现出来了

[22楼] yerl** 2017-07-04 15:00

@5楼  @14楼

5楼提出的问题在14楼有了解答,但我感觉并不完全正确,14楼懂了照相机的概念但是没有具体去想想照相机的高度。正确来讲那两条线肯定不只是两条线的侧面,而是多条线叠在一起的结果(建议以对称的两条线为一组来为线段设置不同的颜色,这样最后看到的效果非常明显)。

在解决这个问题时我产生了一个疑惑,感觉按道理讲在i===10时的那条线应该在照相机眼里会是一个点,

但实际上并没有这么一个点,我不知道是不是在这种三维世界里单个点都是直接忽略的,希望老师或者懂这方面的朋友能够解答一下,谢谢了

[23楼] yxy** 2017-07-17 16:30

老师好,画出20个网格,for循环里以50为间隔,那么画出来后不应该是长宽都是50px的正方形吗,这个单位不是px吗

[24楼] jian** 2017-08-22 11:45

我们在浏览器看到的图像,都是相机拍照后,用渲染器渲染出来的。

理解了这个,那么我们就要找到相机在哪个方向,对场景进行了拍照。

在本节课中,相机在(0,1000,0)这个位置,相机的聚焦点在(0,0,0),也就是说,

在右手坐标系中,相机是从 上方垂直向下拍照场景的。这个情况下,Y轴在相机的眼中,就成了一个点,而

X轴和Z轴垂直交叉 ,构成了一个 “十”字。我们看到的图像,就是相机拍照 X和Z轴构成的那个平面。

[25楼] 1618** 2017-09-06 09:41

老师您好,我是特意注册一下,上来就是为您鼓掌。感谢您的无私奉献,为我这样的初学者带来了很多曙光。非常的感谢您。

[26楼] 1618** 2017-09-06 09:51

老师您好,我还有一个问题

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


这句话是说 向canvas-frame中添加一个渲染器的元素对吗?

那么是否也可以用这个方式向其中添加一个物体对象呢 比如说一个长方体,我的意思是向这个场景中。

我的根本意思就是 我想通过外部的鼠标事件 来触发向这个场景中添加我需要的物体,请问是否可以实现

[27楼] badw** 2017-09-28 11:25

由于camera视角的问题会出现理解不能的情况...所以自己重新改了点参数,加了点线段,便于理解

代码在https://github.com/BadWaka/BadWaka.github.io/blob/master/views/three/three-demo-2-2.html

Image

WebGL中文网老师回答:

不错,加油

[28楼] knig** 2017-10-21 23:39

31楼的哥们有初级教程的密码吗

WebGL中文网老师回答:

官网域名:www.hewebgl.com 是密码

[29楼] gosa** 2017-11-22 17:08

用新版的同学,把lookat修改就可以啦。


修改前:

camera.lookAt({ x : 0,

y : 0,

z : 0

});


修改后:

camera.lookAt(0,0,0);

WebGL中文网老师回答:

其实一样,本质没变,看一下源码,30s即明白,大家要养成一些学习的习惯,如看源码。

[30楼] gosa** 2017-11-22 17:41

$ACD6946F9FD2DDE.jpg

为什么上传图片失败了呢。。

[31楼] Rich** 2017-12-22 11:42

0,1000,0老师好,老师在评论里说up 和lookat这两个方向必须垂直,

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
});

请问up(0,0,1),lookat(0,0,0),position(0,1000,0)是如何垂直的;

position-up:(0,1000,0)->(0,0,1);

position-lookat:(0,1000,0)->(0,0,0);

如果是中心->头顶,中心->视点,这样是不垂直的

[32楼] 流年异彩** 2018-03-28 20:57

91版本的three.js复制文中代码不报错没效果什么情况

[33楼] 名字长很** 2018-04-02 10:58

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

感觉上面原文的话错了,z轴正方向向上,y轴由屏幕从里向外才对。

[34楼] lirc** 2018-04-08 15:38

@12楼

一个是从上向下看,一个是从前向后看,不一样吧

[35楼] xmlh** 2018-04-19 11:51

92dev版本的 只显示竖线,不显示横线 ,什么情况??

[36楼] MOpi** 2018-05-07 15:05

30楼的代码链接打不开?求大神告知

[37楼] Matr** 2018-08-07 16:51

老师你好,我在本课遇到这个警告WebGL: INVALID_OPERATION: getAttribLocation: program not linked,页面没有显示出网格。百度过没有找到答案,我该怎么解决呢?

WebGL中文网老师回答:

看一下浏览器是否支持webgl。

[38楼] 5913** 2018-08-13 17:03

[3楼]相机的位置position的值与THREE.PerspectiveCamera(75, cw / ch, 1, 1000)最后的一个值有关系.

[9楼][10楼]此节的例子相机是在Y轴,主要拍摄X\Z轴组成的面,而且头顶在Z轴方向,所以,在电脑屏幕,水平向左为X轴正方向,向上为Z轴正方向,屏幕向外(向我们人)这边为正方向.

WebGL中文网老师回答:

是的,你说的是正确的,当3D世界在屏幕中之后,最好忘记世界坐标。本课时特殊的情况,如果相机是歪着摆的,那么什么世界坐标系x、y、z就根本说不清了,反而难以理解。

[39楼] cona** 2018-10-15 11:45

老师你好:

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

上述代码中的rotation,旋转中心是哪里?能不能详细讲解一下?

旋转中心是坐标原点?还是这条直线的中点?还是这条直线的某个端点?

在这个示例中,坐标原点就是直线的中点,所以这个rotation的旋转中心具体是什么?

[40楼] jame** 2018-10-15 15:18

关于相机与世界坐标以及相机各个参数之间的关系,我是这样理解的:举个例子来说,我们要用手机拍一个物体,比如香蕉,那么我们会怎么做?首先是不是得把手机拿起来放到某个位置上去,你得拿你的手固定住手机才能拍出照片,对吧,这就对应是camera的三个position属性(位置)。其次,当你把手机放到那个位置上后,你要拍到香蕉,你是不是得把手机对准那个香蕉,不然你手机虽然在那个位置,但你向上,向下随便翻动手机,可能会拍到香蕉吗?当然不会,所以对准香蕉这个操作就对应camera的 looAt() 操作。最后,你手机也摆好了,香蕉也对准了,但你是不是还得考虑到底是横着拍还是竖着拍,或者斜着拍?因为你手机横着或者竖着拍出来的香蕉是不同的,所以你手机到底是横着还是竖着对应的就是camera的up属性,这个up指的就是你手机向上的方向。当这三个因素被确定下来后,相机才能够被确定,从而拍出确定的照片,“确定”这个条件对计算机是非常重要的,因为不确定的东西对计算机来说是无法被理解的,所以也就不可能被计算机呈现。

[41楼] luck** 2018-11-01 14:37

老师,明白相机参数的意思,但是我三维想象差,不明白参数变了拍到的是什么样子,痛苦中。。。,求指点

[42楼] zsb5** 2018-12-27 22:55

老师你好,我想问下这个关于相机的位置在(0, 100, 0) 看向 (0, 0, 0)的问题:

camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.x = 0;
camera.position.y = 100;
camera.position.z = 0;
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
camera.lookAt({
  x : 0,
  y : 0,
  z : 0
});

然后两个点分别是p1是黑色的,p2是红色的,我原本觉得从上往下看的时候,应该是左下角是黑色 -> 右上角是红色的,但是事实却是左上角黑色 -> 右下角红色(截图上传不了呢)

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

[43楼] hans** 2019-03-25 19:57

@5楼


因为,围绕自身y轴旋转,指的是,在  x轴和z轴围成的那个平面之内,进行旋转。

[44楼] 飞飞飞飞** 2019-04-26 16:42

这教程真给劲儿,点赞!!两个线对象的名称居然可以一样?

[45楼] nka6** 2019-05-20 16:11

camera.postion定义camera的位置。camera.up定义相机镜头所在的平面,lookat定义镜头朝向,聚焦位置。camera.position所在的坐标系参照物就是场景。 而camera.up定义的时候要以相机为原点,重新建立右手坐标系。up(x,y,z)的数值所表示的方向  只要跟lookat 的点跟相机位置连线垂直就可以了。这个得自己去理解了。

[46楼] 1253** 2019-08-27 17:11

小计:

场景就是这个世界,相机就是我们的眼睛,而显示在屏幕上的就是相当于眼睛看到以后视网膜的成像,

我个人理解偏向于世界中心固定,方便自己想象成像。

至于楼上的大佬们说在不同位置坐标轴的方向会变,这是相对相机而言的,人站着的时候和躺着的时候看电线杆自然是不一样的,.up方法就是用来决定人是站着还是躺着的。

[47楼] 6870** 2019-09-19 06:11

感谢老师。一个困惑:

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

Opacity 这个 property 似乎被忽略?我画出来的线是 opacity=1 的实线。

在官方文档上没有罗列出 opacity 这个 parameter?

https://threejs.org/docs/#api/en/materials/LineBasicMaterial

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

加上“transpare:true” 解决。具体原因跟three.js需要确定渲染顺序有关?对此很疑惑。

[48楼] loto** 2020-11-20 17:47

为什么我把代码copy下来,在浏览器中运行,没有任何的效果呢?

[49楼] hqzh** 2021-01-20 17:50

回复32楼,当前最新版,以下两处改一下即可

camera.lookAt(new THREE.Vector3(0, 0, 0));

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

[50楼] hqzh** 2021-01-20 17:57

同样48楼

[51楼] Lese** 2022-08-16 17:28

  camera.position.x = 0;
  camera.position.y = 1300;
  camera.position.z = 0;

我将视角放大到1300,才能完整显示21根线

[52楼] huan** 2023-03-30 10:01

最新的能跑起来的代码,使用了更简单的易看的代码风格,逻辑没变, 没办法太长了没法直接发完整代码:

initLight() {

this.light = new THREE.DirectionalLight(0xff0000, 1.0, 0)

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

this.scene.add(this.light)

},

initObject() {

let geometry = new THREE.BufferGeometry()

geometry.setFromPoints([

new THREE.Vector3(-500, 0, 0),

new THREE.Vector3(500, 0, 0)

])

提问或评论

登陆后才可留言或提问哦:) 登陆 | 注册 登陆后请返回本课提问
用户名
密   码
验证码