Panda3D Manual: Vertices in Panda3D
<<prev | top | next>>
## How Panda Stores Vertex Information As with any major 3D engine, geometry in Panda3D is primarily defined by vertices. So before we discuss how to actually make geometry we have to discuss how Panda3D handles them.The following information only applies to Panda3D 1.1. For more information you can visit the Panda Developers Wiki ## Vertex Format In order to define a vertex Panda3D has to know what format the vertex has. The format decides what information the vertex can store(such as color, texture coordinate, normals, etc..). That information is stored in an object from the `GeomVertexFormat` class. Panda3D comes with several predefined formats which you can get from the `GeomVertexFormat.get*()` family of functions. The naming format for these functions are:
V3 | This means the position of the vertex is encoded in the format. All formats begin with this.
n3 | This means the normal (3 components) of each vertex is encoded in the format.
cp or c4 | This means the color of each vertex is encoded in the format. cp means the color will be packed DirectX style while c4 means the color will be stored in four bytes, OpenGL style. Panda will automatically convert the types at runtime if you are not using the native backend (cp for OpenGl or c4 for DirectX).
t2 | This means the texture coordinates (2 components) of each vertex are encoded in the format.
You can omit options you dont want but the formats have to be added in the order listed above. For example:
#this is valid GeomVertexFormat.getV3n3() #this isnt valid(V3 must always come first) GeomVertexFormat.getn3V3() #this is valid GeomVertexFormat.getV3cpt2() #this isnt valid (color must come before texture) GeomVertexFormat.getV3t2cp() #this is plain wrong GeomVertexFormat.getcpV3t2n3()
## Making Your Own Custom Format In addition to the formats that come with Panda you can define your own. However this is advance usage and will only be touched upon here. See the Panda 1.1 documentation (which should be out soon) for more information. `GeomVertexFormat` is really a container of `GeomVertexArrayFormat` objects.These objects are made up of `GeomVertexColumn` objects which describe what attributes the format encodes in the vertices. Having one `GeomVertexArrayFormat` object with all the `GeomVertexColumn` objects is practically the same as having a seperate `GeomVertexArrayFormat` object for each `GeomVertexColumn`. The following example should make things clearer:
format=GeomVertexFormat() formatArray=GeomVertexArrayFormat() #we use the addColumn(name, numComponents, NumericType, Contents) function #Contents tell Panda how to update the information, if neccessary #i.e. if you apply a transformation to this geometry all columns that have #Geom.CPoint for Contents will be updated appropriately #the hard way to get the V3n3cpt2 format formatArray.addColumn(InternalName.make("vertex"), 3,Geom.NTFloat32, Geom.CPoint) formatArray.addColumn(InternalName.make("color"), 4,Geom.NTPackedDcba, Geom.CColor) formatArray.addColumn(InternalName.make("normal"), 3,Geom.NTFloat32, Geom.CVector) formatArray.addColumn(InternalName.make("texcoord"), 2,Geom.NTFloat32, Geom.CTexcoord) #if we can keep adding more GeomVertexArrayFormat objects as long as none of #the columns have the same name format.addArray(formatArray) #we have to register formats before we use them. format=GeomVertexFormat.registerFormat(format) #now format can be used just as any other GeomVertexFormat
None of the `GeomVertexArrayFormat` objects can have `GeomVertexColumn` objects with the same name. Furthermore, the column names "vertex", "color", "normal", and "texcoord" are the only attributes that directly map to their counterpart ("vertex" will hold the current position of the vertex in Panda, "color" will hold the current color assigned through Panda, etc...). The standard formats above are already setup to use these default names. Any attributes you add other than these have no meaning to Panda (not unlike the `setTag` interface for NodePaths). ## Vertex Data `GeomVertexData` objects are used to hold the information encoded in vertices. They have a row for each vertex and a column for each attribute the vertex should have (i.e. color, etc...). You need to have at least one of these objects before you can make any vertices of your own. You can create them using `GeomVertexData(name, format, usageHint)`. `name` is just the arbitrary name you want to give it. `format` is an object from the `GeomVertexFormat` class. This lets the `GeomVertexData` object know how many columns it should have. The last parameter `usageHint` tells Panda what optimizations it can perform on the vertices in this `GeomVertexData` object. The types of usage hints are:
Geom.UHClient | Don't attempt to upload the data; always keep it on the client. This is used for very special purposes only; typically you would use Geom.UHStream instead.
Geom.UHStream | For objects that are going to be rendered a few times and then discarded.
Geom.UHDynamic | For objects that will have their data modified by the program.
Geom.UHStatic | For objects that will not have their state change during the program (This does not count animations or scene graph transformations).
These hints are ordered from most dynamic to most static. The most common usage hint, by far, is `Geom.UHStatic`; if you have any uncertainty, you should probably use this one. Using the constructor is the only functionality of the `GeomVertexData` class that you should really use. Use `GeomVertexReader` to read the information in a `GeomVertexData` object or `GeomVertexWriter` to change/add information (both classes are discussed below). An example:
format=GeomVertexFormat.getV3n3cpt2() #use this if you want to create vertices whose information wont change often myVertexData=GeomVertexData("holds my vertices", format, Geom.UHStatic)
## Reading and Writing Vertex Information Messing around directly with `GeomVertexData` objects directly leaves a lot of room for error. The preferred way to read/write information from/to a `GeomVertexData` object is to use the `GeomVertexReader` and `GeomVertexWriter` classes. Both are optimized for reading/writing down the same column (the same attribute). You can change columns if you need to using their `setColumn` functions, but if you have to change columns often it is more efficient to create multiple `GeomVertexReader`/`GeomVertexWriter` objects, one for each column. Whenever you perform a read/write function with these classes they automatically move down to the next row (next vertex). You can get the row you are currently on by calling `getReadRow()` and `getWriteRow()` respectively. You can also set the row using the `setRow(newRow)` function for both classes. To find out if you are at the end of column use `isAtEnd()`. If you are reading and writing at the same time you must create the `GeomVertexWriter` objects before `GeomVertexReader` objects. However using the class `GeomVertexRewriter`, which has the functionality of both classes, is the preferred way to read/write data at the same time. ## GeomVertexWriter This class has two sets of functions. The `setData*(...)` functions will crash if you try to write when `isAtEnd()` is True. Use this set of functions if you wish to modify the vertices in a `GeomVertexData` object but not add to them. The `addData*(...)` functions will automatically add a row to the `GeomVertexData` object if it reaches the end. The syntax is the same for both sets of functions. You have `setData` or `addData` followed by the number of components (1,2,3 or 4) and then followed by the type(i for integer or f for float). For example:
#assume a V3n3cpt2 format #the constructor takes the GeomVertexData object you want to modify and the column you want #to go down. If you dont specify the column you start out at the zeroth column in vdata. myWriter=GeomVertexWriter(vdata, "vertex") #this will crash if there are no vertices myWriter.setData3f(0.0,0.0,0.0) #this will work no matter what myWriter.addData3f(0.0, 0.0, 0.0) #now we want to edit the texture coordinats myWriter=GeomVertexWriter(vdata, "texcoord") #now we use addData2f instead since this is only two components myWriter.addData2f(0.0,0.0)
All the `setData` and `addData` functions have a vector counterpart where appropriate. ## GeomVertexReader This class only has one set of functions, the `getData*(....)` functions. Their naming syntax follows the same rules as the `setData` and `addData` functions but you can only use "f" as the type. The `getData*(...)` functions all return vecotrs of the appropriate type when neccessary (Vec4 for four components, but just the number for one component attributes). A brief example:
#assume a V3n3cpt2 format #the constructor takes the GeomVertexData object you want to read and the column you want #to go down. If you dont specify the column you start out at the zeroth column in vdata. myReader=GeomVertexReader(vdata, "vertex") #this will crash if there are no vertices position=myReader.getData3f() #now we want to read the texture coordinats myReader=GeomVertexReader(vdata, "texcoord") #now we use getData2f instead since this is only two components texcoord=myReader.getData2f()
<<prev | top | next>>