2

我有一个只有vf参数的.obj文件。

我有一个任务,通过将它“封闭”在一个长方体中(由每个轴上的最大和最小顶点定义)来纹理化它,计算它的中心,然后将茶壶顶点的空间坐标与中心坐标相除,这样我就得到了向量以茶壶的中心为起点,以茶壶的表面为终点,然后找到这些向量(射线)与外部长方体表面相交的位置。长方体的每个面都必须模拟一个图像。之后,我必须计算每个顶点的纹理坐标——只需从 3D 交点获取 2D 参数,然后对结果进行归一化,使它们位于 0 和 1 之间(二维)。

所以,我用一些适当的代码行打开 .obj 文件,然后我进行所有描述的计算以找到 vt 参数,然后使用一个函数,该函数允许我使用构成三角形的索引顶点列表获取 NORMALS(面对属性)和一个顶点列表。

看起来像这样(实际上它由两个函数组成,在两个不同的文件中):

1)

def getNormals4Triangles(self):

    tind = np.resize(self.indx,(len(self.indx)/3,3))
    return VOB.getNormals(self.arrs[0],tind)

其中 self.arrs[0] 是从 .obj 获取的 v 属性列表,而 tind 是构成面的顶点的 3 个元素列表的列表。

2)

@staticmethod
def getNormals(verts,tinds):
    print("Shape verts: ",verts.shape)
    print("Shape tinds: ",tinds.shape)

    if len(verts[0])==3:
        xyz = verts
    elif len(verts[0])==4:
        xyz = verts[:,:3]/np.outer(1/verts[:,3],[1,1,1])
    else:
        raise Exception('No cross product defined')
    txyz = xyz[tinds,:]
    txy = txyz[:,2,:]-txyz[:,0,:]
    txz = txyz[:,1,:]-txyz[:,0,:]
    nrmls = np.cross(txy,txz)
    len_nrmls = norm(nrmls,axis=1)
    return nrmls/np.outer(len_nrmls,[1,1,1])

其中“norm”是线性代数 NumPy 集中的一个函数。

之后,我创建了一个 VOB 对象:

self.vob = VOB(arrs = [vert, point, normals],indx=self.obj.indx)

简而言之,我使用 VOB 对象将其发送到 GPU。

vert - 从 .obj 获取的顶点列表 point - 以上述方式计算的纹理坐标列表 normals - 使用上述函数计算的法线向量列表 self.obj.indx - 由来自 .obj 的 f 属性组成的列表

我使用的纹理图像:质地

当我尝试使用经典的 ligthing 展示它时:

gl.glShadeModel( gl.GL_SMOOTH )
gl.glEnable( gl.GL_LIGHTING )
gl.glEnable( gl.GL_LIGHT0 )
gl.glLightModeli( gl.GL_LIGHT_MODEL_TWO_SIDE, 0 )
gl.glLightfv( gl.GL_LIGHT0, gl.GL_POSITION, [4, 4, 4, 1] )
lA = 0.8
gl.glLightfv( gl.GL_LIGHT0, gl.GL_AMBIENT, [lA, lA, lA, 1] )
lD = 1
gl.glLightfv( gl.GL_LIGHT0, gl.GL_DIFFUSE, [lD, lD, lD, 1] )
lS = 1
gl.glLightfv( gl.GL_LIGHT0, gl.GL_SPECULAR, [lS, lS, lS, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, [0.9, 0.8, 0.7, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, [0.7, 0.8, 0.9, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, [0.9, 0.9, 0.9, 1] )
gl.glMaterialf( gl.GL_FRONT_AND_BACK, gl.GL_SHININESS, 100 )

我可以看到这样的东西: 正常照明

但是当我使用 Blinn 和 Phong 着色模型时(我会避免全部粘贴,希望有人遇到过类似的问题),它是这样的:布林依蓬

为什么在这两种情况下我都看不到质地良好的茶壶?是不是我必须在获得法线和vt坐标后准备新的f属性才能发送到VOB?

4

1 回答 1

0

可能您的面部顶点的缠绕方向不一致,导致一些法线指向内部,从而弄乱了您的照明计算。理想情况下,模型文件中的数据具有正确定向的面,但您可以从种子面开始重新定向面并从那里开始工作。此问题已在此处讨论:如何统一法线方向

一个快速的解决方法是实现一个双面照明模式;本质上,如果基元是背面… * !gl_FrontFacing ? -1 : 1,则在钳制为正值之前,您会否定照明点积的结果。

至于纹理坐标的生成:从技术上讲,您可以实现一个立方体贴图纹理坐标映射,它使用一张图片用于立方体的所有 6 个面,并使用顶点位置作为纹理坐标。或者您只需将相同的图像加载到立方体贴图的 6 个子图像中,并直接使用位置属性作为纹理查找的坐标。

于 2015-05-17T22:43:09.443 回答