Author: JonNeal Date: 2008-07-14 21:51:02 -0400 (Mon, 14 Jul 2008) New Revision: 1308
Modified: trunk/pysoy/config.py trunk/pysoy/examples/LandScape.py trunk/pysoy/include/soy.scenes.pxd trunk/pysoy/setup.py trunk/pysoy/src/scenes/Landscape.pym Log: Ticket #929: changed around Landscape.pym and Landscape.py a whole lot. Got it half working! Renders landscape esque thing, lots of work to be done though. Modified: trunk/pysoy/config.py =================================================================== --- trunk/pysoy/config.py 2008-07-12 21:08:42 UTC (rev 1307) +++ trunk/pysoy/config.py 2008-07-15 01:51:02 UTC (rev 1308) @@ -61,7 +61,7 @@ 'materials' : ['gl', 'glew'], 'models' : ['glew', 'gl', 'glu', 'ode'], 'textures' : ['glew', 'gl', 'theora', 'ogg', 'cairo'], - 'scenes' : ['gl', 'ode'], + 'scenes' : ['glew', 'gl', 'ode'], 'shapes' : ['ode'], 'transports' : ['ogg'], 'widgets' : ['glew', 'gl', 'glu'], Modified: trunk/pysoy/examples/LandScape.py =================================================================== --- trunk/pysoy/examples/LandScape.py 2008-07-12 21:08:42 UTC (rev 1307) +++ trunk/pysoy/examples/LandScape.py 2008-07-15 01:51:02 UTC (rev 1308) @@ -3,47 +3,66 @@ import soy from time import sleep - ### Start Heightmap Code -heightTex = soy.transports.File('media/white.soy')['gimp'] +heightTex = soy.transports.File('media/Heightmap.soy')['gimp'] sleep(2) # HACK: this will wait while transportloop does his stuff -heightScene = soy.scenes.Landscape(heightTex,soy.materials.Material()) -#sce = soy.scenes.Scene() +heightScene = soy.scenes.Landscape(heightTex,soy.materials.Material(),height=100) #heightScene = soy.scenes.Scene();# with normal scene, everything is peachy ### Start PySoy Code (Excerpt from pysoy-primer.py) # Initialize a window - scr = soy.Screen() -win = soy.Window(scr, "A Spinning Cube") +win = soy.Window(scr, "A cube and landscape") # Create a cube with a shape, material and a body. cube = soy.shapes.Box(1, 1, 1) # Step 1: Shape mat = soy.materials.Material() # Step 2: Material mat.shininess = 5 # (Optional) Looks nicer (modifies the applied specular lighting; play with this setting to see how it affects appearance) -body = soy.bodies.Body(scene=heightScene, model=soy.models.Shape(mat), shape=cube, position=(0,-2,0)) # Step 3: Body - +body = soy.bodies.Body(scene=heightScene, model=soy.models.Shape(mat), shape=cube, position=(0,5,0)) # Step 3: Body +global camera # Put a light and camera into the initialized screen light = soy.bodies.Light(heightScene) camera = soy.bodies.Camera(heightScene) -#stx = soy.widgets.StackX(win) -#pro = soy.widgets.Projector(stx, camera=camera) -#cam2 = soy.bodies.Camera(sce) -#cam2.position = (-0.3, 0.0, 15.0) -#pro2 = soy.widgets.Projector(stx, camera=cam2) - pro = soy.widgets.Projector(win, camera=camera) -#lig = soy.bodies.Light(sce) -#lig.position = (-10.0,10.0,2.0) -camera.position = (0, -2, 5.0) #50? +camera.position = (0, 1, 250.0) #50? light.position = (0.5, 1.0, 5.0) -#heightScene.gravity = (0,-1,0) -#mat=soy.materials.Material() -#a=soy.bodies.Body(scene=sce,model=soy.models.Shape(mat),shape=soy.shapes.Box(2,1,2),position=(0,-1.2,-1)) +heightScene.gravity = (0,-1,0) +def addx() : + global camera + camera.position[0] += 1 +def addy() : + global camera + camera.position[1] += 1 +def addz(): + global camera + camera.position[2] += 1 +def subz(): + global camera + camera.position[2] -= 1 +def subx() : + global camera + camera.position[0] -= 1 +def suby(): + camera.position[1] -= 1 +def toggleWireframe(): + camera.wireframe = not camera.wireframe + +key = soy.controllers.Keyboard(win) +key['R'] = addy #up +key['Q'] = subx #left +key['T'] = suby #down +key['S'] = addx #right +key['V'] = addz #pgup +key['U'] = subz #pgdwn +key['w'] = toggleWireframe +key['q'] = soy.actions.Quit() +key[ 1 ] = soy.actions.Quit() # 9 = esc key +wcn = soy.controllers.Window(win) +wcn['close'] = soy.actions.Quit() + if __name__ == "__main__": #mainloop goes here while 1: - sleep(1) - #print body.position #annoying + sleep(0.1) Modified: trunk/pysoy/include/soy.scenes.pxd =================================================================== --- trunk/pysoy/include/soy.scenes.pxd 2008-07-12 21:08:42 UTC (rev 1307) +++ trunk/pysoy/include/soy.scenes.pxd 2008-07-15 01:51:02 UTC (rev 1308) @@ -82,13 +82,15 @@ cdef int _width cdef int _depth cdef int _height + cdef soy.textures.Texture _heightmapTex cdef gl.GLuint _buffer cdef gl.GLuint _elementbuffer - cdef void _createBuffer ( self ) + cdef int _position[3] cdef int _verts cdef Vert* _vertArray cdef Face* _elementArray - cdef gl.GLfloat* vertices[72] + cdef void _createBuffer ( self ) + cdef void _createArrays ( self ) cdef class Planar (Scene) : cdef ode.dGeomID _planeID Modified: trunk/pysoy/setup.py =================================================================== --- trunk/pysoy/setup.py 2008-07-12 21:08:42 UTC (rev 1307) +++ trunk/pysoy/setup.py 2008-07-15 01:51:02 UTC (rev 1308) @@ -46,7 +46,7 @@ 'materials' : ['GL','GLEW'], 'models' : ['GLEW','GL','GLU','ode'], 'textures' : ['GLEW','GL', 'theora', 'ogg', 'cairo'], - 'scenes' : ['GL', 'ode'], + 'scenes' : ['GLEW', 'GL', 'ode'], 'shapes' : ['ode'], 'transports' : ['ogg'], 'widgets' : ['GLEW','GL','GLU'], Modified: trunk/pysoy/src/scenes/Landscape.pym =================================================================== --- trunk/pysoy/src/scenes/Landscape.pym 2008-07-12 21:08:42 UTC (rev 1307) +++ trunk/pysoy/src/scenes/Landscape.pym 2008-07-15 01:51:02 UTC (rev 1308) @@ -17,12 +17,12 @@ # # $Id$ - cdef class Landscape (Scene) : ''' Landscape Scene This is a scene based on a heightmap. - Accepts a heightmap with the detail of it, the width, depth, and height of it. + Accepts a heightmap with the detail of it, the width, depth, and height, and + the position in the form of a dict (x, y, z) ''' ############################################################################ @@ -30,111 +30,152 @@ # Python functions # - def __cinit__(self, soy.textures.Texture heightmap,soy.materials.Material mat, detail = 1, width=1024, depth=1024, height=1024, *args, **kw) : - cdef int _i, _j - cdef double _value - if not isinstance(heightmap, soy.textures.Texture) or heightmap._chans != 1 : - raise TypeError('Heightmap must be of type soy.textures.Texture and 1 channel, not '+str(heightmap._chans)) + def __cinit__(self, soy.textures.Texture heightmap,soy.materials.Material mat, \ + detail = 1, width=1024, depth=1024, height=1024, position=(0, 0, 0), *args, **kw) : + assert isinstance(heightmap, soy.textures.Texture) or heightmap._chans != 1, \ + "Heightmap must be of type soy.textures.Texture and 1 channel, not "+str(heightmap._chans) + assert type(position[0]) == int or type(position[1]) == int or \ + type(position[2]) == int, "The heightmap position must be an int" #We need to make an array on the heap, and put the verts there - stdio.printf("Cinit Start!\n"); - # Now we need to define the vars somehow (like px py pz, tx ty ...) - self._verts = 0 + self._buffer = 0 + self._elementbuffer = 0 self._width = width self._depth = depth self._height = height + self.position = position self._heightmapID = ode.dGeomHeightfieldDataCreate() - self._vertArray = <Vert *> py.PyMem_Malloc((heightmap._width*heightmap._height/detail)*16*4) - self._elementArray = <Face *> py.PyMem_Malloc(sizeof(Face)*((heightmap._width*heightmap._height/detail))/3) #21k*Face - #for _i from 0 < _i < 72: + self._vertArray = <Vert *> py.PyMem_Malloc(heightmap._width*heightmap._height*16*4) + self._elementArray = <Face *> py.PyMem_Malloc(sizeof(Face)*((heightmap._width-1)*(heightmap._height-1)*2)) ode.dGeomHeightfieldDataBuildByte(self._heightmapID, <unsigned char*> heightmap._texels, 0, heightmap._width, heightmap._depth, self._width/heightmap._width, self._depth/heightmap._depth, 1, 0, 1, 0) - self._heightmap = ode.dCreateHeightfield(self._spaceID, self._heightmapID, 1) - ##Setup Arrays Here - for _i from 1 <= _i < heightmap._width : - for _j from 1 <= _j < heightmap._height : - self._verts +=1 - # Get the y value here - _value = heightmap._texels[heightmap._width*(_i-1)+_j] - #stdio.printf("%d\n",value) - #yea, so now value*scale got - _value = _value/255.0 #255 is max, so if the value == 255(white) then its a 1 for high, thats mul'ed by height - self._vertArray[heightmap._width*(_i-1)+_j].px = _i - self._vertArray[heightmap._width*(_i-1)+_j].pz = _j - self._vertArray[heightmap._width*(_i-1)+_j].py = _value - self._vertArray[heightmap._width*(_i-1)+_j].tx = 0 - self._vertArray[heightmap._width*(_i-1)+_j].ty = 1 - self._vertArray[heightmap._width*(_i-1)+_j].tz = 0 - self._vertArray[heightmap._width*(_i-1)+_j].nx = 0 - self._vertArray[heightmap._width*(_i-1)+_j].ny = 1 - self._vertArray[heightmap._width*(_i-1)+_j].nz = 0 - #stdio.printf("%f\n", _value); - #Make a Step for the above loops, or make a loop for making the faces - #I think we need to make the element array generation code here - _i = 0 - for _i from 1 <= _i < ((heightmap._width*heightmap._height/detail))/3: - - self._elementArray[_i].a = (_i*3)-2 - self._elementArray[_i].b = (_i*3)-1 - self._elementArray[_i].c = (_i*3) - #stdio.printf("index :%d, A: %d, B: %d, C: %d\n",_i,self._elementArray[_i].a,self._elementArray[_i].b,self._elementArray[_i].c); - stdio.printf("Cinit Done!\n"); + self._heightmap = ode.dCreateHeightfield(self._spaceID, self._heightmapID, 1) #the ode heightmap + self._heightmapTex = heightmap + self._createArrays() def __dealloc__(self) : - ode.dGeomHeightfieldDataDestroy(self._heightmapID) + pass + #ode.dGeomHeightfieldDataDestroy(self._heightmapID) #gl.glDeleteBuffersARB(1, &self._buffer); ############################################################################ # + # Properties + # + + property position : + '''Landscape's Position + ''' + def __get__(self) : + return (self._position[0], self._position[1], self._position[2]) + def __set__(self, value) : + assert type(value) != tuple or type(value) != list, \ + "Must provide a tuple or list for landscape position!" + assert len(value) == 3, "Must provide (x,y,z)" + self._position[0] = value[0] + self._position[1] = value[1] + self._position[2] = value[2] + + ############################################################################ + # # General C functions # + cdef void _createArrays(self) : + cdef int _i, _j, _currentLoop + cdef double _x, _y, _z + # set up the vert array + for _i from 0 <= _i < self._heightmapTex._height : + for _j from 0 <= _j < self._heightmapTex._width : + # Get the y value here + _y = self._heightmapTex._texels[self._heightmapTex._width*_i+_j] + #divide by width to get what percentage it is of width, then multiply by width wanted + _x = _j / 1.0 / self._heightmapTex._width * self._width + self._position[0] + _y = _y / 255.0 * self._height + self._position[1] + _z = _i / 1.0 / self._heightmapTex._height * self._depth + self._position[2] + self._vertArray[self._heightmapTex._width*_i+_j].px = _x + self._vertArray[self._heightmapTex._width*_i+_j].pz = _z + self._vertArray[self._heightmapTex._width*_i+_j].py = _y + #all below need to be calculated CORRECTLY! + self._vertArray[self._heightmapTex._width*_i+_j].tx = 0 + self._vertArray[self._heightmapTex._width*_i+_j].ty = 1 + self._vertArray[self._heightmapTex._width*_i+_j].tz = 0 + self._vertArray[self._heightmapTex._width*_i+_j].ux = 0 + self._vertArray[self._heightmapTex._width*_i+_j].uy = 1 + self._vertArray[self._heightmapTex._width*_i+_j].uz = 0 + self._vertArray[self._heightmapTex._width*_i+_j].nx = 0 + self._vertArray[self._heightmapTex._width*_i+_j].ny = 1 # Up + self._vertArray[self._heightmapTex._width*_i+_j].nz = 0 + #clear vars for next loops! + _i = 0 + _j = 0 + _currentLoop = 0 + #loop through all of the quads in the grid + for _i from 0 <= _i < self._heightmapTex._height-1 : + for _j from 0 <= _j < self._heightmapTex._width-1 : + #create the upper left tri in the quad + #verts are in counter clockwise direction + self._elementArray[_currentLoop*2].a = _j + 1 + _i * self._heightmapTex._width + self._elementArray[_currentLoop*2].b = _j + _i * self._heightmapTex._width + self._elementArray[_currentLoop*2].c = _j + (_i+1) * self._heightmapTex._width + #now the bottom right! + self._elementArray[_currentLoop*2+1].a = _j + 1 + _i * self._heightmapTex._width + self._elementArray[_currentLoop*2+1].b = _j + (_i+1) * self._heightmapTex._width + self._elementArray[_currentLoop*2+1].c = _j + 1 + (_i+1) * self._heightmapTex._width + _currentLoop = _currentLoop + 1 + + cdef void _createBuffer(self) : - stdio.printf("createBuffer Start!\n"); - - cdef void _render(self) : - stdio.printf("%s","_render\n") - gl.glGenBuffersARB(1, <gl.GLuint*> &self._buffer) # Create the vertex buffers? + gl.glGenBuffersARB(1, <gl.GLuint*> &self._buffer) # Create the vertex buffers gl.glBindBufferARB(gl.GL_ARRAY_BUFFER_ARB, <gl.GLuint> self._buffer) - gl.glBufferDataARB(gl.GL_ARRAY_BUFFER_ARB, (sizeof(Vert)*self._verts), - self._vertArray, gl.GL_STATIC_DRAW_ARB) + gl.glBufferDataARB(gl.GL_ARRAY_BUFFER_ARB, (sizeof(Vert)* + self._heightmapTex._width*self._heightmapTex._height), self._vertArray, + gl.GL_STATIC_DRAW_ARB) gl.glGenBuffersARB(1, &self._elementbuffer) gl.glBindBufferARB(gl.GL_ELEMENT_ARRAY_BUFFER_ARB, self._elementbuffer) # Create the elements buffers - gl.glBufferDataARB(gl.GL_ELEMENT_ARRAY_BUFFER_ARB, self._verts/3, - self._elementArray, gl.GL_STATIC_DRAW_ARB) - #gl.glGenBuffersARB(1, &self._buffer); - #gl.glBindBufferARB(gl.GL_ARRAY_BUFFER_ARB, self._buffer); - #gl.glBufferDataARB(gl.GL_ARRAY_BUFFER_ARB, sizeof(vertices), <gl.GLvoid*>0, gl.GL_STATIC_DRAW_ARB); - #gl.glBufferSubDataARB(gl.GL_ARRAY_BUFFER_ARB, 0, sizeof(vertices), vertices); - #gl.glBindBufferARB(gl.GL_ARRAY_BUFFER_ARB, _buffer) - gl.glVertexPointer (3, gl.GL_FLOAT, sizeof(Vert), <float*> 0) - gl.glNormalPointer ( gl.GL_FLOAT, sizeof(Vert), <float*> 12) - #gl.glNormalPointer(gl.GL_FLOAT, 0, <gl.GLvoid *>0); - gl.glTexCoordPointer(3, gl.GL_FLOAT, sizeof(Vert), <float*> 24) - #gl.glDrawArrays(gl.GL_QUADS, 0, 24); - stdio.printf("%s","glDrawElements\n") - gl.glDrawElements (gl.GL_TRIANGLES, 20, - gl.GL_UNSIGNED_SHORT, <Face*> 0)#self._elementArray) + gl.glBufferDataARB(gl.GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(Face)*(self._heightmapTex._width-1)*(self._heightmapTex._height-1)*2, self._elementArray, gl.GL_STATIC_DRAW_ARB) + + + cdef void _render(self) : + if self._buffer: + py.PyMem_Free(self._elementArray) # The arrays are in Vram so lets free it in system mem + py.PyMem_Free(self._vertArray) + self._elementArray = NULL; # Make the pointer NULL so UB doesn't occur in free() + self._vertArray = NULL; + gl.glBindBufferARB(gl.GL_ARRAY_BUFFER_ARB, <gl.GLuint> self._buffer) # Bind to buffer for rendering below + gl.glBindBufferARB(gl.GL_ELEMENT_ARRAY_BUFFER_ARB, self._elementbuffer) + else: + self._createBuffer() + gl.glVertexPointer (3, gl.GL_FLOAT, sizeof(Vert), <float*> 0) #px py pz + gl.glNormalPointer ( gl.GL_FLOAT, sizeof(Vert), <float*> 12) # nx ny nz + gl.glTexCoordPointer(3, gl.GL_FLOAT, sizeof(Vert), <float*> 24) # tx ty tz + #gl.glDrawArrays(gl.GL_TRIANGLES, 0, self._verts); + #stdio.printf("%s","glDrawElements\n") + gl.glDrawElements (gl.GL_TRIANGLES, (self._heightmapTex._width-1)*(self._heightmapTex._height-1)*2, + gl.GL_UNSIGNED_SHORT, <Face*> 3) gl.glBindBufferARB(gl.GL_ARRAY_BUFFER_ARB, 0); + Scene._render(self) - stdio.printf("Render Done!\n"); """ -TODO : -- First Get it to render -- Divide data in to sectors -- get Sectors middle point +TODO : LOD +- First Get it to render | 3/4 there :P +- Divide data in to sectors | +- get Sectors middle point | - Relative to the sector distance to camera, calculate LOD value - Apply LOD algo using value + -elementsArray has to be reduced using LOD value + -verticies will still be in VRAM, but we're not gonna draw them, so its still optimized. +IRC excerpt, LOD algo basis yea - the size of the number of triangles times three + the size of the number of triangles times three its one big block to you since a landscape will have *one* material - Z texcoord can be used to change the terrain type -this means that you can use the face array for LOD more easily + Z texcoord can be used to change the terrain type (3d texture) +this means that you can use the face array for LOD more easily(elementsArray.. after this i get confused) see basically you can "shift up" the array, adding one to both the offset and length, such that the "base" face array is the lowest resolution and each time you shift up one it removes one triangle and replaces it with two is, if your array has four triangles in the low resolution, ABCD and the second step is A split = EF, B=GH, C=IJ, D=KL, then it's arranged as: @@ -145,4 +186,4 @@ if you try to do this on a one polygon basis you'll end up rendering too many. its easier to group them in each group give the most radical angles the highest priority - so a steep angled triangle would be D in the above example er, sorry, the steepest would be A -""" \ No newline at end of file +""" _______________________________________________ PySoy-SVN mailing list PySoy-SVN@pysoy.org http://www.pysoy.org/mailman/listinfo/pysoy-svn