diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 1dcb621..5ca4c82 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -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; diff --git a/src/d3d/d3d8render.cpp b/src/d3d/d3d8render.cpp index 53d9627..2d05c2f 100644 --- a/src/d3d/d3d8render.cpp +++ b/src/d3d/d3d8render.cpp @@ -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); diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 583211d..41af218 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -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], diff --git a/src/d3d/d3d9render.cpp b/src/d3d/d3d9render.cpp index 0a3ab26..715b4b9 100644 --- a/src/d3d/d3d9render.cpp +++ b/src/d3d/d3d9render.cpp @@ -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, diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index 3c9a466..9e62bbe 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -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; diff --git a/src/geometry.cpp b/src/geometry.cpp index 3b52292..6e87f7b 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -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")); diff --git a/src/geoplg.cpp b/src/geoplg.cpp index 20e1bbe..36a164b 100644 --- a/src/geoplg.cpp +++ b/src/geoplg.cpp @@ -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; diff --git a/src/gl/gl3pipe.cpp b/src/gl/gl3pipe.cpp index 2fbb3e4..bede2b9 100644 --- a/src/gl/gl3pipe.cpp +++ b/src/gl/gl3pipe.cpp @@ -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; diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp index 1694088..91cb3cb 100644 --- a/src/gl/gl3plugins.cpp +++ b/src/gl/gl3plugins.cpp @@ -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; diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 748b211..d4ac0c4 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -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; diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index a31e033..cb39216 100644 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -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); } diff --git a/src/ps2/ps2skin.cpp b/src/ps2/ps2skin.cpp index c0b09c7..815e4c7 100644 --- a/src/ps2/ps2skin.cpp +++ b/src/ps2/ps2skin.cpp @@ -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; diff --git a/src/rwobjects.h b/src/rwobjects.h index bf3b422..3ee0cee 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -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 { enum { ID = 8 }; Object object; - uint32 geoflags; // TODO: rename + uint32 flags; int32 numTriangles; int32 numVertices; int32 numMorphTargets; @@ -390,22 +405,15 @@ struct Geometry : PluginBase 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 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 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; diff --git a/src/tristrip.cpp b/src/tristrip.cpp index 4df066d..195e1f7 100644 --- a/src/tristrip.cpp +++ b/src/tristrip.cpp @@ -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); diff --git a/tools/ps2/main.cpp b/tools/ps2/main.cpp index 1a2c949..859e4a5 100755 --- a/tools/ps2/main.cpp +++ b/tools/ps2/main.cpp @@ -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