Added basic OpenGL instancing code. Corrected Geometry::streamWrite().

This commit is contained in:
Angelo Papenhoff 2014-12-25 11:14:36 +01:00
parent c25a7e6f93
commit 1951d063b4
6 changed files with 232 additions and 23 deletions

View File

@ -27,6 +27,9 @@ main(int argc, char *argv[])
c = Rw::Clump::streamRead(in);
in.close();
for(Rw::int32 i = 0; i < c->numAtomics; i++)
Rw::Gl::Instance(c->atomicList[i]);
ofstream out(argv[2], ios::binary);
c->streamWrite(out);
out.close();

View File

@ -125,7 +125,9 @@ Clump::Clump(void)
this->numAtomics = 0;
this->numLights = 0;
this->numCameras = 0;
constructPlugins();
this->atomicList = NULL;
this->lightList = NULL;
this->constructPlugins();
}
Clump::Clump(Clump *c)
@ -133,12 +135,13 @@ Clump::Clump(Clump *c)
this->numAtomics = c->numAtomics;
this->numLights = c->numLights;
this->numCameras = c->numCameras;
copyPlugins(c);
// TODO: atomics and lights
this->copyPlugins(c);
}
Clump::~Clump(void)
{
destructPlugins();
this->destructPlugins();
}
Clump*
@ -169,14 +172,17 @@ Clump::streamRead(istream &stream)
assert(FindChunk(stream, ID_GEOMETRYLIST, NULL, NULL));
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
numGeometries = readInt32(stream);
Geometry **geometryList = new Geometry*[numGeometries];
Geometry **geometryList = 0;
if(numGeometries)
geometryList = new Geometry*[numGeometries];
for(int32 i = 0; i < numGeometries; i++){
assert(FindChunk(stream, ID_GEOMETRY, NULL, NULL));
geometryList[i] = Geometry::streamRead(stream);
}
// Atomics
clump->atomicList = new Atomic*[clump->numAtomics];
if(clump->numAtomics)
clump->atomicList = new Atomic*[clump->numAtomics];
for(int32 i = 0; i < clump->numAtomics; i++){
assert(FindChunk(stream, ID_ATOMIC, NULL, NULL));
clump->atomicList[i] = Atomic::streamReadClump(stream,
@ -185,7 +191,8 @@ Clump::streamRead(istream &stream)
}
// Lights
clump->lightList = new Light*[clump->numLights];
if(clump->numLights)
clump->lightList = new Light*[clump->numLights];
for(int32 i = 0; i < clump->numLights; i++){
int32 frm;
assert(FindChunk(stream, ID_STRUCT, NULL, NULL));
@ -278,7 +285,7 @@ Clump::streamGetSize(void)
size += 12 + this->atomicList[i]->streamGetSize();
// light
for(int32 i = 0; i < this->numAtomics; i++)
for(int32 i = 0; i < this->numLights; i++)
size += 16 + 12 + this->lightList[i]->streamGetSize();
size += 12 + this->streamGetPluginSize();

View File

@ -154,7 +154,7 @@ geoStructSize(Geometry *geo)
size += sizeof(GeoStreamData);
if(Version < 0x34000)
size += 12; // surface properties
if(!(geo->geoflags & 0xFF000000)){
if(!(geo->geoflags & Geometry::NATIVE)){
if(geo->geoflags&geo->PRELIT)
size += 4*geo->numVertices;
for(int32 i = 0; i < geo->numTexCoordSets; i++)
@ -164,10 +164,12 @@ geoStructSize(Geometry *geo)
for(int32 i = 0; i < geo->numMorphTargets; i++){
MorphTarget *m = &geo->morphTargets[i];
size += 4*4 + 2*4; // bounding sphere and bools
if(m->vertices)
size += 3*geo->numVertices*4;
if(m->normals)
size += 3*geo->numVertices*4;
if(!(geo->geoflags & Geometry::NATIVE)){
if(m->vertices)
size += 3*geo->numVertices*4;
if(m->normals)
size += 3*geo->numVertices*4;
}
}
return size;
}
@ -202,12 +204,19 @@ Geometry::streamWrite(ostream &stream)
for(int32 i = 0; i < this->numMorphTargets; i++){
MorphTarget *m = &this->morphTargets[i];
stream.write((char*)m->boundingSphere, 4*4);
writeInt32(m->vertices != NULL, stream);
writeInt32(m->normals != NULL, stream);
if(m->vertices)
stream.write((char*)m->vertices, 3*this->numVertices*4);
if(m->normals)
stream.write((char*)m->normals, 3*this->numVertices*4);
if(!(this->geoflags & NATIVE)){
writeInt32(m->vertices != NULL, stream);
writeInt32(m->normals != NULL, stream);
if(m->vertices)
stream.write((char*)m->vertices,
3*this->numVertices*4);
if(m->normals)
stream.write((char*)m->normals,
3*this->numVertices*4);
}else{
writeInt32(0, stream);
writeInt32(0, stream);
}
}
size = 12 + 4;

View File

@ -18,6 +18,17 @@ using namespace std;
namespace Rw {
namespace Gl {
// VC
// 8733 0 0 0 3
// 45 1 0 0 2
// 8657 1 3 0 2
// 4610 2 1 1 3
// 4185 3 2 1 4
// 256 4 2 1 4
// 201 4 4 1 4
// 457 5 2 0 4
// SA
// 20303 0 0 0 3 vertices: 3 float
// 53 1 0 0 2 texCoords: 2 floats
// 20043 1 3 0 2 texCoords: 2 shorts
@ -28,6 +39,7 @@ namespace Gl {
// 421 5 2 0 4 indices: 4 ubytes
// 12887 6 2 1 4 extracolor:4 ubytes normalized
/*
static void
printAttribInfo(AttribDesc *attribs, int n)
{
@ -38,6 +50,7 @@ printAttribInfo(AttribDesc *attribs, int n)
attribs[i].normalized,
attribs[i].size);
}
*/
void*
DestroyNativeData(void *object, int32, int32)
@ -71,7 +84,7 @@ ReadNativeData(istream &stream, int32, void *object, int32, int32)
}
void
WriteNativeData(ostream &stream, int32 len, void *object, int32, int32)
WriteNativeData(ostream &stream, int32, void *object, int32, int32)
{
Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL);
@ -93,6 +106,180 @@ GetSizeNativeData(void *object, int32, int32)
return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
}
static void
packattrib(uint8 *dst, float32 *src, AttribDesc *a)
{
int8 *i8dst;
uint16 *u16dst;
int16 *i16dst;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8dst = (int8*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
i8dst[i] = src[i];
else if(src[i] > 0.0f)
i8dst[i] = src[i]*127.0f;
else
i8dst[i] = src[i]*128.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i];
else
dst[i] = src[i]*255.0f;
}
break;
case 3: // short
i16dst = (int16*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
i16dst[i] = src[i];
else if(src[i] > 0.0f)
i16dst[i] = src[i]*32767.0f;
else
i16dst[i] = src[i]*32768.0f;
}
break;
case 4: // ushort
u16dst = (uint16*)dst;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
u16dst[i] = src[i];
else
u16dst[i] = src[i]*65535.0f;
}
break;
}
}
// TODO: make pipeline dependent (skin data, night colors)
void
Instance(Atomic *atomic)
{
Geometry *geo = atomic->geometry;
InstanceDataHeader *header = new InstanceDataHeader;
geo->instData = header;
header->platform = PLATFORM_OGL;
header->vbo = 0;
header->ibo = 0;
header->numAttribs = 1 + (geo->numTexCoordSets > 0);
if(geo->geoflags & Geometry::PRELIT)
header->numAttribs++;
if(geo->geoflags & Geometry::NORMALS)
header->numAttribs++;
int32 offset = 0;
header->attribs = new AttribDesc[header->numAttribs];
AttribDesc *a = header->attribs;
// Vertices
a->index = 0;
a->type = 0;
a->normalized = 0;
a->size = 3;
a->offset = offset;
offset += 12;
a++;
// texCoords, only one set here
if(geo->numTexCoordSets){
a->index = 1;
a->type = 3;
a->normalized = 0;
a->size = 2;
a->offset = offset;
offset += 4;
a++;
}
if(geo->geoflags & Geometry::NORMALS){
a->index = 2;
a->type = 1;
a->normalized = 1;
a->size = 3;
a->offset = offset;
offset += 4;
a++;
}
if(geo->geoflags & Geometry::PRELIT){
a->index = 3;
a->type = 2;
a->normalized = 1;
a->size = 4;
a->offset = offset;
offset += 4;
a++;
}
// TODO: skin, extra colors; what to do with multiple coords?
a = header->attribs;
for(int32 i = 0; i < header->numAttribs; i++)
a[i].stride = offset;
header->dataSize = offset*geo->numVertices;
header->data = new uint8[header->dataSize];
memset(header->data, 0xFF, header->dataSize);
uint8 *p = header->data + a->offset;
float32 *vert = geo->morphTargets->vertices;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, vert, a);
vert += 3;
p += a->stride;
}
a++;
if(geo->numTexCoordSets){
p = header->data + a->offset;
float32 *texcoord = geo->texCoords[0];
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, texcoord, a);
texcoord += 2;
p += a->stride;
}
a++;
}
if(geo->geoflags & Geometry::NORMALS){
p = header->data + a->offset;
float32 *norm = geo->morphTargets->normals;
for(int32 i = 0; i < geo->numVertices; i++){
packattrib(p, norm, a);
norm += 3;
p += a->stride;
}
a++;
}
if(geo->geoflags & Geometry::PRELIT){
p = header->data + a->offset;
uint8 *color = geo->colors;
float32 f[4];
for(int32 i = 0; i < geo->numVertices; i++){
f[0] = color[0];
f[1] = color[1];
f[2] = color[2];
f[3] = color[3];
packattrib(p, f, a);
color += 4;
p += a->stride;
}
a++;
}
geo->geoflags |= Geometry::NATIVE;
}
#ifdef RW_OPENGL
void

View File

@ -290,7 +290,7 @@ struct Breakable
};
static void*
destroyBreakableModel(void *object, int32 offset, int32 size)
destroyBreakableModel(void *object, int32 offset, int32)
{
uint8 *p = *PLUGINOFFSET(uint8*, object, offset);
delete[] p;
@ -298,7 +298,7 @@ destroyBreakableModel(void *object, int32 offset, int32 size)
}
static void
readBreakableModel(istream &stream, int32 len, void *object, int32 o, int32 s)
readBreakableModel(istream &stream, int32, void *object, int32 o, int32)
{
uint32 header[13];
uint32 hasBreakable = readUInt32(stream);
@ -334,7 +334,7 @@ readBreakableModel(istream &stream, int32 len, void *object, int32 o, int32 s)
}
static void
writeBreakableModel(ostream &stream, int32 len, void *object, int32 o, int32 s)
writeBreakableModel(ostream &stream, int32, void *object, int32 o, int32)
{
uint32 header[13];
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o);
@ -357,7 +357,7 @@ writeBreakableModel(ostream &stream, int32 len, void *object, int32 o, int32 s)
}
static int32
getSizeBreakableModel(void *object, int32 offset, int32 size)
getSizeBreakableModel(void *object, int32 offset, int32)
{
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset);
if(breakable == NULL)

View File

@ -31,6 +31,9 @@ void ReadNativeData(std::istream &stream, int32 len, void *object, int32, int32)
void WriteNativeData(std::ostream &stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeData(void *object, int32, int32);
void Instance(Atomic *atomic);
// only RW_OPENGL
void UploadGeo(Geometry *geo);
void SetAttribPointers(InstanceDataHeader *inst);