前言:
目前姐妹们对“python背景变黑”大约比较注重,我们都想要知道一些“python背景变黑”的相关知识。那么小编也在网上网罗了一些有关“python背景变黑””的相关知识,希望兄弟们能喜欢,我们快快来学习一下吧!我们在《7.Python趣味数学笔记:三维向量及其运算》一章中,通过多组三维向量绘制出了正八面体的结构。
本章我们将在二维平面上渲染出三维对象的俯视图,以便熟悉上一章的点积和叉积运算。假设:光源为上斜侧光,位置坐标;视角为相对于XY平面的俯视。
如果正八面体是个实体,我们只能看到一侧,也就是四个面。在二维平面上渲染出三维对象的俯视图,相当于对四个面进行着色,同时需要考虑光源照射强弱(使用颜色深浅代表明暗变化)。
基本思路:
1)定义三维空间中的三角形,找到视角内可见的四个三角面
2)找到四个三角面的朝外的法向量
3)将三角面投影到二维平面,得到投影面
4)根据四个三角面距离光源的远近,设置投影面的颜色深浅
三角面和法向量
三个顶点向量可以定义一个三角面,不过只知道面还不够,还需要知道面的朝向。
为此需要合理安排三个顶点向量的顺序,使得叉积后得到的法向量垂直于当前面,而且是朝外的(根据右手法则),这意味着我们可以看到这个面。
另外,我们只需要视角内可见的四个三角面。可以根据向量的Z轴分量的正负判断,取所有为正的。
二维投影
将三维对象投影到二维平面,可以转换成:将定义三维对象的点投影到二维平面,消除一个维度的值。
是不是想到了点积?通过点积计算,我们可以得到:一个向量在另一个向量上面的投影。
为此,我们可以定义两个单位向量:X轴和Y轴,然后跟三角面(视角内可见的四个三角面)的顶点分别计算点积,可以得到投影到二维平面上的点坐标。
假设:,根据点积计算公式:
当:
当:
投影到二维平面上的点坐标:
可以看出,三维向量跟某个坐标轴的单位向量的点积,实际上就是:三维向量在该坐标轴上的投影,也就是三维向量在该坐标轴上的分量。
距离光源的远近
距离光源越近,亮度越高,颜色越发白;距离光源越远,亮度越低,颜色越发黑。
如何度量距离光源的远近?
上一章关于点积,我们提到“一般来说,点积越大,两向量夹角越小,彼此越靠近”。借助于点积,度量距离光源的远近,可以转换成:度量三角面的法向量跟光源向量的夹角大小。
使用cmap设置颜色,需要提供。假设透明度固定为1.0,那么黑色:,白色:,灰色:调整0到1之间的值。
因此,设置颜色的过程,可以使用如下计算方式:
,是垂直于三角面的法向量的单位化向量;是光源向量的单位化向量;是三角面的法向量跟光源向量的夹角
因为光源位于斜上方,颜色值的计算结果会落在0到1之间。
部分代码
from draw_objects import Lines,draw_objects#使用点积计算投影长度def component(v,direction): return dot(v,direction)/length(direction)#三维向量投影到(x,y)平面def vector_to_2d(v): return (component(v,(1,0,0)),component(v,(0,1,0)))#将单个面投影到(x,y)平面def face_to_2d(face): return [vector_to_2d(v) for v in face]#转换成单位向量def unit(v): return scale(1. / length(v), v)#叉积运算得到垂直于三角面的法向量def normal(face): return cross(subtract(face[0],face[2]),subtract(face[1],face[2]))#在二维平面上渲染三维对象的投影def render(faces,color_map,light=(1,2,3),lines=None): lines=[] #遍历所有面 for face in faces: #计算垂直于该面的单位向量 unit_normal=unit(normal(face)) #只有当向量的z轴分量为正(指向观察者),俯视图? if unit_normal[2]>0 : #法向量和光源的点积越大,说明越靠近光源,阴影越少 value=1-dot(unit_normal,unit(light)) #有效值在[0,1]范围内 if value < 0 : value=0.0 elif value>1.0: value=1.0 c=color_map(value) #print(c) p=Lines(face_to_2d(face),fill=c,color=lines) lines.append(p) draw_objects(*lines,axes=False,origin=False,grid=None)#在二维平面上渲染三维对象的投影,俯视图v=[1,-1]#6个顶点vertexs=[(x,0,0) for x in v]+ \ [(0,y,0) for y in v] + \ [(0,0,z) for z in v]#8个面faces=[ #这里是有顺序的(a,b,c),(a-c)×(b-c)指向八面体外部 [(1,0,0),(0,1,0),(0,0,1)],#右上 [(1,0,0),(0, 0,-1),(0, 1, 0)],#右下 [(1,0,0),(0,0,1),(0,-1,0)],#左上 [(1,0,0),(0,-1,0),(0,0,-1)],#左下 [(-1,0,0),(0,0,1),(0,1,0)],#后右上 [(-1,0,0),(0,1,0),(0,0,-1)],#后右下 [(-1,0,0),(0,-1,0),(0,0,1)],#后左上 [(-1,0,0),(0,0,-1),(0,-1,0)],#后左下]#使用灰色greys=cm.get_cmap('Greys')#在二维平面上渲染三维对象的投影render(faces=faces,color_map=greys,lines=black)绘制效果图
距离光源越近,亮度越高,颜色越发白;距离光源越远,亮度越低,颜色越发黑:
对比图:
标签: #python背景变黑 #python背景变黑代码