mirror of https://github.com/aap/librw.git
implemented reinstancing for d3d9
This commit is contained in:
parent
47fcb3001a
commit
f1c9112f27
|
@ -257,7 +257,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
|||
geo->instData = header;
|
||||
header->platform = PLATFORM_D3D8;
|
||||
|
||||
header->serialNumber = 0;
|
||||
header->serialNumber = meshh->serialNum;
|
||||
header->numMeshes = meshh->numMeshes;
|
||||
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
|
||||
|
|
|
@ -97,14 +97,12 @@ getDeclaration(void *declaration, VertexElement *elements)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
destroyNativeData(void *object, int32, int32)
|
||||
void
|
||||
freeInstanceData(Geometry *geometry)
|
||||
{
|
||||
Geometry *geometry = (Geometry*)object;
|
||||
if(geometry->instData == nil ||
|
||||
geometry->instData->platform != PLATFORM_D3D9)
|
||||
return object;
|
||||
return;
|
||||
InstanceDataHeader *header =
|
||||
(InstanceDataHeader*)geometry->instData;
|
||||
geometry->instData = nil;
|
||||
|
@ -114,6 +112,14 @@ destroyNativeData(void *object, int32, int32)
|
|||
deleteObject(header->vertexStream[1].vertexBuffer);
|
||||
rwFree(header->inst);
|
||||
rwFree(header);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
destroyNativeData(void *object, int32, int32)
|
||||
{
|
||||
freeInstanceData((Geometry*)object);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -309,23 +315,18 @@ registerNativeDataPlugin(void)
|
|||
getSizeNativeData);
|
||||
}
|
||||
|
||||
static void
|
||||
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
||||
static InstanceDataHeader*
|
||||
instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo)
|
||||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
// TODO: allow for REINSTANCE
|
||||
if(geo->instData)
|
||||
return;
|
||||
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
MeshHeader *meshh = geo->meshHeader;
|
||||
geo->instData = header;
|
||||
header->platform = PLATFORM_D3D9;
|
||||
|
||||
header->serialNumber = 0;
|
||||
header->serialNumber = meshh->serialNum;
|
||||
header->numMeshes = meshh->numMeshes;
|
||||
header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
|
||||
header->useOffsets = 0;
|
||||
header->vertexDeclaration = nil;
|
||||
header->totalNumVertex = geo->numVertices;
|
||||
header->totalNumIndex = meshh->totalIndices;
|
||||
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
|
@ -359,7 +360,36 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
|||
|
||||
memset(&header->vertexStream, 0, 2*sizeof(VertexStream));
|
||||
|
||||
pipe->instanceCB(geo, header);
|
||||
return header;
|
||||
}
|
||||
|
||||
static void
|
||||
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
||||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
// don't try to (re)instance native data
|
||||
if(geo->flags & Geometry::NATIVE)
|
||||
return;
|
||||
|
||||
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
|
||||
if(geo->instData){
|
||||
// Already have instanced data, so check if we have to reinstance
|
||||
assert(header->platform == PLATFORM_D3D9);
|
||||
if(header->serialNumber != geo->meshHeader->serialNum){
|
||||
// Mesh changed, so reinstance everything
|
||||
freeInstanceData(geo);
|
||||
}
|
||||
}
|
||||
|
||||
// no instance or complete reinstance
|
||||
if(geo->instData == nil){
|
||||
geo->instData = instanceMesh(rwpipe, geo);
|
||||
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0);
|
||||
}else if(geo->lockedSinceInst)
|
||||
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1);
|
||||
|
||||
geo->lockedSinceInst = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -401,8 +431,6 @@ render(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
|||
{
|
||||
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
|
||||
Geometry *geo = atomic->geometry;
|
||||
// TODO: allow for REINSTANCE
|
||||
if(geo->instData == nil)
|
||||
pipe->instance(atomic);
|
||||
assert(geo->instData != nil);
|
||||
assert(geo->instData->platform == PLATFORM_D3D9);
|
||||
|
@ -422,17 +450,26 @@ ObjPipeline::ObjPipeline(uint32 platform)
|
|||
}
|
||||
|
||||
void
|
||||
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
||||
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
|
||||
{
|
||||
int i = 0;
|
||||
VertexElement dcl[NUMDECLELT];
|
||||
|
||||
VertexStream *s = &header->vertexStream[0];
|
||||
|
||||
bool isPrelit = (geo->flags & Geometry::PRELIT) != 0;
|
||||
bool hasNormals = (geo->flags & Geometry::NORMALS) != 0;
|
||||
|
||||
// TODO: support both vertex buffers
|
||||
|
||||
if(!reinstance){
|
||||
// Create declarations and buffers only the first time
|
||||
|
||||
assert(s->vertexBuffer == nil);
|
||||
s->offset = 0;
|
||||
s->managed = 1;
|
||||
s->geometryFlags = 0;
|
||||
s->dynamicLock = 0;
|
||||
|
||||
int i = 0;
|
||||
dcl[i].stream = 0;
|
||||
dcl[i].offset = 0;
|
||||
dcl[i].type = D3DDECLTYPE_FLOAT3;
|
||||
|
@ -443,7 +480,6 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|||
uint16 stride = 12;
|
||||
s->geometryFlags |= 0x2;
|
||||
|
||||
bool isPrelit = (geo->flags & Geometry::PRELIT) != 0;
|
||||
if(isPrelit){
|
||||
dcl[i].stream = 0;
|
||||
dcl[i].offset = stride;
|
||||
|
@ -468,7 +504,6 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|||
stride += 8;
|
||||
}
|
||||
|
||||
bool hasNormals = (geo->flags & Geometry::NORMALS) != 0;
|
||||
if(hasNormals){
|
||||
dcl[i].stream = 0;
|
||||
dcl[i].offset = stride;
|
||||
|
@ -481,22 +516,29 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|||
stride += 12;
|
||||
}
|
||||
dcl[i] = D3DDECL_END();
|
||||
header->vertexStream[0].stride = stride;
|
||||
s->stride = stride;
|
||||
|
||||
assert(header->vertexDeclaration == nil);
|
||||
header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
|
||||
|
||||
s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, 0, D3DPOOL_MANAGED);
|
||||
}else
|
||||
getDeclaration(header->vertexDeclaration, dcl);
|
||||
|
||||
// TODO: support both vertex buffers
|
||||
uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
|
||||
|
||||
// Instance vertices
|
||||
if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
|
||||
for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
|
||||
;
|
||||
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
|
||||
geo->morphTargets[0].vertices,
|
||||
header->totalNumVertex,
|
||||
header->vertexStream[dcl[i].stream].stride);
|
||||
}
|
||||
|
||||
if(isPrelit){
|
||||
// Instance prelight colors
|
||||
if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
|
||||
for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
|
||||
;
|
||||
InstanceData *inst = header->inst;
|
||||
|
@ -512,7 +554,9 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|||
}
|
||||
}
|
||||
|
||||
// Instance tex coords
|
||||
for(int32 n = 0; n < geo->numTexCoordSets; n++){
|
||||
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
|
||||
for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != n; i++)
|
||||
;
|
||||
instTexCoords(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
|
||||
|
@ -520,8 +564,10 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
|
|||
header->totalNumVertex,
|
||||
header->vertexStream[dcl[i].stream].stride);
|
||||
}
|
||||
}
|
||||
|
||||
if(hasNormals){
|
||||
// Instance normals
|
||||
if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
|
||||
for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
|
||||
;
|
||||
instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
|
||||
|
|
|
@ -67,14 +67,14 @@ void registerNativeDataPlugin(void);
|
|||
class ObjPipeline : public rw::ObjPipeline
|
||||
{
|
||||
public:
|
||||
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
|
||||
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
|
||||
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
|
||||
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
|
||||
|
||||
ObjPipeline(uint32 platform);
|
||||
};
|
||||
|
||||
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header);
|
||||
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
|
||||
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
|
||||
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
|||
// The 0x18 byte are the resentryheader.
|
||||
// We don't have it but it's used for alignment.
|
||||
header->data = rwNewT(uint8, header->size + 0x18, MEMDUR_EVENT | ID_GEOMETRY);
|
||||
header->serialNumber = 0;
|
||||
header->serialNumber = meshh->serialNum;
|
||||
header->numMeshes = meshh->numMeshes;
|
||||
header->primType = meshh->flags == MeshHeader::TRISTRIP ?
|
||||
D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
|
||||
|
|
|
@ -73,6 +73,7 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
|
|||
geo->addMorphTargets(1);
|
||||
|
||||
geo->matList.init();
|
||||
geo->lockedSinceInst = 0;
|
||||
geo->meshHeader = nil;
|
||||
geo->instData = nil;
|
||||
geo->refCount = 1;
|
||||
|
@ -98,6 +99,24 @@ Geometry::destroy(void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Geometry::lock(int32 lockFlags)
|
||||
{
|
||||
lockedSinceInst |= lockFlags;
|
||||
if(lockFlags & LOCKPOLYGONS){
|
||||
rwFree(this->meshHeader);
|
||||
this->meshHeader = nil;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Geometry::unlock(void)
|
||||
{
|
||||
if(this->meshHeader == nil)
|
||||
this->buildMeshes();
|
||||
|
||||
}
|
||||
|
||||
struct GeoStreamData
|
||||
{
|
||||
uint32 flags;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
namespace rw {
|
||||
|
||||
static uint16 nextSerialNum = 1;
|
||||
|
||||
// Mesh
|
||||
|
||||
// Allocate a mesh header, meshes and optionally indices.
|
||||
|
@ -50,7 +52,7 @@ Geometry::allocateMeshes(int32 numMeshes, uint32 numIndices, bool32 noIndices)
|
|||
this->meshHeader = mh;
|
||||
}
|
||||
mh->numMeshes = numMeshes;
|
||||
mh->serialNum = 0; // TODO
|
||||
mh->serialNum = nextSerialNum++;
|
||||
mh->totalIndices = numIndices;
|
||||
m = mh->getMeshes();
|
||||
indices = (uint16*)&m[numMeshes];
|
||||
|
|
|
@ -35,7 +35,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
|
|||
geo->instData = header;
|
||||
header->platform = PLATFORM_GL3;
|
||||
|
||||
header->serialNumber = 0;
|
||||
header->serialNumber = meshh->serialNum;
|
||||
header->numMeshes = meshh->numMeshes;
|
||||
header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES;
|
||||
header->totalNumVertex = geo->numVertices;
|
||||
|
|
|
@ -343,7 +343,7 @@ struct MeshHeader
|
|||
};
|
||||
uint32 flags;
|
||||
uint16 numMeshes;
|
||||
uint16 serialNum; // not used yet
|
||||
uint16 serialNum;
|
||||
uint32 totalIndices;
|
||||
uint32 pad; // needed for alignment of Meshes
|
||||
// after this the meshes
|
||||
|
@ -391,13 +391,13 @@ struct MaterialList
|
|||
uint32 streamGetSize(void);
|
||||
};
|
||||
|
||||
// TODO: implement locking
|
||||
struct Geometry
|
||||
{
|
||||
PLUGINBASE
|
||||
enum { ID = 8 };
|
||||
Object object;
|
||||
uint32 flags;
|
||||
uint16 lockedSinceInst;
|
||||
int32 numTriangles;
|
||||
int32 numVertices;
|
||||
int32 numMorphTargets;
|
||||
|
@ -417,6 +417,8 @@ struct Geometry
|
|||
|
||||
static Geometry *create(int32 numVerts, int32 numTris, uint32 flags);
|
||||
void destroy(void);
|
||||
void lock(int32 lockFlags);
|
||||
void unlock(void);
|
||||
void addMorphTargets(int32 n);
|
||||
void calculateBoundingSphere(void);
|
||||
bool32 hasColoredMaterial(void);
|
||||
|
@ -453,6 +455,26 @@ struct Geometry
|
|||
NATIVEINSTANCE = 0x02000000
|
||||
};
|
||||
|
||||
enum LockFlags
|
||||
{
|
||||
LOCKPOLYGONS = 0x0001,
|
||||
LOCKVERTICES = 0x0002,
|
||||
LOCKNORMALS = 0x0004,
|
||||
LOCKPRELIGHT = 0x0008,
|
||||
|
||||
LOCKTEXCOORDS = 0x0010,
|
||||
LOCKTEXCOORDS1 = 0x0010,
|
||||
LOCKTEXCOORDS2 = 0x0020,
|
||||
LOCKTEXCOORDS3 = 0x0040,
|
||||
LOCKTEXCOORDS4 = 0x0080,
|
||||
LOCKTEXCOORDS5 = 0x0100,
|
||||
LOCKTEXCOORDS6 = 0x0200,
|
||||
LOCKTEXCOORDS7 = 0x0400,
|
||||
LOCKTEXCOORDS8 = 0x0800,
|
||||
LOCKTEXCOORDSALL = 0x0ff0,
|
||||
|
||||
LOCKALL = 0x0fff
|
||||
};
|
||||
};
|
||||
|
||||
void registerMeshPlugin(void);
|
||||
|
|
Loading…
Reference in New Issue