前回からの続きです。Open Dynamics Engineでは、任意の三角形は、節点の座標データと、節点の番号データの配列で扱われます。STLデータでは、各三角形の頂点座標と法線ベクトルで構成されているので、少々変換が必要です。下はPyOdeのTutorialから、TriMeshDataの説明です。
前回のコードの読み込む処理を変更しました。
import os import struct from OpenGL.GL import * from OpenGL.GLU import * from OpenGL.GLUT import * import pygame from pygame.locals import * import numpy as np from struct import unpack NormalV =[] NodePoint = [] Vertex1 = [] Vertex2 = [] Vertex3 = [] NVertex = [[0,1,2],[0,1,2]] Eye_from_x = 60.0 Eye_from_y = 50.0 Eye_from_z = 100.0 Center_X =0. Center_Y =0. Center_Z =0. T_Color = [0.5, 0.7, 0.5, 1.0] #Object Color def BinarySTL(fname): global NVertex #read start of file to determine if its a binay stl file or a ascii stl file fp=open(fname,'rb') h=fp.read(80) type=h[0:5] fp.close() if type=='solid': print ( "reading text file"+str(fname)) return else: print ("reading binary stl file "+str(fname,)) fp = open(fname, 'rb') Header = fp.read(80) nn = fp.read(4) Numtri = unpack('i', nn)[0] #print nn record_dtype = np.dtype([ ('normals', np.float32,(3,)), ('Vertex1', np.float32,(3,)), ('Vertex2', np.float32,(3,)), ('Vertex3', np.float32,(3,)) , ('atttr', '<i2',(1,) ) ]) data = np.fromfile(fp , dtype = record_dtype , count =Numtri) fp.close() Normals = data['normals'] Vertex1= data['Vertex1'] Vertex2= data['Vertex2'] Vertex3= data['Vertex3'] p = np.append(Vertex1,Vertex2,axis=0) p = np.append(p,Vertex3,axis=0) #list(v1) Points =np.array(list(set(tuple(p1) for p1 in p))) NVertex = np.resize(NVertex,(len(Vertex1),3)) NVertex[0][0] = Points.tolist().index([Vertex1[0][0],Vertex1[0][1],Vertex1[0][2]]) NVertex[0][1] = Points.tolist().index([Vertex2[0][0],Vertex2[0][1],Vertex2[0][2]]) NVertex[0][2] = Points.tolist().index([Vertex3[0][0],Vertex3[0][1],Vertex3[0][2]]) for i in range(1,len(Vertex1)): # print(i) NVertex[i][0] = Points.tolist().index([Vertex1[i][0],Vertex1[i][1],Vertex1[i][2]]) NVertex[i][1] = Points.tolist().index([Vertex2[i][0],Vertex2[i][1],Vertex2[i][2]]) NVertex[i][2] = Points.tolist().index([Vertex3[i][0],Vertex3[i][1],Vertex3[i][2]]) return Header,Points,Normals return def draw_box(): global NormalV,NodePoint,NVertex glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, T_Color) glPushMatrix() glBegin(GL_TRIANGLES) for i in range(len(NormalV)): glNormal3f(NormalV[i][0],NormalV[i][1],NormalV[i][2]) glVertex3f(NodePoint[NVertex[i][0]][0],NodePoint[NVertex[i][0]][1],NodePoint[NVertex[i][0]][2]) glVertex3f(NodePoint[NVertex[i][1]][0],NodePoint[NVertex[i][1]][1],NodePoint[NVertex[i][1]][2]) glVertex3f(NodePoint[NVertex[i][2]][0],NodePoint[NVertex[i][2]][1],NodePoint[NVertex[i][2]][2]) glEnd() glPopMatrix() def prepare_GL(): global quadratic quadratic = gluNewQuadric() glViewport(0,0,640,480) glClearColor(0.8,0.8,0.9,0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_LIGHTING) glEnable(GL_LIGHTING) glEnable(GL_NORMALIZE) glShadeModel(GL_FLAT) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective (90,1.3333,0.1,1000.) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) glEnable(GL_LIGHT0) glDisable(GL_CULL_FACE) gluLookAt (Eye_from_x, Eye_from_y, Eye_from_z, Center_X, Center_Y, Center_Z, 0.0, 0.0, 1.0) def init_GL(): glutInit ([]) glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) x = 0 y = 0 width = 640 height = 480 glutInitWindowPosition (x, y); glutInitWindowSize (width, height); glutCreateWindow ("test".encode("cp932")) glEnable(GL_DEPTH_TEST) glEnable(GL_CULL_FACE); glCullFace(GL_BACK); def _keyfunc (c, x, y): global Eye_from_x ,Eye_from_y, Eye_from_z,Center_Z if c == "p".encode("cp932"): Center_Z = Center_Z + 5.0 elif c == "l".encode("cp932"): Center_Z = Center_Z - 5.0 elif c == "j".encode("cp932"): Eye_from_x = Eye_from_x + 5.0 elif c == "f".encode("cp932"): Eye_from_x = Eye_from_x - 5.0 elif c == "b".encode("cp932"): Eye_from_z = Eye_from_z + 5.0 elif c == "c".encode("cp932"): Eye_from_z = Eye_from_z - 5.0 elif c == "u".encode("cp932"): Eye_from_y = Eye_from_y + 5.0 elif c == "r".encode("cp932"): Eye_from_y = Eye_from_y - 5.0 elif c == "q".encode("cp932"): sys.exit (0) else: print ("key missed") glutPostRedisplay() def _drawfunc (): green = [0.2, 0.8, 0.3, 1.0] blue = [0.0, 0.0, 1.0, 1.0] red = [1.0, 0.0, 0.0, 1.0] prepare_GL() draw_box() glutSwapBuffers () def _idlefunc (): glutPostRedisplay () #main program loop def main(): global NormalV,Vertex1,Vertex2,Vertex3,NVertex,NodePoint fname = "Zentradi_Battlepod_-_Low_Poly.stl" # "porsche.stl" head,NodePoint,NormalV = BinarySTL(fname) print(NVertex) print(len(NVertex)) print(NodePoint) print(len(NodePoint)) max_x = -99999999999. min_x = 99999999999. max_y = -99999999999. min_y = 99999999999. max_z = -99999999999. min_z = 99999999999. for i in range(len(NodePoint)): if (max_x < NodePoint[i][0]): max_x = NodePoint[i][0] if (min_x > NodePoint[i][0]): min_x = NodePoint[i][0] if (max_y < NodePoint[i][1]): max_y = NodePoint[i][1] if (min_y > NodePoint[i][1]): min_y = NodePoint[i][1] if (max_z < NodePoint[i][2]): max_z = NodePoint[i][2] if (min_z > NodePoint[i][2]): min_z = NodePoint[i][2] print (max_x,min_x) print (max_y,min_y) print (max_z,min_z) Center_X = (max_x+min_x)/2. Center_Y = (max_y+min_y)/2. Center_Z = (max_z+min_z)/2. init_GL() glutKeyboardFunc (_keyfunc) glutDisplayFunc (_drawfunc) glutIdleFunc (_idlefunc) glutMainLoop () if __name__ == '__main__': main()
貼り付け時にカラムがおかしくなってしまっているかも・・・。
今回が左(色を変えました)、前回が右です。うまくいっているようです。
次回は、ODEにおける質量などの情報の付加です。