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); c = Rw::Clump::streamRead(in);
in.close(); in.close();
for(Rw::int32 i = 0; i < c->numAtomics; i++)
Rw::Gl::Instance(c->atomicList[i]);
ofstream out(argv[2], ios::binary); ofstream out(argv[2], ios::binary);
c->streamWrite(out); c->streamWrite(out);
out.close(); out.close();

View File

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

View File

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

View File

@ -18,6 +18,17 @@ using namespace std;
namespace Rw { namespace Rw {
namespace Gl { 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 // 20303 0 0 0 3 vertices: 3 float
// 53 1 0 0 2 texCoords: 2 floats // 53 1 0 0 2 texCoords: 2 floats
// 20043 1 3 0 2 texCoords: 2 shorts // 20043 1 3 0 2 texCoords: 2 shorts
@ -28,6 +39,7 @@ namespace Gl {
// 421 5 2 0 4 indices: 4 ubytes // 421 5 2 0 4 indices: 4 ubytes
// 12887 6 2 1 4 extracolor:4 ubytes normalized // 12887 6 2 1 4 extracolor:4 ubytes normalized
/*
static void static void
printAttribInfo(AttribDesc *attribs, int n) printAttribInfo(AttribDesc *attribs, int n)
{ {
@ -38,6 +50,7 @@ printAttribInfo(AttribDesc *attribs, int n)
attribs[i].normalized, attribs[i].normalized,
attribs[i].size); attribs[i].size);
} }
*/
void* void*
DestroyNativeData(void *object, int32, int32) DestroyNativeData(void *object, int32, int32)
@ -71,7 +84,7 @@ ReadNativeData(istream &stream, int32, void *object, int32, int32)
} }
void void
WriteNativeData(ostream &stream, int32 len, void *object, int32, int32) WriteNativeData(ostream &stream, int32, void *object, int32, int32)
{ {
Geometry *geometry = (Geometry*)object; Geometry *geometry = (Geometry*)object;
assert(geometry->instData->platform == PLATFORM_OGL); assert(geometry->instData->platform == PLATFORM_OGL);
@ -93,6 +106,180 @@ GetSizeNativeData(void *object, int32, int32)
return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize; 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 #ifdef RW_OPENGL
void void

View File

@ -290,7 +290,7 @@ struct Breakable
}; };
static void* static void*
destroyBreakableModel(void *object, int32 offset, int32 size) destroyBreakableModel(void *object, int32 offset, int32)
{ {
uint8 *p = *PLUGINOFFSET(uint8*, object, offset); uint8 *p = *PLUGINOFFSET(uint8*, object, offset);
delete[] p; delete[] p;
@ -298,7 +298,7 @@ destroyBreakableModel(void *object, int32 offset, int32 size)
} }
static void 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 header[13];
uint32 hasBreakable = readUInt32(stream); uint32 hasBreakable = readUInt32(stream);
@ -334,7 +334,7 @@ readBreakableModel(istream &stream, int32 len, void *object, int32 o, int32 s)
} }
static void 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]; uint32 header[13];
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o); Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o);
@ -357,7 +357,7 @@ writeBreakableModel(ostream &stream, int32 len, void *object, int32 o, int32 s)
} }
static int32 static int32
getSizeBreakableModel(void *object, int32 offset, int32 size) getSizeBreakableModel(void *object, int32 offset, int32)
{ {
Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset); Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset);
if(breakable == NULL) 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); void WriteNativeData(std::ostream &stream, int32 len, void *object, int32, int32);
int32 GetSizeNativeData(void *object, int32, int32); int32 GetSizeNativeData(void *object, int32, int32);
void Instance(Atomic *atomic);
// only RW_OPENGL
void UploadGeo(Geometry *geo); void UploadGeo(Geometry *geo);
void SetAttribPointers(InstanceDataHeader *inst); void SetAttribPointers(InstanceDataHeader *inst);