implemented MaterialList struct

This commit is contained in:
aap 2017-03-16 11:42:59 +01:00
parent 4941711964
commit e3c1f30856
15 changed files with 305 additions and 185 deletions

View File

@ -129,7 +129,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32)
inst->numVertices = *(uint32*)p; p += 4;
inst->numIndices = *(uint32*)p; p += 4;
uint32 matid = *(uint32*)p; p += 4;
inst->material = geometry->materialList[matid];
inst->material = geometry->matList.materials[matid];
inst->vertexShader = *(uint32*)p; p += 4;
inst->primType = *(uint32*)p; p += 4;
inst->indexBuffer = nil; p += 4;
@ -184,7 +184,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
*(uint32*)p = inst->stride; p += 4;
*(uint32*)p = inst->numVertices; p += 4;
*(uint32*)p = inst->numIndices; p += 4;
int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
int32 matid = geometry->matList.findIndex(inst->material);
*(int32*)p = matid; p += 4;
*(uint32*)p = inst->vertexShader; p += 4;
*(uint32*)p = inst->primType; p += 4;
@ -248,9 +248,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
@ -295,11 +295,11 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D8);
geo->geoflags &= ~Geometry::NATIVE;
geo->flags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
@ -328,7 +328,7 @@ render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D8);
@ -350,8 +350,8 @@ ObjPipeline::ObjPipeline(uint32 platform)
void
defaultInstanceCB(Geometry *geo, InstanceData *inst)
{
inst->vertexShader = makeFVFDeclaration(geo->geoflags, geo->numTexCoordSets);
inst->stride = getStride(geo->geoflags, geo->numTexCoordSets);
inst->vertexShader = makeFVFDeclaration(geo->flags, geo->numTexCoordSets);
inst->stride = getStride(geo->flags, geo->numTexCoordSets);
inst->vertexBuffer = createVertexBuffer(inst->numVertices*inst->stride,
inst->vertexShader, D3DPOOL_MANAGED);
@ -363,7 +363,7 @@ defaultInstanceCB(Geometry *geo, InstanceData *inst)
inst->numVertices, inst->stride);
dst += 12;
if(geo->geoflags & Geometry::NORMALS){
if(geo->flags & Geometry::NORMALS){
instV3d(VERT_FLOAT3, dst,
&geo->morphTargets[0].normals[3*inst->minVert],
inst->numVertices, inst->stride);
@ -371,7 +371,7 @@ defaultInstanceCB(Geometry *geo, InstanceData *inst)
}
inst->vertexAlpha = 0;
if(geo->geoflags & Geometry::PRELIT){
if(geo->flags & Geometry::PRELIT){
inst->vertexAlpha = instColor(VERT_ARGB, dst, &geo->colors[4*inst->minVert],
inst->numVertices, inst->stride);
dst += 4;
@ -394,7 +394,7 @@ defaultUninstanceCB(Geometry *geo, InstanceData *inst)
src, inst->numVertices, inst->stride);
src += 12;
if(geo->geoflags & Geometry::NORMALS){
if(geo->flags & Geometry::NORMALS){
uninstV3d(VERT_FLOAT3,
&geo->morphTargets[0].normals[3*inst->minVert],
src, inst->numVertices, inst->stride);
@ -402,7 +402,7 @@ defaultUninstanceCB(Geometry *geo, InstanceData *inst)
}
inst->vertexAlpha = 0;
if(geo->geoflags & Geometry::PRELIT){
if(geo->flags & Geometry::PRELIT){
uninstColor(VERT_ARGB, &geo->colors[4*inst->minVert], src,
inst->numVertices, inst->stride);
src += 4;

View File

@ -32,7 +32,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
if(geo->flags & Geometry::PRELIT)
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
device->SetFVF(inst->vertexShader);

View File

@ -153,7 +153,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32)
inst->numIndex = *(uint32*)p; p += 4;
inst->minVert = *(uint32*)p; p += 4;
uint32 matid = *(uint32*)p; p += 4;
inst->material = geometry->materialList[matid];
inst->material = geometry->matList.materials[matid];
inst->vertexAlpha = *(bool32*)p; p += 4;
inst->vertexShader = nil; p += 4;
inst->baseIndex = 0; p += 4;
@ -235,7 +235,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
for(uint32 i = 0; i < header->numMeshes; i++){
*(uint32*)p = inst->numIndex; p += 4;
*(uint32*)p = inst->minVert; p += 4;
int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
int32 matid = geometry->matList.findIndex(inst->material);
*(int32*)p = matid; p += 4;
*(bool32*)p = inst->vertexAlpha; p += 4;
*(uint32*)p = 0; p += 4; // vertex shader
@ -312,9 +312,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
@ -365,11 +365,11 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D9);
geo->geoflags &= ~Geometry::NATIVE;
geo->flags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
@ -398,7 +398,7 @@ render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_D3D9);
@ -439,7 +439,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
uint16 stride = 12;
s->geometryFlags |= 0x2;
bool isPrelit = (geo->geoflags & Geometry::PRELIT) != 0;
bool isPrelit = (geo->flags & Geometry::PRELIT) != 0;
if(isPrelit){
dcl[i].stream = 0;
dcl[i].offset = stride;
@ -464,7 +464,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
stride += 8;
}
bool hasNormals = (geo->geoflags & Geometry::NORMALS) != 0;
bool hasNormals = (geo->flags & Geometry::NORMALS) != 0;
if(hasNormals){
dcl[i].stream = 0;
dcl[i].offset = stride;
@ -540,7 +540,7 @@ defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
header->totalNumVertex,
header->vertexStream[dcl[i].stream].stride);
if(geo->geoflags & Geometry::PRELIT){
if(geo->flags & Geometry::PRELIT){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
;
uninstColor(vertFormatMap[dcl[i].type],
@ -560,7 +560,7 @@ defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
header->vertexStream[dcl[i].stream].stride);
}
if(geo->geoflags & Geometry::NORMALS){
if(geo->flags & Geometry::NORMALS){
for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
;
uninstV3d(vertFormatMap[dcl[i].type],

View File

@ -37,7 +37,7 @@ defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
d3d::setRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
d3d::setRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
d3d::setRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
if(geo->geoflags & Geometry::PRELIT)
if(geo->flags & Geometry::PRELIT)
d3d::setRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
d3d::flushCache();
device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex,

View File

@ -197,9 +197,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
@ -247,11 +247,11 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_XBOX);
geo->geoflags &= ~Geometry::NATIVE;
geo->flags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
@ -293,7 +293,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
{
uint32 *vertexFmt = getVertexFmt(geo);
if(*vertexFmt == 0)
*vertexFmt = makeVertexFmt(geo->geoflags, geo->numTexCoordSets);
*vertexFmt = makeVertexFmt(geo->flags, geo->numTexCoordSets);
header->stride = getVertexFmtStride(*vertexFmt);
header->vertexBuffer = new uint8[header->stride*header->numVertices];
uint8 *dst = (uint8*)header->vertexBuffer;

View File

@ -14,6 +14,8 @@
namespace rw {
SurfaceProperties defaultSurfaceProps = { 1.0f, 1.0f, 1.0f };
Geometry*
Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
{
@ -23,11 +25,11 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
return nil;
}
geo->object.init(Geometry::ID, 0);
geo->geoflags = flags & 0xFF00FFFF;
geo->flags = flags & 0xFF00FFFF;
geo->numTexCoordSets = (flags & 0xFF0000) >> 16;
if(geo->numTexCoordSets == 0)
geo->numTexCoordSets = (geo->geoflags & TEXTURED) ? 1 :
(geo->geoflags & TEXTURED2) ? 2 : 0;
geo->numTexCoordSets = (geo->flags & TEXTURED) ? 1 :
(geo->flags & TEXTURED2) ? 2 : 0;
geo->numTriangles = numTris;
geo->numVertices = numVerts;
geo->numMorphTargets = 1;
@ -36,10 +38,10 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
for(int32 i = 0; i < geo->numTexCoordSets; i++)
geo->texCoords[i] = nil;
geo->triangles = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){
if(geo->geoflags & PRELIT)
if(!(geo->flags & NATIVE) && geo->numVertices){
if(geo->flags & PRELIT)
geo->colors = new uint8[4*geo->numVertices];
if((geo->geoflags & TEXTURED) || (geo->geoflags & TEXTURED2))
if((geo->flags & TEXTURED) || (geo->flags & TEXTURED2))
for(int32 i = 0; i < geo->numTexCoordSets; i++)
geo->texCoords[i] =
new float32[2*geo->numVertices];
@ -51,13 +53,12 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
m->boundingSphere.radius = 0.0f;
m->vertices = nil;
m->normals = nil;
if(!(geo->geoflags & NATIVE) && geo->numVertices){
if(!(geo->flags & NATIVE) && geo->numVertices){
m->vertices = new float32[3*geo->numVertices];
if(geo->geoflags & NORMALS)
if(geo->flags & NORMALS)
m->normals = new float32[3*geo->numVertices];
}
geo->numMaterials = 0;
geo->materialList = nil;
geo->matList.init();
geo->meshHeader = nil;
geo->instData = nil;
geo->refCount = 1;
@ -84,10 +85,7 @@ Geometry::destroy(void)
}
delete[] this->morphTargets;
delete this->meshHeader;
for(int32 i = 0; i < this->numMaterials; i++)
if(this->materialList[i])
this->materialList[i]->destroy();
delete[] this->materialList;
this->matList.deinit();
free(this);
}
}
@ -105,6 +103,9 @@ Geometry::streamRead(Stream *stream)
{
uint32 version;
GeoStreamData buf;
SurfaceProperties surfProps;
MaterialList *ret;
if(!findChunk(stream, ID_STRUCT, nil, &version)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
@ -115,12 +116,11 @@ Geometry::streamRead(Stream *stream)
if(geo == nil)
return nil;
geo->addMorphTargets(buf.numMorphTargets-1);
// skip surface properties
if(version < 0x34000)
stream->seek(12);
stream->read(&surfProps, 12);
if(!(geo->geoflags & NATIVE)){
if(geo->geoflags & PRELIT)
if(!(geo->flags & NATIVE)){
if(geo->flags & PRELIT)
stream->read(geo->colors, 4*geo->numVertices);
for(int32 i = 0; i < geo->numTexCoordSets; i++)
stream->read(geo->texCoords[i],
@ -150,24 +150,13 @@ Geometry::streamRead(Stream *stream)
RWERROR((ERR_CHUNK, "MATLIST"));
goto fail;
}
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
if(version < 0x34000)
defaultSurfaceProps = surfProps;
ret = MaterialList::streamRead(stream, &geo->matList);
if(version < 0x34000)
defaultSurfaceProps = (SurfaceProperties){ 1.0f, 1.0f, 1.0f };
if(ret == nil)
goto fail;
}
geo->numMaterials = stream->readI32();
geo->materialList = new Material*[geo->numMaterials];
stream->seek(geo->numMaterials*4); // material indices...but always -1
Material *m;
for(int32 i = 0; i < geo->numMaterials; i++){
if(!findChunk(stream, ID_MATERIAL, nil, nil)){
RWERROR((ERR_CHUNK, "MATERIAL"));
goto fail;
}
m = Material::streamRead(stream);
if(m == nil)
goto fail;
geo->materialList[i] = m;
}
if(s_plglist.streamRead(stream, geo))
return geo;
@ -183,8 +172,8 @@ geoStructSize(Geometry *geo)
size += sizeof(GeoStreamData);
if(version < 0x34000)
size += 12; // surface properties
if(!(geo->geoflags & Geometry::NATIVE)){
if(geo->geoflags&geo->PRELIT)
if(!(geo->flags & Geometry::NATIVE)){
if(geo->flags&geo->PRELIT)
size += 4*geo->numVertices;
for(int32 i = 0; i < geo->numTexCoordSets; i++)
size += 2*geo->numVertices*4;
@ -193,7 +182,7 @@ 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(!(geo->geoflags & Geometry::NATIVE)){
if(!(geo->flags & Geometry::NATIVE)){
if(m->vertices)
size += 3*geo->numVertices*4;
if(m->normals)
@ -207,13 +196,12 @@ bool
Geometry::streamWrite(Stream *stream)
{
GeoStreamData buf;
uint32 size;
static float32 fbuf[3] = { 1.0f, 1.0f, 1.0f };
writeChunkHeader(stream, ID_GEOMETRY, this->streamGetSize());
writeChunkHeader(stream, ID_STRUCT, geoStructSize(this));
buf.flags = this->geoflags | this->numTexCoordSets << 16;
buf.flags = this->flags | this->numTexCoordSets << 16;
buf.numTriangles = this->numTriangles;
buf.numVertices = this->numVertices;
buf.numMorphTargets = this->numMorphTargets;
@ -221,8 +209,8 @@ Geometry::streamWrite(Stream *stream)
if(version < 0x34000)
stream->write(fbuf, sizeof(fbuf));
if(!(this->geoflags & NATIVE)){
if(this->geoflags & PRELIT)
if(!(this->flags & NATIVE)){
if(this->flags & PRELIT)
stream->write(this->colors, 4*this->numVertices);
for(int32 i = 0; i < this->numTexCoordSets; i++)
stream->write(this->texCoords[i],
@ -240,7 +228,7 @@ Geometry::streamWrite(Stream *stream)
for(int32 i = 0; i < this->numMorphTargets; i++){
MorphTarget *m = &this->morphTargets[i];
stream->write(&m->boundingSphere, 4*4);
if(!(this->geoflags & NATIVE)){
if(!(this->flags & NATIVE)){
stream->writeI32(m->vertices != nil);
stream->writeI32(m->normals != nil);
if(m->vertices)
@ -255,16 +243,7 @@ Geometry::streamWrite(Stream *stream)
}
}
size = 12 + 4;
for(int32 i = 0; i < this->numMaterials; i++)
size += 4 + 12 + this->materialList[i]->streamGetSize();
writeChunkHeader(stream, ID_MATLIST, size);
writeChunkHeader(stream, ID_STRUCT, 4 + this->numMaterials*4);
stream->writeI32(this->numMaterials);
for(int32 i = 0; i < this->numMaterials; i++)
stream->writeI32(-1);
for(int32 i = 0; i < this->numMaterials; i++)
this->materialList[i]->streamWrite(stream);
this->matList.streamWrite(stream);
s_plglist.streamWrite(stream, this);
return true;
@ -275,9 +254,7 @@ Geometry::streamGetSize(void)
{
uint32 size = 0;
size += 12 + geoStructSize(this);
size += 12 + 12 + 4;
for(int32 i = 0; i < this->numMaterials; i++)
size += 4 + 12 + this->materialList[i]->streamGetSize();
size += 12 + this->matList.streamGetSize();
size += 12 + s_plglist.streamGetSize(this);
return size;
}
@ -296,9 +273,9 @@ Geometry::addMorphTargets(int32 n)
MorphTarget *m = &morphTargets[i];
m->vertices = nil;
m->normals = nil;
if(!(this->geoflags & NATIVE)){
if(!(this->flags & NATIVE)){
m->vertices = new float32[3*this->numVertices];
if(this->geoflags & NORMALS)
if(this->flags & NORMALS)
m->normals = new float32[3*this->numVertices];
}
}
@ -331,11 +308,11 @@ Geometry::calculateBoundingSphere(void)
bool32
Geometry::hasColoredMaterial(void)
{
for(int32 i = 0; i < this->numMaterials; i++)
if(this->materialList[i]->color.red != 255 ||
this->materialList[i]->color.green != 255 ||
this->materialList[i]->color.blue != 255 ||
this->materialList[i]->color.alpha != 255)
for(int32 i = 0; i < this->matList.numMaterials; i++)
if(this->matList.materials[i]->color.red != 255 ||
this->matList.materials[i]->color.green != 255 ||
this->matList.materials[i]->color.blue != 255 ||
this->matList.materials[i]->color.alpha != 255)
return 1;
return 0;
}
@ -343,15 +320,15 @@ Geometry::hasColoredMaterial(void)
void
Geometry::allocateData(void)
{
if(this->geoflags & PRELIT)
if(this->flags & PRELIT)
this->colors = new uint8[4*this->numVertices];
if((this->geoflags & TEXTURED) || (this->geoflags & TEXTURED2))
if((this->flags & TEXTURED) || (this->flags & 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)
if(this->flags & NORMALS)
m->normals = new float32[3*this->numVertices];
// TODO: morph targets (who cares anyway?)
}
@ -404,9 +381,7 @@ Geometry::generateTriangles(int8 *adc)
m++;
continue;
}
int32 matid = findPointer((void*)m->material,
(void**)this->materialList,
this->numMaterials);
int32 matid = this->matList.findIndex(m->material);
if(header->flags == MeshHeader::TRISTRIP)
for(uint32 j = 0; j < m->numIndices-2; j++){
if(adc && adcbits[j+2] ||
@ -456,13 +431,13 @@ Geometry::buildMeshes(void)
Triangle *tri;
MeshHeader *h = new MeshHeader;
this->meshHeader = h;
if((this->geoflags & Geometry::TRISTRIP) == 0){
if((this->flags & Geometry::TRISTRIP) == 0){
h->flags = 0;
h->totalIndices = this->numTriangles*3;
h->numMeshes = this->numMaterials;
h->numMeshes = this->matList.numMaterials;
h->mesh = new Mesh[h->numMeshes];
for(uint32 i = 0; i < h->numMeshes; i++){
h->mesh[i].material = this->materialList[i];
h->mesh[i].material = this->matList.materials[i];
h->mesh[i].numIndices = 0;
}
// count indices per mesh
@ -496,7 +471,7 @@ Geometry::correctTristripWinding(void)
{
MeshHeader *header = this->meshHeader;
if(header == nil || header->flags != MeshHeader::TRISTRIP ||
this->geoflags & NATIVE)
this->flags & NATIVE)
return;
MeshHeader *newhead = new MeshHeader;
newhead->flags = header->flags;
@ -546,7 +521,6 @@ Geometry::correctTristripWinding(void)
delete header;
}
// HAS to be called with an existing mesh
void
Geometry::removeUnusedMaterials(void)
{
@ -556,24 +530,28 @@ Geometry::removeUnusedMaterials(void)
for(uint32 i = 0; i < mh->numMeshes; i++)
if(mh->mesh[i].indices == nil)
return;
int32 *map = new int32[this->numMaterials];
Material **matlist = new Material*[this->numMaterials];
int32 *map = new int32[this->matList.numMaterials];
Material **materials = new Material*[this->matList.numMaterials];
int32 numMaterials = 0;
/* Build new material list and map */
for(uint32 i = 0; i < mh->numMeshes; i++){
Mesh *m = &mh->mesh[i];
if(m->numIndices <= 0)
continue;
matlist[numMaterials] = m->material;
int32 oldid = findPointer((void*)m->material,
(void**)this->materialList,
this->numMaterials);
materials[numMaterials] = m->material;
m->material->refCount++;
int32 oldid = this->matList.findIndex(m->material);
map[oldid] = numMaterials;
numMaterials++;
}
delete[] this->materialList;
this->materialList = matlist;
this->numMaterials = numMaterials;
for(int32 i = 0; i < this->matList.numMaterials; i++)
this->matList.materials[i]->destroy();
free(this->matList.materials);
this->matList.materials = materials;
this->matList.space = this->matList.numMaterials;
this->matList.numMaterials = numMaterials;
/* Build new meshes */
MeshHeader *newmh = new MeshHeader;
newmh->flags = mh->flags;
@ -602,12 +580,154 @@ Geometry::removeUnusedMaterials(void)
}
delete this->meshHeader;
this->meshHeader = newmh;
/* Remap triangle material IDs */
for(int32 i = 0; i < this->numTriangles; i++)
this->triangles[i].matId = map[this->triangles[i].matId];
delete[] map;
}
//
// MaterialList
//
void
MaterialList::init(void)
{
this->materials = nil;
this->numMaterials = 0;
this->space = 0;
}
void
MaterialList::deinit(void)
{
if(this->materials){
for(int32 i = 0; i < this->numMaterials; i++)
this->materials[i]->destroy();
free(this->materials);
}
}
int32
MaterialList::appendMaterial(Material *mat)
{
Material **ml;
int32 space;
if(this->numMaterials >= this->space){
space = this->space + 20;
if(this->materials)
ml = (Material**)realloc(this->materials,
space*sizeof(Material*));
else
ml = (Material**)malloc(space*sizeof(Material*));
if(ml == nil)
return -1;
this->space = space;
this->materials = ml;
}
this->materials[this->numMaterials++] = mat;
mat->refCount++;
return this->numMaterials-1;
}
int32
MaterialList::findIndex(Material *mat)
{
for(int32 i = 0; i < this->numMaterials; i++)
if(this->materials[i] == mat)
return i;
return -1;
}
MaterialList*
MaterialList::streamRead(Stream *stream, MaterialList *matlist)
{
int32 *indices = nil;
int32 numMat;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
goto fail;
}
matlist->init();
numMat = stream->readI32();
if(numMat == 0)
return matlist;
matlist->materials = (Material**)malloc(numMat*sizeof(Material*));
if(matlist->materials == nil)
goto fail;
matlist->space = numMat;
indices = (int32*)malloc(numMat*4);
stream->read(indices, numMat*4);
Material *m;
for(int32 i = 0; i < numMat; i++){
if(indices[i] >= 0){
m = matlist->materials[indices[i]];
m->refCount++;
}else{
if(!findChunk(stream, ID_MATERIAL, nil, nil)){
RWERROR((ERR_CHUNK, "MATERIAL"));
goto fail;
}
m = Material::streamRead(stream);
if(m == nil)
goto fail;
}
matlist->appendMaterial(m);
m->destroy();
}
free(indices);
return matlist;
fail:
free(indices);
matlist->deinit();
return nil;
}
bool
MaterialList::streamWrite(Stream *stream)
{
uint32 size = this->streamGetSize();
writeChunkHeader(stream, ID_MATLIST, size);
writeChunkHeader(stream, ID_STRUCT, 4 + this->numMaterials*4);
stream->writeI32(this->numMaterials);
int32 idx;
for(int32 i = 0; i < this->numMaterials; i++){
idx = -1;
for(int32 j = i-1; j >= 0; j--)
if(this->materials[i] == this->materials[j]){
idx = j;
break;
}
stream->writeI32(idx);
}
for(int32 i = 0; i < this->numMaterials; i++){
for(int32 j = i-1; j >= 0; j--)
if(this->materials[i] == this->materials[j])
goto found;
this->materials[i]->streamWrite(stream);
found:;
}
return true;
}
uint32
MaterialList::streamGetSize(void)
{
uint32 size = 12 + 4 + this->numMaterials*4;
for(int32 i = 0; i < this->numMaterials; i++){
for(int32 j = i-1; j >= 0; j--)
if(this->materials[i] == this->materials[j])
goto found;
size += 12 + this->materials[i]->streamGetSize();
found:;
}
return size;
}
//
// Material
//
@ -622,9 +742,7 @@ Material::create(void)
}
mat->texture = nil;
memset(&mat->color, 0xFF, 4);
mat->surfaceProps.ambient = 1.0f;
mat->surfaceProps.specular = 1.0f;
mat->surfaceProps.diffuse = 1.0f;
mat->surfaceProps = defaultSurfaceProps;
mat->pipeline = nil;
mat->refCount = 1;
s_plglist.construct(mat);
@ -695,17 +813,10 @@ Material::streamRead(Stream *stream)
if(mat == nil)
return nil;
mat->color = buf.color;
if(version < 0x30400){
mat->surfaceProps.ambient = 1.0f;
mat->surfaceProps.specular = 1.0f;
mat->surfaceProps.diffuse = 1.0f;
}else{
float32 surfaceProps[3];
stream->read(surfaceProps, sizeof(surfaceProps));
mat->surfaceProps.ambient = surfaceProps[0];
mat->surfaceProps.specular = surfaceProps[1];
mat->surfaceProps.diffuse = surfaceProps[2];
}
if(version < 0x30400)
mat->surfaceProps = defaultSurfaceProps;
else
stream->read(&mat->surfaceProps, sizeof(surfaceProps));
if(buf.textured){
if(!findChunk(stream, ID_TEXTURE, &length, nil)){
RWERROR((ERR_CHUNK, "TEXTURE"));

View File

@ -39,14 +39,14 @@ readMesh(Stream *stream, int32 len, void *object, int32, int32)
Mesh *mesh = geo->meshHeader->mesh;
bool hasData = len > 12+geo->meshHeader->numMeshes*8;
uint16 *p = nil;
if(!(geo->geoflags & Geometry::NATIVE) || hasData)
if(!(geo->flags & Geometry::NATIVE) || hasData)
p = new uint16[geo->meshHeader->totalIndices];
for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){
stream->read(buf, 8);
mesh->numIndices = buf[0];
mesh->material = geo->materialList[buf[1]];
mesh->material = geo->matList.materials[buf[1]];
mesh->indices = nil;
if(geo->geoflags & Geometry::NATIVE){
if(geo->flags & Geometry::NATIVE){
// OpenGL stores uint16 indices here
if(hasData){
mesh->indices = p;
@ -85,11 +85,9 @@ writeMesh(Stream *stream, int32, void *object, int32, int32)
Mesh *mesh = geo->meshHeader->mesh;
for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){
buf[0] = mesh->numIndices;
buf[1] = findPointer((void*)mesh->material,
(void**)geo->materialList,
geo->numMaterials);
buf[1] = geo->matList.findIndex(mesh->material);
stream->write(buf, 8);
if(geo->geoflags & Geometry::NATIVE){
if(geo->flags & Geometry::NATIVE){
assert(geo->instData != nil);
if(geo->instData->platform == PLATFORM_WDGL)
stream->write(mesh->indices,
@ -117,7 +115,7 @@ getSizeMesh(void *object, int32, int32)
if(geo->meshHeader == nil)
return -1;
int32 size = 12 + geo->meshHeader->numMeshes*8;
if(geo->geoflags & Geometry::NATIVE){
if(geo->flags & Geometry::NATIVE){
assert(geo->instData != nil);
if(geo->instData->platform == PLATFORM_WDGL)
size += geo->meshHeader->totalIndices*2;

View File

@ -27,9 +27,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
InstanceDataHeader *header = new InstanceDataHeader;
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
@ -87,7 +87,7 @@ render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_GL3);
@ -129,7 +129,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
// Normals
// TODO: compress
bool hasNormals = !!(geo->geoflags & Geometry::NORMALS);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
@ -141,7 +141,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
}
// Prelighting
bool isPrelit = !!(geo->geoflags & Geometry::PRELIT);
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;

View File

@ -287,7 +287,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
// Normals
// TODO: compress
bool hasNormals = !!(geo->geoflags & Geometry::NORMALS);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
@ -299,7 +299,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
}
// Prelighting
bool isPrelit = !!(geo->geoflags & Geometry::PRELIT);
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;

View File

@ -322,7 +322,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
InstanceDataHeader *header = new InstanceDataHeader;
geo->instData = header;
@ -331,9 +331,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
header->ibo = 0;
header->numAttribs =
pipe->numCustomAttribs + 1 + (geo->numTexCoordSets > 0);
if(geo->geoflags & Geometry::PRELIT)
if(geo->flags & Geometry::PRELIT)
header->numAttribs++;
if(geo->geoflags & Geometry::NORMALS)
if(geo->flags & Geometry::NORMALS)
header->numAttribs++;
int32 offset = 0;
header->attribs = new AttribDesc[header->numAttribs];
@ -361,7 +361,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
firstCustom++;
}
if(geo->geoflags & Geometry::NORMALS){
if(geo->flags & Geometry::NORMALS){
a->index = 2;
a->type = 1;
a->normalized = 1;
@ -372,7 +372,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
firstCustom++;
}
if(geo->geoflags & Geometry::PRELIT){
if(geo->flags & Geometry::PRELIT){
a->index = 3;
a->type = 2;
a->normalized = 1;
@ -414,7 +414,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
a++;
}
if(geo->geoflags & Geometry::NORMALS){
if(geo->flags & Geometry::NORMALS){
p = header->data + a->offset;
float32 *norm = geo->morphTargets->normals;
for(int32 i = 0; i < geo->numVertices; i++){
@ -425,7 +425,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
a++;
}
if(geo->geoflags & Geometry::PRELIT){
if(geo->flags & Geometry::PRELIT){
// TODO: this seems too complicated
p = header->data + a->offset;
uint8 *color = geo->colors;
@ -441,7 +441,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
}
a++;
}
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
}
static void
@ -449,11 +449,11 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_WDGL);
geo->geoflags &= ~Geometry::NATIVE;
geo->flags &= ~Geometry::NATIVE;
geo->allocateData();
uint8 *p;

View File

@ -333,8 +333,8 @@ instanceUV(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d = (uint32*)g->texCoords[0];
if((g->geoflags & Geometry::TEXTURED) ||
(g->geoflags & Geometry::TEXTURED2))
if((g->flags & Geometry::TEXTURED) ||
(g->flags & Geometry::TEXTURED2))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j*2+0];
@ -383,7 +383,7 @@ instanceRGBA(uint32 *p, Geometry *g, Mesh *m, uint32 idx, uint32 n)
{
uint16 j;
uint32 *d = (uint32*)g->colors;
if((g->geoflags & Geometry::PRELIT))
if((g->flags & Geometry::PRELIT))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j];
@ -402,7 +402,7 @@ instanceNormal(uint32 *wp, Geometry *g, Mesh *m, uint32 idx, uint32 n)
uint16 j;
float *d = g->morphTargets[0].normals;
uint8 *p = (uint8*)wp;
if((g->geoflags & Geometry::NORMALS))
if((g->flags & Geometry::NORMALS))
for(uint32 i = idx; i < idx+n; i++){
j = m->indices[i];
*p++ = d[j*3+0]*127.0f;
@ -742,7 +742,7 @@ objInstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if(geo->geoflags & Geometry::NATIVE)
if(geo->flags & Geometry::NATIVE)
return;
InstanceDataHeader *header = new InstanceDataHeader;
geo->instData = header;
@ -763,7 +763,7 @@ objInstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
m->instance(geo, instance, mesh);
instance->material = mesh->material;
}
geo->geoflags |= Geometry::NATIVE;
geo->flags |= Geometry::NATIVE;
}
static void
@ -800,14 +800,14 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
if((geo->geoflags & Geometry::NATIVE) == 0)
if((geo->flags & Geometry::NATIVE) == 0)
return;
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_PS2);
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
// highest possible number of vertices
geo->numVertices = geo->meshHeader->totalIndices;
geo->geoflags &= ~Geometry::NATIVE;
geo->flags &= ~Geometry::NATIVE;
geo->allocateData();
geo->meshHeader->allocateIndices();
uint32 *flags = new uint32[geo->numVertices];
@ -964,9 +964,9 @@ genericUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh
}
uint32 mask = 0x1; // vertices
if(normals && geo->geoflags & Geometry::NORMALS)
if(normals && geo->flags & Geometry::NORMALS)
mask |= 0x10;
if(rgba && geo->geoflags & Geometry::PRELIT)
if(rgba && geo->flags & Geometry::PRELIT)
mask |= 0x100;
if((uv || uv2) && geo->numTexCoordSets > 0)
mask |= 0x1000;
@ -1027,9 +1027,9 @@ defaultUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh
uint8 *colors = (uint8*)data[AT_RGBA];
int8 *norms = (int8*)data[AT_NORMAL];
uint32 mask = 0x1; // vertices
if(geo->geoflags & Geometry::NORMALS)
if(geo->flags & Geometry::NORMALS)
mask |= 0x10;
if(geo->geoflags & Geometry::PRELIT)
if(geo->flags & Geometry::PRELIT)
mask |= 0x100;
for(int32 i = 0; i < geo->numTexCoordSets; i++)
mask |= 0x1000 << i;
@ -1245,7 +1245,7 @@ writeADC(Stream *stream, int32 len, void *object, int32 offset, int32)
ADCData *adc = PLUGINOFFSET(ADCData, object, offset);
Geometry *geometry = (Geometry*)object;
writeChunkHeader(stream, ID_ADC, len-12);
if(geometry->geoflags & Geometry::NATIVE){
if(geometry->flags & Geometry::NATIVE){
stream->writeI32(0);
return stream;
}
@ -1262,7 +1262,7 @@ getSizeADC(void *object, int32 offset, int32)
ADCData *adc = PLUGINOFFSET(ADCData, object, offset);
if(!adc->adcFormatted)
return 0;
if(geometry->geoflags & Geometry::NATIVE)
if(geometry->flags & Geometry::NATIVE)
return 16;
return 16 + (adc->numBits+3 & ~3);
}

View File

@ -264,9 +264,9 @@ skinUninstanceCB(MatPipeline*, Geometry *geo, uint32 flags[], Mesh *mesh, uint8
int8 *norms = (int8*)data[AT_NORMAL];
uint32 *wghts = (uint32*)data[AT_NORMAL+1];
uint32 mask = 0x1; // vertices
if(geo->geoflags & Geometry::NORMALS)
if(geo->flags & Geometry::NORMALS)
mask |= 0x10;
if(geo->geoflags & Geometry::PRELIT)
if(geo->flags & Geometry::PRELIT)
mask |= 0x100;
if(geo->numTexCoordSets > 0)
mask |= 0x1000;

View File

@ -375,11 +375,26 @@ struct Triangle
uint16 matId;
};
struct MaterialList
{
Material **materials;
int32 numMaterials;
int32 space;
void init(void);
void deinit(void);
int32 appendMaterial(Material *mat);
int32 findIndex(Material *mat);
static MaterialList *streamRead(Stream *stream, MaterialList *matlist);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
};
struct Geometry : PluginBase<Geometry>
{
enum { ID = 8 };
Object object;
uint32 geoflags; // TODO: rename
uint32 flags;
int32 numTriangles;
int32 numVertices;
int32 numMorphTargets;
@ -390,22 +405,15 @@ struct Geometry : PluginBase<Geometry>
float32 *texCoords[8];
MorphTarget *morphTargets;
// TODO: struct
int32 numMaterials;
Material **materialList;
MaterialList matList;
MeshHeader *meshHeader;
InstanceDataHeader *instData;
int32 refCount;
static Geometry *create(int32 numVerts, int32 numTris, uint32 flags);
void destroy(void);
static Geometry *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
void addMorphTargets(int32 n);
void calculateBoundingSphere(void);
bool32 hasColoredMaterial(void);
@ -415,6 +423,9 @@ struct Geometry : PluginBase<Geometry>
void buildTristrips(void);
void correctTristripWinding(void);
void removeUnusedMaterials(void);
static Geometry *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
enum Flags
{
@ -446,13 +457,13 @@ struct Atomic : PluginBase<Atomic>
typedef void (*RenderCB)(Atomic *atomic);
enum { ID = 1 };
enum {
// flags
COLLISIONTEST = 0x01, // unused here
RENDER = 0x04,
// private
WORLDBOUNDDIRTY = 0x01
};
enum {
SAMEBOUNDINGSPHERE = 0x01, // for setGeometry
// private flags
WORLDBOUNDDIRTY = 0x01,
// for setGeometry
SAMEBOUNDINGSPHERE = 0x01,
};
ObjectWithFrame object;

View File

@ -428,7 +428,7 @@ Geometry::buildTristrips(void)
printf("%ld\n", sizeof(StripNode));
smesh.nodes = new StripNode[this->numTriangles];
for(int32 i = 0; i < this->numMaterials; i++){
for(int32 i = 0; i < this->matList.numMaterials; i++){
smesh.loneNodes.init();
smesh.endNodes.init();
collectFaces(this, &smesh, i);

View File

@ -115,7 +115,7 @@ void
drawAtomic(rw::Atomic *atomic)
{
rw::Geometry *geo = atomic->geometry;
if(!(geo->geoflags & rw::Geometry::NATIVE)){
if(!(geo->flags & rw::Geometry::NATIVE)){
if(atomic->pipeline)
atomic->pipeline->instance(atomic);
else