def __init__ ( self, meshName, planeSize, complexity ): self.dirty = True # need to refo calcs self.meshName = meshName self.complexity = complexity self.numFaces = 2 * complexity * complexity self.numVertices = (complexity + 1) * (complexity + 1) self.lastTimeStamp = 0 self.lastAnimationTimeStamp = 0 self.lastFrameTime = 0 ## initialize algorithm parameters self.PARAM_C = 0.3 ## ripple speed self.PARAM_D = 0.4 ## distance self.PARAM_U = 0.05 ## viscosity self.PARAM_T = 0.13 ## time self.useFakeNormals = False ## allocate space for normal calculation self.vNormals=[] for x in range ( self.numVertices * 3 ): self.vNormals.append(0) ## create mesh and submesh self.mesh = ogre.MeshManager.getSingleton().createManual(meshName, ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME) self.subMesh = self.mesh.createSubMesh() self.subMesh.useSharedVertices=False ## Vertex buffers ##self.subMesh.vertexData = ogre.VertexData() self.subMesh.vertexData = ogre.createVertexData() self.subMesh.vertexData.vertexStart = 0 self.subMesh.vertexData.vertexCount = self.numVertices vdecl = self.subMesh.vertexData.vertexDeclaration vbind = self.subMesh.vertexData.vertexBufferBinding vdecl.addElement(0, 0, ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_POSITION) vdecl.addElement(1, 0, ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_NORMAL) vdecl.addElement(2, 0, ogre.VertexElementType.VET_FLOAT2, ogre.VertexElementSemantic.VES_TEXTURE_COORDINATES) ## Prepare buffer for positions - todo: first attempt, slow self.posVertexBuffer = \ ogre.HardwareBufferManager.getSingleton().createVertexBuffer( 3 * ctypes.sizeof(ctypes.c_float), self.numVertices, ogre.HardwareBuffer.HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE) vbind.setBinding(0, self.posVertexBuffer) ## Prepare buffer for normals - write only self.normVertexBuffer = \ ogre.HardwareBufferManager.getSingleton().createVertexBuffer( 3*ctypes.sizeof(ctypes.c_float), self.numVertices, ogre.HardwareBuffer.HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE) vbind.setBinding(1, self.normVertexBuffer) ## Prepare texture coords buffer - static one ## todo: optimize to write directly into buffer texcoordsBufData=array.array('f') for x in range (self.numVertices*2): texcoordsBufData.append(0) for y in range (complexity) : for x in range(complexity) : texcoordsBufData[2*(y*(complexity+1)+x)+0] = float(x) / complexity texcoordsBufData[2*(y*(complexity+1)+x)+1] = 1.0 - (float(y) / (complexity)) texcoordsVertexBuffer = \ ogre.HardwareBufferManager.getSingleton().createVertexBuffer( 2*ctypes.sizeof(ctypes.c_float), self.numVertices, ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY) texcoordsVertexBuffer.writeData(0, texcoordsVertexBuffer.getSizeInBytes(), texcoordsBufData.buffer_info()[0], True) ## true? vbind.setBinding(2, texcoordsVertexBuffer) ## Prepare buffer for indices self.indexBuffer = \ ogre.HardwareBufferManager.getSingleton().createIndexBuffer( ogre.HardwareIndexBuffer.IT_16BIT, 3*self.numFaces, ogre.HardwareBuffer.HBU_STATIC, True) # using a helper object to handle the ctypes implement # Create a buffer object and then lock it faceVertexIndices = buffer ( self.indexBuffer ) faceVertexIndices.lock (0, self.numFaces*3*2, ogre.HardwareBuffer.HBL_DISCARD) for y in range (complexity) : for x in range (complexity ) : twoface = (y*complexity+x)*2*3 # index into buffer p0 = y*(complexity+1) + x p1 = y*(complexity+1) + x + 1 p2 = (y+1)*(complexity+1) + x p3 = (y+1)*(complexity+1) + x + 1 # write a series of bytes faceVertexIndices [ twoface + 0]= p2 faceVertexIndices [ twoface + 1]= p1 faceVertexIndices [ twoface + 2]= p0 faceVertexIndices [ twoface + 3]= p2 faceVertexIndices [ twoface + 4]= p3 faceVertexIndices [ twoface + 5]= p1 self.indexBuffer.unlock() ## Set index buffer for self submesh self.subMesh.indexData.indexBuffer = self.indexBuffer self.subMesh.indexData.indexStart = 0 self.subMesh.indexData.indexCount = 3*self.numFaces # prepare vertex positions # note - we use 3 vertex buffers, since algorighm uses two last phases # to calculate the next one # we need 2 floats, and are going through the loop three times floatStorage = ctypes.c_float * (self.numVertices * 3 ) #self.vertexBuffers = storageclass2 (1.1) # # Change here to use an 'array' for the buffers self.vertexBuffers = [] for x in range (3): if USE_ARRAY: self.vertexBuffers.append( array.array('f') ) for y in range (self.numVertices *3): self.vertexBuffers[x].append(0) else: self.vertexBuffers.append( floatStorage(1.1) ) ## Note that in the C++ code self.vertexBuffers is a float * array[3], whcih indexes into float*numverticies*3 ## we have made a single array bige nough to cope #self.vertexIndexSize = self.numVertices*3 for b in range(3) : for y in range(complexity) : for x in range (complexity) : numPoint = y*(complexity+1) + x VertexPos = 3 * numPoint self.vertexBuffers[b][VertexPos + 0] = float(x) / float(complexity) * float(planeSize) self.vertexBuffers[b][VertexPos + 1] = 0 self.vertexBuffers[b][VertexPos + 2] = float(y) / float(complexity) * float(planeSize) meshBounds = ogre.AxisAlignedBox(0,0,0, planeSize,0, planeSize) self.mesh._setBounds(meshBounds) self.currentBufNumber = 0 if USE_ARRAY: self.posVertexBuffer.writeData(0, self.posVertexBuffer.getSizeInBytes(), ## size self.vertexBuffers[0].buffer_info()[0], True) ## discard? else: self.posVertexBuffer.writeData(0, self.posVertexBuffer.getSizeInBytes(), ## size ctypes.addressof(self.vertexBuffers[0]), True) ## discard? self.mesh.load() self.mesh.touch()
def _prepareMesh(self): self.mesh = ogre.MeshManager.getSingleton().createManual(self.name, ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME) self.subMesh = self.mesh.createSubMesh() self.subMesh.useSharedVertices=False numVertices = 4 if (WaterCircle._first) : # first Circle, create some static common data WaterCircle._first = False #static buffer for position and normals WaterCircle._posnormVertexBuffer =\ ogre.HardwareBufferManager.getSingleton().createVertexBuffer( 6*ctypes.sizeof(ctypes.c_float), #size of one vertex data 4, # number of vertices ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY, # usage False) # no shadow buffer posnormBufData = buffer ( WaterCircle._posnormVertexBuffer ) posnormBufData.lock(ogre.HardwareBuffer.HBL_DISCARD) for i in range (numVertices): posnormBufData[6*i+0]=(float(i%2)-0.5)*WaterCircle.CIRCLE_SIZE; # pos X posnormBufData[6*i+1]=0; # pos Y posnormBufData[6*i+2]=(float(i/2)-0.5)*WaterCircle.CIRCLE_SIZE; # pos Z posnormBufData[6*i+3]=0 ; # normal X posnormBufData[6*i+4]=1 ; # normal Y posnormBufData[6*i+5]=0 ; # normal Z posnormBufData.unlock() #static buffers for 16 sets of texture coordinates for lvl in range ( 16 ): WaterCircle._texcoordsVertexBuffers.append( ogre.HardwareBufferManager.getSingleton().createVertexBuffer( 2*ctypes.sizeof(ctypes.c_float), # size of one vertex data numVertices, # number of vertices ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY, # usage False)) # no shadow buffer texcoordsBufData = buffer( WaterCircle._texcoordsVertexBuffers[lvl]) texcoordsBufData.lock(ogre.HardwareBuffer.HBL_DISCARD) x0 = float(lvl % 4) * 0.25 y0 = float(lvl / 4) * 0.25 y0 = 0.75-y0 # upside down for i in range (4): texcoordsBufData[i*2 + 0]=x0 + 0.25 * float(i%2) texcoordsBufData[i*2 + 1]=y0 + 0.25 * float(i/2) texcoordsBufData.unlock() # Index buffer for 2 faces faces = array.array('H',[2,1,0,2,3,1]) # unsigned short array WaterCircle._indexBuffer =\ ogre.HardwareBufferManager.getSingleton().createIndexBuffer( ogre.HardwareIndexBuffer.IT_16BIT, 6, ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY) WaterCircle._indexBuffer.writeData(0, WaterCircle._indexBuffer.getSizeInBytes(), faces.buffer_info()[0], True); # true? # Initialize vertex data self.subMesh.vertexData = ogre.createVertexData() self.subMesh.vertexData.vertexStart = 0 self.subMesh.vertexData.vertexCount = 4 #first, set vertex buffer bindings vbind = self.subMesh.vertexData.vertexBufferBinding vbind.setBinding(0, WaterCircle._posnormVertexBuffer) vbind.setBinding(1, WaterCircle._texcoordsVertexBuffers[0]) #now, set vertex buffer declaration vdecl = self.subMesh.vertexData.vertexDeclaration vdecl.addElement(0, 0, ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_POSITION); vdecl.addElement(0, 3*ctypes.sizeof(ctypes.c_float), ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_NORMAL); vdecl.addElement(1, 0, ogre.VertexElementType.VET_FLOAT2, ogre.VertexElementSemantic.VES_TEXTURE_COORDINATES); # Initialize index data self.subMesh.indexData.indexBuffer = WaterCircle._indexBuffer self.subMesh.indexData.indexStart = 0 self.subMesh.indexData.indexCount = 6 # set mesh bounds circleBounds = ogre.AxisAlignedBox (-WaterCircle.CIRCLE_SIZE/2.0, 0, -WaterCircle.CIRCLE_SIZE/2.0, WaterCircle.CIRCLE_SIZE/2.0, 0, WaterCircle.CIRCLE_SIZE/2.0) self.mesh._setBounds(circleBounds) self.mesh.load() self.mesh.touch()
def createGrassMesh(self): global GRASS_MESH_NAME self.SetToNone = [] ## Each grass section is 3 planes at 60 degrees to each other ## Normals point straight up to simulate correct lighting msh = ogre.MeshManager.getSingleton().createManual(GRASS_MESH_NAME, ogre.ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME) self.msh = msh self.hw = ogre.HardwareBufferManager.getSingleton() sm = msh.createSubMesh() sm.useSharedVertices = False self.vertexdata = ogre.createVertexData() ## Create the VertexData Object ## NOTE the submesh will delete the vertexData when it is destroyed which is BAD -- ie we have C++ specifically ## deleting a Python object which makes everything confused.. The fix is to set the submesh vertexData to ## 'None' before exiting -- see the __del__ function sm.vertexData = self.vertexdata sm.vertexData.vertexStart = 0 sm.vertexData.vertexCount = 12 dcl = sm.vertexData.vertexDeclaration offset = 0 dcl.addElement(0, offset, ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_POSITION) offset += ogre.VertexElement.getTypeSize(ogre.VertexElementType.VET_FLOAT3) dcl.addElement(0, offset, ogre.VertexElementType.VET_FLOAT3, ogre.VertexElementSemantic.VES_NORMAL) offset += ogre.VertexElement.getTypeSize(ogre.VertexElementType.VET_FLOAT3) dcl.addElement(0, offset, ogre.VertexElementType.VET_FLOAT2, ogre.VertexElementSemantic.VES_TEXTURE_COORDINATES) offset += ogre.VertexElement.getTypeSize(ogre.VertexElementType.VET_FLOAT2) vbuf = ogre.HardwareBufferManager.getSingleton().createVertexBuffer( offset, 12, ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY) #lock the buffer and get a pointer to the data pointer = vbuf.lock(ogre.HardwareBuffer.HBL_DISCARD) baseVec = ogre.Vector3(GRASS_WIDTH/2, 0, 0) vec = baseVec rot = ogre.Quaternion () rot.FromAngleAxis(ogre.Degree(d=60), ogre.Vector3().UNIT_Y) # change from the C++ demo - we build a buffer and then write it in one go buffer=[] for i in range ( 3 ) : ## position buffer.append( -vec.x ) buffer.append( GRASS_HEIGHT ) buffer.append( -vec.z ) ## normal buffer.append( 0 ) buffer.append( 1 ) buffer.append( 0 ) ## uv buffer.append( 0 ) buffer.append( 0 ) ## position buffer.append( vec.x ) buffer.append( GRASS_HEIGHT ) buffer.append( vec.z ) ## normal buffer.append( 0 ) buffer.append( 1 ) buffer.append( 0 ) ## uv buffer.append( 1 ) buffer.append( 0 ) ## position buffer.append( -vec.x ) buffer.append( 0 ) buffer.append( -vec.z ) ## normal buffer.append( 0 ) buffer.append( 1 ) buffer.append( 0 ) ## uv buffer.append( 0 ) buffer.append( 1 ) ## position buffer.append( vec.x ) buffer.append( 0 ) buffer.append( vec.z ) ## normal buffer.append( 0 ) buffer.append( 1 ) buffer.append( 0 ) ## uv buffer.append( 1 ) buffer.append( 1 ) vec = rot * vec ## Python-Ogre extension function to write a list of floats to a buffer ogre.setFloat( pointer, buffer ) vbuf.unlock() sm.vertexData.vertexBufferBinding.setBinding(0, vbuf) sm.indexData.indexCount = 6*3 sm.indexData.indexBuffer = ogre.HardwareBufferManager.getSingleton().createIndexBuffer( ogre.HardwareIndexBuffer.IT_16BIT, sm.indexData.indexCount, ogre.HardwareBuffer.HBU_STATIC_WRITE_ONLY) pointer = sm.indexData.indexBuffer.lock(ogre.HardwareBuffer.HBL_DISCARD) ## here is one way to do this using a Python-Ogre helper function # # buff=[] # # for i in range ( 3 ): # # off = i*4 # # buff.append( 0 + off ) # # buff.append( 3 + off ) # # buff.append( 1 + off ) # # # # buff.append( 0 + off ) # # buff.append( 2 + off ) # # buff.append( 3 + off ) # # # # # another Python-Ogre helper function to write unsigned ints to a buffer # # ogre.setUint16( pointer, buff ) ## Here is a way to do it with ctypes.... pVert= ( ctypes.c_uint16 * (sm.indexData.indexCount)).from_address ( ogre.castAsInt ( pointer ) ) index = 0 for i in range ( 3 ): off = i*4 pVert[ index ] = 0 + off index +=1 pVert[ index ] = 3 + off index +=1 pVert[ index ] = 1 + off index +=1 pVert[ index ] = 0 + off index +=1 pVert[ index ] = 2 + off index +=1 pVert[ index ] = 3 + off index +=1 sm.indexData.indexBuffer.unlock() sm.setMaterialName(GRASS_MATERIAL) msh.load() ## we need to keep access to the submesh so we can set .vertexData to None at exit (see __del__ ) self.sm = sm