uninstacing OpenGL geometry

This commit is contained in:
aap 2015-08-11 20:57:43 +02:00
parent c84249900a
commit c620ad8692
7 changed files with 320 additions and 79 deletions

10
TODO
View File

@ -15,20 +15,24 @@ Clump & related:
- implement plugins:
Clump
R* Collision
Animation (old III dffs)
Atomic
((Particles))
R* Pipeline Set
Skin (old III dffs)
Geometry
-Native Data
((Morph))
-Skin
R* 2dfx
Material
UV Anim
Texture
(Sky Mipmap Val)
- PDS Pipelines (at least dummies)
- PDS Pipelines
- ADC
- uninstance geometry
- UV Anim Dict

View File

@ -62,15 +62,6 @@ main(int argc, char *argv[])
// printf("%s\n", argv[arg]);
// only opengl:
/*
for(int32 i = 0; i < c->numAtomics; i++){
Atomic *a = c->atomicList[i];
gl::printPipeinfo(a);
}
return 0;
*/
/*
for(int32 i = 0; i < c->numAtomics; i++){
Atomic *a = c->atomicList[i];
@ -93,9 +84,9 @@ main(int argc, char *argv[])
p->instance(a);
}
data = new rw::uint8[256*1024];
data = new rw::uint8[512*1024];
rw::StreamMemory out;
out.open(data, 0, 256*1024);
out.open(data, 0, 512*1024);
c->streamWrite(&out);
FILE *cf = fopen("out.dff", "wb");

View File

@ -270,6 +270,79 @@ Geometry::addMorphTargets(int32 n)
this->numMorphTargets += n;
}
void
Geometry::allocateData(void)
{
if(this->geoflags & PRELIT)
this->colors = new uint8[4*this->numVertices];
if((this->geoflags & TEXTURED) || (this->geoflags & TEXTURED2))
for(int32 i = 0; i < this->numTexCoordSets; i++)
this->texCoords[i] =
new float32[2*this->numVertices];
MorphTarget *m = this->morphTargets;
m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS)
m->normals = new float32[3*this->numVertices];
// TODO: morph targets (who cares anyway?)
}
static int
isDegenerate(uint16 *idx)
{
// TODO: maybe check position instead of index?
return idx[0] == idx[1] ||
idx[0] == idx[2] ||
idx[1] == idx[2];
}
void
Geometry::generateTriangles(void)
{
MeshHeader *header = this->meshHeader;
assert(header != NULL);
this->numTriangles = 0;
Mesh *m = header->mesh;
for(uint32 i = 0; i < header->numMeshes; i++){
if(header->flags == 1){ // tristrip
for(uint32 j = 0; j < m->numIndices-2; j++){
if(!isDegenerate(&m->indices[j]))
this->numTriangles++;
}
}else
this->numTriangles += m->numIndices/3;
m++;
}
delete[] this->triangles;
this->triangles = new uint16[4*this->numTriangles];
printf("%d %p\n", this->numTriangles, this->triangles);
uint16 *f = this->triangles;
m = header->mesh;
for(uint32 i = 0; i < header->numMeshes; i++){
int32 matid = findPointer((void*)m->material,
(void**)this->materialList,
this->numMaterials);
if(header->flags == 1) // tristrip
for(uint32 j = 0; j < m->numIndices-2; j++){
if(isDegenerate(&m->indices[j]))
continue;
*f++ = m->indices[j+1 + (j%2)];
*f++ = m->indices[j+0];
*f++ = matid;
*f++ = m->indices[j+2 - (j%2)];
}
else
for(uint32 j = 0; j < m->numIndices-2; j+=3){
*f++ = m->indices[j+1];
*f++ = m->indices[j+0];
*f++ = matid;
*f++ = m->indices[j+2];
}
m++;
}
}
//
// Material

View File

@ -176,7 +176,8 @@ packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
}
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform), numCustomAttribs(0), instanceCB(NULL) { }
: rw::ObjPipeline(platform), numCustomAttribs(0),
instanceCB(NULL), uninstanceCB(NULL) { }
void
ObjPipeline::instance(Atomic *atomic)
@ -286,6 +287,7 @@ ObjPipeline::instance(Atomic *atomic)
}
if(geo->geoflags & Geometry::PRELIT){
// TODO: this seems too complicated
p = header->data + a->offset;
uint8 *color = geo->colors;
float32 f[4];
@ -303,6 +305,132 @@ ObjPipeline::instance(Atomic *atomic)
geo->geoflags |= Geometry::NATIVE;
}
static void
unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8src;
uint16 *u16src;
int16 *i16src;
switch(a->type){
case 0: // float
memcpy(dst, src, a->size*4);
break;
// TODO: maybe have loop inside if?
case 1: // byte
i8src = (int8*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i8src[i]/scale;
else
dst[i] = i8src[i]/127.0f;
}
break;
case 2: // ubyte
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = src[i]/scale;
else
dst[i] = src[i]/255.0f;
}
break;
case 3: // short
i16src = (int16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = i16src[i]/scale;
else
dst[i] = i16src[i]/32767.0f;
}
break;
case 4: // ushort
u16src = (uint16*)src;
for(int i = 0; i < a->size; i++){
if(!a->normalized)
dst[i] = u16src[i]/scale;
else
dst[i] = u16src[i]/65435.0f;
}
break;
}
}
void
ObjPipeline::uninstance(Atomic *atomic)
{
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
return;
geo->geoflags &= ~Geometry::NATIVE;
geo->allocateData();
uint8 *p;
float32 *texcoord = geo->texCoords[0];
uint8 *color = geo->colors;
float32 *vert = geo->morphTargets->vertices;
float32 *norm = geo->morphTargets->normals;
float32 f[4];
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
for(int i = 0; i < header->numAttribs; i++){
AttribDesc *a = &header->attribs[i];
p = header->data + a->offset;
switch(a->index){
case 0: // Vertices
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(vert, p, a);
vert += 3;
p += a->stride;
}
break;
case 1: // texCoords
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(texcoord, p, a, 512.0f);
texcoord += 2;
p += a->stride;
}
break;
case 2: // normals
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(norm, p, a);
norm += 3;
p += a->stride;
}
break;
case 3: // colors
for(int32 i = 0; i < geo->numVertices; i++){
// TODO: this seems too complicated
unpackattrib(f, p, a);
color[0] = f[0]*255.0f;
color[1] = f[1]*255.0f;
color[2] = f[2]*255.0f;
color[3] = f[3]*255.0f;
color += 4;
p += a->stride;
}
break;
}
}
if(this->uninstanceCB)
uninstanceCB(geo);
geo->generateTriangles();
delete header->attribs;
delete header->data;
delete header;
geo->instData = NULL;
}
ObjPipeline*
makeDefaultPipeline(void)
{
@ -466,6 +594,46 @@ skinInstanceCB(Geometry *g, int32 i, uint32 offset)
return 8;
}
void
skinUninstanceCB(Geometry *geo)
{
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset);
if(skin == NULL)
return;
skin->allocateVertexData(geo->numVertices);
uint8 *p;
float *weights = skin->weights;
uint8 *indices = skin->indices;
for(int i = 0; i < header->numAttribs; i++){
AttribDesc *a = &header->attribs[i];
p = header->data + a->offset;
switch(a->index){
case 4: // weights
for(int32 i = 0; i < geo->numVertices; i++){
unpackattrib(weights, p, a);
weights += 4;
p += a->stride;
}
break;
case 5: // indices
for(int32 i = 0; i < geo->numVertices; i++){
*indices++ = p[0];
*indices++ = p[1];
*indices++ = p[2];
*indices++ = p[3];
p += a->stride;
}
break;
}
}
}
ObjPipeline*
makeSkinPipeline(void)
{
@ -474,6 +642,7 @@ makeSkinPipeline(void)
pipe->pluginData = 1;
pipe->numCustomAttribs = 2;
pipe->instanceCB = skinInstanceCB;
pipe->uninstanceCB = skinUninstanceCB;
return pipe;
}

View File

@ -62,9 +62,9 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32)
{
int32 cnst, numNodes;
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
cnst = stream->readI32();
if(cnst != 256){
printf("hanim const was not 256\n");
ver = stream->readI32();
if(ver != 0x100){
fprintf(stderr, "hanim ver was not 0x100\n");
return;
}
hanim->id = stream->readI32();
@ -362,38 +362,13 @@ copySkin(void *dst, void *src, int32 offset, int32)
dstskin->numBones = srcskin->numBones;
dstskin->numUsedBones = srcskin->numUsedBones;
dstskin->maxIndex = srcskin->maxIndex;
uint32 size = srcskin->numUsedBones +
srcskin->numBones*64 +
geometry->numVertices*(16+4) + 15;
uint8 *data = new uint8[size];
dstskin->data = data;
memcpy(dstskin->data, srcskin->data, size);
dstskin->usedBones = NULL;
if(srcskin->usedBones){
dstskin->usedBones = data;
data += dstskin->numUsedBones;
}
uintptr ptr = (uintptr)data + 15;
ptr &= ~0xF;
data = (uint8*)ptr;
dstskin->inverseMatrices = NULL;
if(srcskin->inverseMatrices){
dstskin->inverseMatrices = (float*)data;
data += 64*dstskin->numBones;
}
dstskin->indices = NULL;
if(srcskin->indices){
dstskin->indices = data;
data += 4*geometry->numVertices;
}
dstskin->weights = NULL;
if(srcskin->weights)
dstskin->weights = (float*)data;
dstskin->allocateData(geometry->numVertices);
memcpy(dstskin->usedBones, srcskin->usedBones, srcskin->numUsedBones);
memcpy(dstskin->inverseMatrices, srcskin->inverseMatrices,
srcskin->numBones*64);
memcpy(dstskin->indices, srcskin->indices, geometry->numVertices*4);
memcpy(dstskin->weights, srcskin->weights, geometry->numVertices*16);
return dst;
}
@ -422,37 +397,9 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
skin->numUsedBones = header[1];
skin->maxIndex = header[2];
// probably rw::version >= 0x34000
bool oldFormat = skin->numUsedBones == 0;
uint32 size = skin->numUsedBones +
skin->numBones*64 +
geometry->numVertices*(16+4) + 15;
uint8 *data = new uint8[size];
skin->data = data;
skin->usedBones = NULL;
if(skin->numUsedBones){
skin->usedBones = data;
data += skin->numUsedBones;
}
uintptr ptr = (uintptr)data + 15;
ptr &= ~0xF;
data = (uint8*)ptr;
skin->inverseMatrices = NULL;
if(skin->numBones){
skin->inverseMatrices = (float*)data;
data += 64*skin->numBones;
}
skin->indices = NULL;
if(geometry->numVertices){
skin->indices = data;
data += 4*geometry->numVertices;
}
skin->weights = NULL;
if(geometry->numVertices)
skin->weights = (float*)data;
skin->allocateData(geometry->numVertices);
if(skin->usedBones)
stream->read(skin->usedBones, skin->numUsedBones);
@ -569,6 +516,55 @@ registerSkinPlugin(void)
Atomic::setStreamRightsCallback(ID_SKIN, skinRights);
}
void
Skin::allocateData(int32 numVerts)
{
uint32 size = this->numUsedBones +
this->numBones*64 +
numVerts*(16+4) + 15;
this->data = new uint8[size];
uint8 *data = this->data;
this->usedBones = NULL;
if(this->numUsedBones){
this->usedBones = data;
data += this->numUsedBones;
}
uintptr ptr = (uintptr)data + 15;
ptr &= ~0xF;
data = (uint8*)ptr;
this->inverseMatrices = NULL;
if(this->numBones){
this->inverseMatrices = (float*)data;
data += 64*this->numBones;
}
this->indices = NULL;
if(numVerts){
this->indices = data;
data += 4*numVerts;
}
this->weights = NULL;
if(numVerts)
this->weights = (float*)data;
}
void
Skin::allocateVertexData(int32 numVerts)
{
uint8 *usedBones = this->usedBones;
float *invMats = this->inverseMatrices;
uint8 *data = this->data;
this->allocateData(numVerts);
memcpy(this->usedBones, usedBones, this->numUsedBones);
memcpy(this->inverseMatrices, invMats, this->numBones*64);
delete[] data;
}
//
// MatFX
//
@ -612,6 +608,7 @@ writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
static int32
getSizeAtomicMatFX(void *object, int32 offset, int32)
{
// TODO: version dependent
/* int32 flag;
flag = *PLUGINOFFSET(int32, object, offset);
return flag ? 4 : -1; */

View File

@ -289,6 +289,8 @@ struct Geometry : PluginBase<Geometry>, Object
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
void addMorphTargets(int32 n);
void allocateData(void);
void generateTriangles(void);
enum Flags
{
@ -318,6 +320,9 @@ struct Skin
uint8 *indices;
float *weights;
uint8 *data; // only used by delete
void allocateData(int32 numVerts);
void allocateVertexData(int32 numVerts);
};
struct SkinGlobals

View File

@ -39,9 +39,11 @@ class ObjPipeline : public rw::ObjPipeline
public:
uint32 numCustomAttribs;
uint32 (*instanceCB)(Geometry *g, int32 i, uint32 offset);
void (*uninstanceCB)(Geometry *g);
ObjPipeline(uint32 platform);
virtual void instance(Atomic *atomic);
virtual void uninstance(Atomic *atomic);
};
ObjPipeline *makeDefaultPipeline(void);