mirror of https://github.com/aap/librw.git
some changes
This commit is contained in:
parent
56e48f4d76
commit
d20a6c3d04
|
@ -85,6 +85,7 @@ Global
|
|||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32
|
||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64
|
||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.Build.0 = Release|x64
|
||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
|
||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
|
|
|
@ -149,6 +149,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
@ -301,11 +301,6 @@ registerUVAnimInterpolator(void)
|
|||
|
||||
int32 uvAnimOffset;
|
||||
|
||||
struct UVAnim
|
||||
{
|
||||
AnimInterpolator *interp[8];
|
||||
};
|
||||
|
||||
static void*
|
||||
createUVAnim(void *object, int32 offset, int32)
|
||||
{
|
||||
|
@ -367,7 +362,7 @@ makeDummyAnimation(const char *name)
|
|||
static void
|
||||
readUVAnim(Stream *stream, int32, void *object, int32 offset, int32)
|
||||
{
|
||||
UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset);
|
||||
UVAnim *uvanim = PLUGINOFFSET(UVAnim, object, offset);
|
||||
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
||||
char name[32];
|
||||
uint32 mask = stream->readI32();
|
||||
|
|
|
@ -88,16 +88,21 @@ Frame::destroyHierarchy(void)
|
|||
}
|
||||
|
||||
Frame*
|
||||
Frame::addChild(Frame *child)
|
||||
Frame::addChild(Frame *child, bool32 append)
|
||||
{
|
||||
if(this->child == NULL)
|
||||
if(append){
|
||||
if(this->child == NULL)
|
||||
this->child = child;
|
||||
else{
|
||||
Frame *f;
|
||||
for(f = this->child; f->next; f = f->next);
|
||||
f->next = child;
|
||||
}
|
||||
child->next = NULL;
|
||||
}else{
|
||||
child->next = this->child;
|
||||
this->child = child;
|
||||
else{
|
||||
Frame *f;
|
||||
for(f = this->child; f->next; f = f->next);
|
||||
f->next = child;
|
||||
}
|
||||
child->next = NULL;
|
||||
child->object.parent = this;
|
||||
child->root = this->root;
|
||||
return this;
|
||||
|
@ -364,7 +369,8 @@ Clump::streamWrite(Stream *stream)
|
|||
writeChunkHeader(stream, ID_CLUMP, size);
|
||||
int32 numAtomics = this->countAtomics();
|
||||
int32 numLights = this->countLights();
|
||||
int buf[3] = { numAtomics, numLights, 0 };
|
||||
int32 numCameras = this->countCameras();
|
||||
int buf[3] = { numAtomics, numLights, numCameras };
|
||||
size = version > 0x33000 ? 12 : 4;
|
||||
writeChunkHeader(stream, ID_STRUCT, size);
|
||||
stream->write(buf, size);
|
||||
|
@ -372,7 +378,6 @@ Clump::streamWrite(Stream *stream)
|
|||
int32 numFrames = this->getFrame()->count();
|
||||
Frame **flist = new Frame*[numFrames];
|
||||
makeFrameList(this->getFrame(), flist);
|
||||
|
||||
this->frameListStreamWrite(stream, flist, numFrames);
|
||||
|
||||
if(rw::version >= 0x30400){
|
||||
|
@ -550,6 +555,18 @@ Atomic::create(void)
|
|||
atomic->geometry = NULL;
|
||||
atomic->pipeline = NULL;
|
||||
atomic->constructPlugins();
|
||||
|
||||
// flags:
|
||||
// rpATOMICCOLLISIONTEST = 0x01, /**<A generic collision flag to indicate
|
||||
// * that the atomic should be considered
|
||||
// * in collision tests.
|
||||
// */
|
||||
// rpATOMICRENDER = 0x04, /**<The atomic is rendered if it is
|
||||
// * in the view frustum.
|
||||
// */
|
||||
|
||||
// private flags:
|
||||
// rpATOMICPRIVATEWORLDBOUNDDIRTY = 0x01
|
||||
return atomic;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags)
|
|||
for(int32 i = 0; i < geo->numTexCoordSets; i++)
|
||||
geo->texCoords[i] =
|
||||
new float32[2*geo->numVertices];
|
||||
geo->triangles = new uint16[4*geo->numTriangles];
|
||||
geo->triangles = new Triangle[geo->numTriangles];
|
||||
}
|
||||
geo->morphTargets = new MorphTarget[1];
|
||||
MorphTarget *m = geo->morphTargets;
|
||||
|
@ -77,7 +77,7 @@ Geometry::destroy(void)
|
|||
for(int32 i = 0; i < this->numTexCoordSets; i++)
|
||||
delete[] this->texCoords[i];
|
||||
delete[] this->triangles;
|
||||
|
||||
|
||||
for(int32 i = 0; i < this->numMorphTargets; i++){
|
||||
MorphTarget *m = &this->morphTargets[i];
|
||||
delete[] m->vertices;
|
||||
|
@ -120,7 +120,14 @@ Geometry::streamRead(Stream *stream)
|
|||
for(int32 i = 0; i < geo->numTexCoordSets; i++)
|
||||
stream->read(geo->texCoords[i],
|
||||
2*geo->numVertices*4);
|
||||
stream->read(geo->triangles, 4*geo->numTriangles*2);
|
||||
for(int32 i = 0; i < geo->numTriangles; i++){
|
||||
uint32 tribuf[2];
|
||||
stream->read(tribuf, 8);
|
||||
geo->triangles[i].v[0] = tribuf[0] >> 16;
|
||||
geo->triangles[i].v[1] = tribuf[0];
|
||||
geo->triangles[i].v[2] = tribuf[1] >> 16;
|
||||
geo->triangles[i].matId = tribuf[1];
|
||||
}
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < geo->numMorphTargets; i++){
|
||||
|
@ -200,7 +207,14 @@ Geometry::streamWrite(Stream *stream)
|
|||
for(int32 i = 0; i < this->numTexCoordSets; i++)
|
||||
stream->write(this->texCoords[i],
|
||||
2*this->numVertices*4);
|
||||
stream->write(this->triangles, 4*this->numTriangles*2);
|
||||
for(int32 i = 0; i < this->numTriangles; i++){
|
||||
uint32 tribuf[2];
|
||||
tribuf[0] = this->triangles[i].v[0] << 16 |
|
||||
this->triangles[i].v[1];
|
||||
tribuf[1] = this->triangles[i].v[2] << 16 |
|
||||
this->triangles[i].matId;
|
||||
stream->write(tribuf, 8);
|
||||
}
|
||||
}
|
||||
|
||||
for(int32 i = 0; i < this->numMorphTargets; i++){
|
||||
|
@ -363,9 +377,9 @@ Geometry::generateTriangles(int8 *adc)
|
|||
}
|
||||
|
||||
delete[] this->triangles;
|
||||
this->triangles = new uint16[4*this->numTriangles];
|
||||
this->triangles = new Triangle[this->numTriangles];
|
||||
|
||||
uint16 *f = this->triangles;
|
||||
Triangle *tri = this->triangles;
|
||||
m = header->mesh;
|
||||
adcbits = adc;
|
||||
for(uint32 i = 0; i < header->numMeshes; i++){
|
||||
|
@ -382,23 +396,65 @@ Geometry::generateTriangles(int8 *adc)
|
|||
if(adc && adcbits[j+2] ||
|
||||
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)];
|
||||
tri->v[0] = m->indices[j+0];
|
||||
tri->v[1] = m->indices[j+1 + (j%2)];
|
||||
tri->v[2] = m->indices[j+2 - (j%2)];
|
||||
tri->matId = matid;
|
||||
tri++;
|
||||
}
|
||||
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];
|
||||
tri->v[0] = m->indices[j+0];
|
||||
tri->v[1] = m->indices[j+1];
|
||||
tri->v[2] = m->indices[j+2];
|
||||
tri->matId = matid;
|
||||
}
|
||||
adcbits += m->numIndices;
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Geometry::buildMeshes(void)
|
||||
{
|
||||
delete this->meshHeader;
|
||||
|
||||
Triangle *tri;
|
||||
MeshHeader *h = new MeshHeader;
|
||||
this->meshHeader = h;
|
||||
if((this->geoflags & Geometry::TRISTRIP) == 0){
|
||||
h->flags = 0;
|
||||
h->totalIndices = this->numTriangles*3;
|
||||
h->numMeshes = this->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].numIndices = 0;
|
||||
}
|
||||
// count indices per mesh
|
||||
tri = this->triangles;
|
||||
for(int32 i = 0; i < this->numTriangles; i++){
|
||||
h->mesh[tri->matId].numIndices += 3;
|
||||
tri++;
|
||||
}
|
||||
h->allocateIndices();
|
||||
for(uint32 i = 0; i < h->numMeshes; i++)
|
||||
h->mesh[i].numIndices = 0;
|
||||
// same as above but fill with indices
|
||||
tri = this->triangles;
|
||||
for(int32 i = 0; i < this->numTriangles; i++){
|
||||
uint32 idx = h->mesh[tri->matId].numIndices;
|
||||
h->mesh[tri->matId].indices[idx++] = tri->v[0];
|
||||
h->mesh[tri->matId].indices[idx++] = tri->v[1];
|
||||
h->mesh[tri->matId].indices[idx++] = tri->v[2];
|
||||
h->mesh[tri->matId].numIndices = idx;
|
||||
tri++;
|
||||
}
|
||||
}else{
|
||||
assert(0 && "can't tristrip\n");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Material
|
||||
//
|
||||
|
|
|
@ -61,6 +61,9 @@ attachPlugins(void)
|
|||
rw::ps2::registerNativeRaster();
|
||||
rw::xbox::registerNativeRaster();
|
||||
rw::d3d::registerNativeRaster();
|
||||
int32 nativeRasterOffset = Raster::registerPlugin(sizeof(NativeRaster),
|
||||
0x12340000 | PLATFORM_NULL, NULL, NULL, NULL);
|
||||
Raster::nativeOffsets[PLATFORM_NULL] = nativeRasterOffset;
|
||||
|
||||
rw::registerMeshPlugin();
|
||||
rw::registerNativeDataPlugin();
|
||||
|
@ -873,13 +876,6 @@ static bool hasColors2(uint32 id)
|
|||
return id == 0x53f20083 || id == 0x53f2008f;
|
||||
}
|
||||
|
||||
struct SaVert : ps2::Vertex {
|
||||
float32 w[4];
|
||||
uint8 i[4];
|
||||
float32 t1[2];
|
||||
uint8 c1[4];
|
||||
};
|
||||
|
||||
static void
|
||||
saPreCB(MatPipeline *p, Geometry *geo)
|
||||
{
|
||||
|
@ -916,27 +912,28 @@ findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v)
|
|||
cols1 = PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors;
|
||||
|
||||
for(int32 i = 0; i < g->numVertices; i++){
|
||||
if(mask & flags[i] & 0x1 &&
|
||||
uint32 flag = flags ? flags[i] : ~0;
|
||||
if(mask & flag & 0x1 &&
|
||||
!(verts[0] == v->p[0] && verts[1] == v->p[1] && verts[2] == v->p[2]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x10 &&
|
||||
if(mask & flag & 0x10 &&
|
||||
!(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x100 &&
|
||||
if(mask & flag & 0x100 &&
|
||||
!(cols0[0] == v->c[0] && cols0[1] == v->c[1] &&
|
||||
cols0[2] == v->c[2] && cols0[3] == v->c[3]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x200 &&
|
||||
if(mask & flag & 0x200 &&
|
||||
!(cols1[0] == v->c1[0] && cols1[1] == v->c1[1] &&
|
||||
cols1[2] == v->c1[2] && cols1[3] == v->c1[3]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x1000 &&
|
||||
if(mask & flag & 0x1000 &&
|
||||
!(tex0[0] == v->t[0] && tex0[1] == v->t[1]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x2000 &&
|
||||
if(mask & flag & 0x2000 &&
|
||||
!(tex1[0] == v->t1[0] && tex1[1] == v->t1[1]))
|
||||
goto cont;
|
||||
if(mask & flags[i] & 0x10000 &&
|
||||
if(mask & flag & 0x10000 &&
|
||||
!(wghts[0] == v->w[0] && wghts[1] == v->w[1] &&
|
||||
wghts[2] == v->w[2] && wghts[3] == v->w[3] &&
|
||||
inds[0] == v->i[0] && inds[1] == v->i[1] &&
|
||||
|
|
|
@ -124,6 +124,15 @@ void registerCollisionPlugin(void);
|
|||
|
||||
// PDS pipes
|
||||
|
||||
struct SaVert : ps2::Vertex {
|
||||
float32 w[4];
|
||||
uint8 i[4];
|
||||
float32 t1[2];
|
||||
uint8 c1[4];
|
||||
};
|
||||
void insertSAVertex(Geometry *geo, int32 i, uint32 mask, SaVert *v);
|
||||
int32 findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v);
|
||||
|
||||
void registerPDSPipes(void);
|
||||
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ Texture*
|
|||
Texture::streamRead(Stream *stream)
|
||||
{
|
||||
uint32 length;
|
||||
char name[32], mask[32];
|
||||
char name[128], mask[128];
|
||||
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
||||
uint32 filterAddressing = stream->readU32();
|
||||
// TODO: if V addressing is 0, copy U
|
||||
|
@ -197,18 +197,22 @@ bool
|
|||
Texture::streamWrite(Stream *stream)
|
||||
{
|
||||
int size;
|
||||
char buf[36];
|
||||
writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize());
|
||||
writeChunkHeader(stream, ID_STRUCT, 4);
|
||||
stream->writeU32(this->filterAddressing);
|
||||
|
||||
// TODO: length can't be > 32
|
||||
size = strlen(this->name)+4 & ~3;
|
||||
memset(buf, 0, 36);
|
||||
strncpy(buf, this->name, 32);
|
||||
size = strlen(buf)+4 & ~3;
|
||||
writeChunkHeader(stream, ID_STRING, size);
|
||||
stream->write(this->name, size);
|
||||
stream->write(buf, size);
|
||||
|
||||
size = strlen(this->mask)+4 & ~3;
|
||||
memset(buf, 0, 36);
|
||||
strncpy(buf, this->mask, 32);
|
||||
size = strlen(buf)+4 & ~3;
|
||||
writeChunkHeader(stream, ID_STRING, size);
|
||||
stream->write(this->mask, size);
|
||||
stream->write(buf, size);
|
||||
|
||||
this->streamWritePlugins(stream);
|
||||
return true;
|
||||
|
@ -640,7 +644,7 @@ Raster::calculateNumLevels(int32 width, int32 height)
|
|||
Raster*
|
||||
Raster::createFromImage(Image *image)
|
||||
{
|
||||
assert(0 && "unsupported atm");
|
||||
assert(0 && "cannot create raster from image");
|
||||
int32 format;
|
||||
// TODO: make that into a function
|
||||
if(image->depth == 32)
|
||||
|
|
216
src/plugins.cpp
216
src/plugins.cpp
|
@ -24,6 +24,101 @@ namespace rw {
|
|||
//
|
||||
|
||||
int32 hAnimOffset;
|
||||
bool32 hAnimDoStream = 1;
|
||||
|
||||
HAnimHierarchy*
|
||||
HAnimHierarchy::create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize)
|
||||
{
|
||||
HAnimHierarchy *hier = (HAnimHierarchy*)malloc(sizeof(*hier));
|
||||
|
||||
hier->numNodes = numNodes;
|
||||
hier->flags = flags;
|
||||
hier->maxInterpKeyFrameSize = maxKeySize;
|
||||
hier->parentFrame = NULL;
|
||||
hier->parentHierarchy = hier;
|
||||
if(hier->flags & 2)
|
||||
hier->matrices = hier->matricesUnaligned = NULL;
|
||||
else{
|
||||
hier->matricesUnaligned =
|
||||
(float*) new uint8[hier->numNodes*64 + 15];
|
||||
hier->matrices =
|
||||
(float*)((uintptr)hier->matricesUnaligned & ~0xF);
|
||||
}
|
||||
hier->nodeInfo = new HAnimNodeInfo[hier->numNodes];
|
||||
for(int32 i = 0; i < hier->numNodes; i++){
|
||||
hier->nodeInfo[i].id = nodeIDs[i];
|
||||
hier->nodeInfo[i].index = i;
|
||||
hier->nodeInfo[i].flags = nodeFlags[i];
|
||||
hier->nodeInfo[i].frame = NULL;
|
||||
}
|
||||
return hier;
|
||||
}
|
||||
|
||||
void
|
||||
HAnimHierarchy::destroy(void)
|
||||
{
|
||||
delete[] (uint8*)this->matricesUnaligned;
|
||||
delete[] this->nodeInfo;
|
||||
free(this);
|
||||
}
|
||||
|
||||
static Frame*
|
||||
findById(Frame *f, int32 id)
|
||||
{
|
||||
if(f == NULL) return NULL;
|
||||
HAnimData *hanim = HAnimData::get(f);
|
||||
if(hanim->id >= 0 && hanim->id == id) return f;
|
||||
Frame *ff = findById(f->next, id);
|
||||
if(ff) return ff;
|
||||
return findById(f->child, id);
|
||||
}
|
||||
|
||||
void
|
||||
HAnimHierarchy::attachByIndex(int32 idx)
|
||||
{
|
||||
int32 id = this->nodeInfo[idx].id;
|
||||
Frame *f = findById(this->parentFrame, id);
|
||||
this->nodeInfo[idx].frame = f;
|
||||
}
|
||||
|
||||
void
|
||||
HAnimHierarchy::attach(void)
|
||||
{
|
||||
for(int32 i = 0; i < this->numNodes; i++)
|
||||
this->attachByIndex(i);
|
||||
}
|
||||
|
||||
int32
|
||||
HAnimHierarchy::getIndex(int32 id)
|
||||
{
|
||||
for(int32 i = 0; i < this->numNodes; i++)
|
||||
if(this->nodeInfo[i].id == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAnimHierarchy*
|
||||
HAnimHierarchy::get(Frame *f)
|
||||
{
|
||||
return HAnimData::get(f)->hierarchy;
|
||||
}
|
||||
|
||||
HAnimHierarchy*
|
||||
HAnimHierarchy::find(Frame *f)
|
||||
{
|
||||
if(f == NULL) return NULL;
|
||||
HAnimHierarchy *hier = HAnimHierarchy::get(f);
|
||||
if(hier) return hier;
|
||||
hier = HAnimHierarchy::find(f->next);
|
||||
if(hier) return hier;
|
||||
return HAnimHierarchy::find(f->child);
|
||||
}
|
||||
|
||||
HAnimData*
|
||||
HAnimData::get(Frame *f)
|
||||
{
|
||||
return PLUGINOFFSET(HAnimData, f, hAnimOffset);
|
||||
}
|
||||
|
||||
static void*
|
||||
createHAnim(void *object, int32 offset, int32)
|
||||
|
@ -38,12 +133,8 @@ static void*
|
|||
destroyHAnim(void *object, int32 offset, int32)
|
||||
{
|
||||
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
|
||||
if(hanim->hierarchy){
|
||||
HAnimHierarchy *hier = hanim->hierarchy;
|
||||
delete[] (uint8*)hier->matricesUnaligned;
|
||||
delete[] hier->nodeInfo;
|
||||
delete hier;
|
||||
}
|
||||
if(hanim->hierarchy)
|
||||
hanim->hierarchy->destroy();
|
||||
hanim->id = -1;
|
||||
hanim->hierarchy = NULL;
|
||||
return object;
|
||||
|
@ -70,28 +161,20 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32)
|
|||
hanim->id = stream->readI32();
|
||||
numNodes = stream->readI32();
|
||||
if(numNodes != 0){
|
||||
HAnimHierarchy *hier = new HAnimHierarchy;
|
||||
hanim->hierarchy = hier;
|
||||
hier->numNodes = numNodes;
|
||||
hier->flags = stream->readI32();
|
||||
hier->maxInterpKeyFrameSize = stream->readI32();
|
||||
hier->parentFrame = (Frame*)object;
|
||||
hier->parentHierarchy = hier;
|
||||
if(hier->flags & 2)
|
||||
hier->matrices = hier->matricesUnaligned = NULL;
|
||||
else{
|
||||
hier->matricesUnaligned =
|
||||
(float*) new uint8[hier->numNodes*64 + 15];
|
||||
hier->matrices =
|
||||
(float*)((uintptr)hier->matricesUnaligned & ~0xF);
|
||||
}
|
||||
hier->nodeInfo = new HAnimNodeInfo[hier->numNodes];
|
||||
for(int32 i = 0; i < hier->numNodes; i++){
|
||||
hier->nodeInfo[i].id = stream->readI32();
|
||||
hier->nodeInfo[i].index = stream->readI32();
|
||||
hier->nodeInfo[i].flags = stream->readI32();
|
||||
hier->nodeInfo[i].frame = NULL;
|
||||
int32 flags = stream->readI32();
|
||||
int32 maxKeySize = stream->readI32();
|
||||
int32 *nodeFlags = new int32[numNodes];
|
||||
int32 *nodeIDs = new int32[numNodes];
|
||||
for(int32 i = 0; i < numNodes; i++){
|
||||
nodeIDs[i] = stream->readI32();
|
||||
stream->readI32(); // index...unused
|
||||
nodeFlags[i] = stream->readI32();
|
||||
}
|
||||
hanim->hierarchy = HAnimHierarchy::create(numNodes,
|
||||
nodeFlags, nodeIDs, flags, maxKeySize);
|
||||
hanim->hierarchy->parentFrame = (Frame*)object;
|
||||
delete[] nodeFlags;
|
||||
delete[] nodeIDs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,8 +204,9 @@ getSizeHAnim(void *object, int32 offset, int32)
|
|||
{
|
||||
HAnimData *hanim = PLUGINOFFSET(HAnimData, object, offset);
|
||||
// TODO: version correct?
|
||||
if(version >= 0x35000 && hanim->id == -1 && hanim->hierarchy == NULL)
|
||||
return -1;
|
||||
if(!hAnimDoStream ||
|
||||
version >= 0x35000 && hanim->id == -1 && hanim->hierarchy == NULL)
|
||||
return 0;
|
||||
if(hanim->hierarchy)
|
||||
return 12 + 8 + hanim->hierarchy->numNodes*12;
|
||||
return 12;
|
||||
|
@ -605,7 +689,7 @@ getSizeSkin(void *object, int32 offset, int32)
|
|||
static void
|
||||
skinRights(void *object, int32, int32, uint32)
|
||||
{
|
||||
((Atomic*)object)->pipeline = skinGlobals.pipelines[rw::platform];
|
||||
Skin::setPipeline((Atomic*)object, 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -712,6 +796,13 @@ Skin::findUsedBones(int32 numVertices)
|
|||
this->usedBones[this->numUsedBones++] = i;
|
||||
}
|
||||
|
||||
void
|
||||
Skin::setPipeline(Atomic *a, int32 type)
|
||||
{
|
||||
(void)type;
|
||||
a->pipeline = skinGlobals.pipelines[rw::platform];
|
||||
}
|
||||
|
||||
//
|
||||
// MatFX
|
||||
//
|
||||
|
@ -728,28 +819,22 @@ createAtomicMatFX(void *object, int32 offset, int32)
|
|||
static void*
|
||||
copyAtomicMatFX(void *dst, void *src, int32 offset, int32)
|
||||
{
|
||||
*PLUGINOFFSET(int32, dst, offset) = *PLUGINOFFSET(int32, src, offset);
|
||||
if(*PLUGINOFFSET(int32, src, offset))
|
||||
MatFX::enableEffects((Atomic*)dst);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static void
|
||||
readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
||||
{
|
||||
int32 flag;
|
||||
stream->read(&flag, 4);
|
||||
// printf("matfx: %d\n", flag);
|
||||
*PLUGINOFFSET(int32, object, offset) = flag;
|
||||
if(flag)
|
||||
((Atomic*)object)->pipeline =
|
||||
matFXGlobals.pipelines[rw::platform];
|
||||
if(stream->readI32())
|
||||
MatFX::enableEffects((Atomic*)object);
|
||||
}
|
||||
|
||||
static void
|
||||
writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
||||
{
|
||||
int32 flag;
|
||||
flag = *PLUGINOFFSET(int32, object, offset);
|
||||
stream->writeI32(flag);
|
||||
stream->writeI32(*PLUGINOFFSET(int32, object, offset));
|
||||
}
|
||||
|
||||
static int32
|
||||
|
@ -826,6 +911,22 @@ MatFX::getEffectIndex(uint32 type)
|
|||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setBumpTexture(Texture *t)
|
||||
{
|
||||
int32 i = this->getEffectIndex(BUMPMAP);
|
||||
if(i >= 0)
|
||||
this->fx[i].bump.tex = t;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setBumpCoefficient(float32 coef)
|
||||
{
|
||||
int32 i = this->getEffectIndex(BUMPMAP);
|
||||
if(i >= 0)
|
||||
this->fx[i].bump.coefficient = coef;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setEnvTexture(Texture *t)
|
||||
{
|
||||
|
@ -842,6 +943,30 @@ MatFX::setEnvCoefficient(float32 coef)
|
|||
this->fx[i].env.coefficient = coef;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setDualTexture(Texture *t)
|
||||
{
|
||||
int32 i = this->getEffectIndex(DUAL);
|
||||
if(i >= 0)
|
||||
this->fx[i].dual.tex = t;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setDualSrcBlend(int32 blend)
|
||||
{
|
||||
int32 i = this->getEffectIndex(DUAL);
|
||||
if(i >= 0)
|
||||
this->fx[i].dual.srcBlend = blend;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::setDualDestBlend(int32 blend)
|
||||
{
|
||||
int32 i = this->getEffectIndex(DUAL);
|
||||
if(i >= 0)
|
||||
this->fx[i].dual.dstBlend = blend;
|
||||
}
|
||||
|
||||
static void*
|
||||
createMaterialMatFX(void *object, int32 offset, int32)
|
||||
{
|
||||
|
@ -1038,11 +1163,18 @@ getSizeMaterialMatFX(void *object, int32 offset, int32)
|
|||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
MatFX::enableEffects(Atomic *atomic)
|
||||
{
|
||||
*PLUGINOFFSET(int32, atomic, matFXGlobals.atomicOffset) = 1;
|
||||
atomic->pipeline = matFXGlobals.pipelines[rw::platform];
|
||||
}
|
||||
|
||||
void
|
||||
registerMatFXPlugin(void)
|
||||
{
|
||||
ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL);
|
||||
defpipe->pluginID = ID_MATFX;
|
||||
defpipe->pluginID = 0; //ID_MATFX;
|
||||
defpipe->pluginData = 0;
|
||||
for(uint i = 0; i < nelem(matFXGlobals.pipelines); i++)
|
||||
matFXGlobals.pipelines[i] = defpipe;
|
||||
|
|
27
src/ps2.cpp
27
src/ps2.cpp
|
@ -233,6 +233,8 @@ static uint32
|
|||
getBatchSize(MatPipeline *pipe, uint32 vertCount)
|
||||
{
|
||||
PipeAttribute *a;
|
||||
if(vertCount == 0)
|
||||
return 0;
|
||||
uint32 size = 1; // ITOP &c. at the end
|
||||
for(uint i = 0; i < nelem(pipe->attribs); i++)
|
||||
if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){
|
||||
|
@ -393,21 +395,22 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m)
|
|||
im.numAttribs++;
|
||||
}
|
||||
uint32 totalVerts = 0;
|
||||
if(g->meshHeader->flags == 1){ // tristrip
|
||||
im.numBatches = 0;
|
||||
for(uint i = 0; i < m->numIndices; i += pipe->triStripCount-2){
|
||||
im.numBatches++;
|
||||
totalVerts += m->numIndices-i < pipe->triStripCount ?
|
||||
m->numIndices-i : pipe->triStripCount;
|
||||
}
|
||||
if(g->meshHeader->flags == MeshHeader::TRISTRIP){
|
||||
im.numBatches = (m->numIndices-2) / (pipe->triStripCount-2);
|
||||
im.batchVertCount = pipe->triStripCount;
|
||||
im.lastBatchVertCount = totalVerts % pipe->triStripCount;
|
||||
}else{ // trilist
|
||||
im.lastBatchVertCount = (m->numIndices-2) % (pipe->triStripCount-2);
|
||||
if(im.lastBatchVertCount){
|
||||
im.numBatches++;
|
||||
im.lastBatchVertCount += 2;
|
||||
}
|
||||
}else{
|
||||
im.numBatches = (m->numIndices+pipe->triListCount-1) /
|
||||
pipe->triListCount;
|
||||
im.batchVertCount = pipe->triListCount;
|
||||
im.lastBatchVertCount = m->numIndices % pipe->triListCount;
|
||||
}
|
||||
if(im.lastBatchVertCount == 0)
|
||||
im.lastBatchVertCount = im.batchVertCount;
|
||||
|
||||
im.batchSize = getBatchSize(pipe, im.batchVertCount);
|
||||
im.lastBatchSize = getBatchSize(pipe, im.lastBatchVertCount);
|
||||
|
@ -572,8 +575,10 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[]
|
|||
if((a = this->attribs[i]) && (a->attrib & AT_RW) == 0){
|
||||
uint32 asz = attribSize(a->attrib);
|
||||
p += 4;
|
||||
if((p[-1] & 0xff004000) != a->attrib)
|
||||
printf("unexpected unpack: %08x %08x\n", p[-1], a->attrib);
|
||||
if((p[-1] & 0xff004000) != a->attrib){
|
||||
fprintf(stderr, "unexpected unpack xx: %08x %08x\n", p[-1], a->attrib);
|
||||
assert(0 && "unexpected unpack\n");
|
||||
}
|
||||
memcpy(datap[i], p, asz*nverts);
|
||||
datap[i] += asz*(nverts-overlap);
|
||||
p += QWC(asz*nverts)*4;
|
||||
|
|
|
@ -25,6 +25,16 @@ int32 build = 0xFFFF;
|
|||
#endif
|
||||
char *debugFile = NULL;
|
||||
|
||||
void
|
||||
matrixIdentify(float32 *mat)
|
||||
{
|
||||
memset(mat, 0, 64);
|
||||
mat[0] = 1.0f;
|
||||
mat[5] = 1.0f;
|
||||
mat[10] = 1.0f;
|
||||
mat[16] = 1.0f;
|
||||
}
|
||||
|
||||
void
|
||||
matrixMult(float32 *out, float32 *a, float32 *b)
|
||||
{
|
||||
|
@ -32,17 +42,41 @@ matrixMult(float32 *out, float32 *a, float32 *b)
|
|||
#define L(i,j) out[i*4+j]
|
||||
#define A(i,j) a[i*4+j]
|
||||
#define B(i,j) b[i*4+j]
|
||||
for(int i = 0; i < 4; i++)
|
||||
for(int j = 0; j < 4; j++)
|
||||
L(i,j) = A(0,j)*B(i,0)
|
||||
+ A(1,j)*B(i,1)
|
||||
+ A(2,j)*B(i,2)
|
||||
+ A(3,j)*B(i,3);
|
||||
for(int i = 0; i < 4; i++)
|
||||
for(int j = 0; j < 4; j++)
|
||||
L(i,j) = A(0,j)*B(i,0)
|
||||
+ A(1,j)*B(i,1)
|
||||
+ A(2,j)*B(i,2)
|
||||
+ A(3,j)*B(i,3);
|
||||
#undef L
|
||||
#undef A
|
||||
#undef B
|
||||
}
|
||||
|
||||
void
|
||||
vecTrans(float32 *out, float32 *mat, float32 *vec)
|
||||
{
|
||||
#define M(i,j) mat[i*4+j]
|
||||
for(int i = 0; i < 4; i++)
|
||||
out[i] = M(0,i)*vec[0]
|
||||
+ M(1,i)*vec[1]
|
||||
+ M(2,i)*vec[2]
|
||||
+ M(3,i)*vec[3];
|
||||
#undef M
|
||||
}
|
||||
|
||||
void
|
||||
matrixTranspose(float32 *out, float32 *in)
|
||||
{
|
||||
#define OUT(i,j) out[i*4+j]
|
||||
#define IN(i,j) in[i*4+j]
|
||||
for(int i = 0; i < 4; i++)
|
||||
for(int j = 0; j < 4; j++)
|
||||
OUT(i,j) = IN(j,i);
|
||||
#undef IN
|
||||
#undef OUT
|
||||
}
|
||||
|
||||
void
|
||||
matrixInvert(float32 *out, float32 *m)
|
||||
{
|
||||
|
|
|
@ -153,7 +153,10 @@ extern int build;
|
|||
extern int platform;
|
||||
extern char *debugFile;
|
||||
|
||||
void matrixIdentify(float32 *mat);
|
||||
void matrixMult(float32 *out, float32 *a, float32 *b);
|
||||
void vecTrans(float32 *out, float32 *mat, float32 *vec);
|
||||
void matrixTranspose(float32 *out, float32 *in);
|
||||
void matrixInvert(float32 *out, float32 *in);
|
||||
|
||||
// 0x04000000 3.1
|
||||
|
|
|
@ -132,7 +132,7 @@ struct Frame : PluginBase<Frame>
|
|||
Frame *cloneHierarchy(void);
|
||||
void destroy(void);
|
||||
void destroyHierarchy(void);
|
||||
Frame *addChild(Frame *f);
|
||||
Frame *addChild(Frame *f, bool32 append = 0);
|
||||
Frame *removeChild(void);
|
||||
Frame *forAllChildren(Callback cb, void *data);
|
||||
Frame *getParent(void){
|
||||
|
@ -144,6 +144,13 @@ struct Frame : PluginBase<Frame>
|
|||
void setHierarchyRoot(Frame *root);
|
||||
Frame *cloneAndLink(Frame *clonedroot);
|
||||
void purgeClone(void);
|
||||
|
||||
// private flags:
|
||||
// #define rwFRAMEPRIVATEHIERARCHYSYNCLTM 0x01
|
||||
// #define rwFRAMEPRIVATEHIERARCHYSYNCOBJ 0x02
|
||||
// #define rwFRAMEPRIVATESUBTREESYNCLTM 0x04
|
||||
// #define rwFRAMEPRIVATESUBTREESYNCOBJ 0x08
|
||||
// #define rwFRAMEPRIVATESTATIC 0x10
|
||||
};
|
||||
|
||||
Frame **makeFrameList(Frame *frame, Frame **flist);
|
||||
|
@ -191,15 +198,32 @@ struct HAnimHierarchy
|
|||
|
||||
// temporary
|
||||
int32 maxInterpKeyFrameSize;
|
||||
|
||||
static HAnimHierarchy *create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize);
|
||||
void destroy(void);
|
||||
void attachByIndex(int32 id);
|
||||
void attach(void);
|
||||
int32 getIndex(int32 id);
|
||||
|
||||
static HAnimHierarchy *get(Frame *f);
|
||||
static HAnimHierarchy *find(Frame *f);
|
||||
|
||||
enum NodeFlag {
|
||||
POP = 1,
|
||||
PUSH
|
||||
};
|
||||
};
|
||||
|
||||
struct HAnimData
|
||||
{
|
||||
int32 id;
|
||||
HAnimHierarchy *hierarchy;
|
||||
|
||||
static HAnimData *get(Frame *f);
|
||||
};
|
||||
|
||||
extern int32 hAnimOffset;
|
||||
extern bool32 hAnimDoStream;
|
||||
void registerHAnimPlugin(void);
|
||||
|
||||
struct Image
|
||||
|
@ -362,7 +386,7 @@ struct MatFX
|
|||
NOTHING = 0,
|
||||
BUMPMAP,
|
||||
ENVMAP,
|
||||
BUMPENVMAP,
|
||||
BUMPENVMAP, // BUMP | ENV
|
||||
DUAL,
|
||||
UVTRANSFORM,
|
||||
DUALUVTRANSFORM
|
||||
|
@ -401,8 +425,15 @@ struct MatFX
|
|||
|
||||
void setEffects(uint32 flags);
|
||||
int32 getEffectIndex(uint32 type);
|
||||
void setBumpTexture(Texture *t);
|
||||
void setBumpCoefficient(float32 coef);
|
||||
void setEnvTexture(Texture *t);
|
||||
void setEnvCoefficient(float32 coef);
|
||||
void setDualTexture(Texture *t);
|
||||
void setDualSrcBlend(int32 blend);
|
||||
void setDualDestBlend(int32 blend);
|
||||
|
||||
static void enableEffects(Atomic *atomic);
|
||||
};
|
||||
|
||||
struct MatFXGlobals
|
||||
|
@ -423,6 +454,9 @@ struct Mesh
|
|||
|
||||
struct MeshHeader
|
||||
{
|
||||
enum {
|
||||
TRISTRIP = 1
|
||||
};
|
||||
uint32 flags;
|
||||
uint16 numMeshes;
|
||||
// RW has uint16 serialNum here
|
||||
|
@ -445,6 +479,12 @@ struct InstanceDataHeader
|
|||
uint32 platform;
|
||||
};
|
||||
|
||||
struct Triangle
|
||||
{
|
||||
uint16 v[3];
|
||||
uint16 matId;
|
||||
};
|
||||
|
||||
struct Geometry : PluginBase<Geometry>
|
||||
{
|
||||
enum { ID = 8 };
|
||||
|
@ -455,7 +495,7 @@ struct Geometry : PluginBase<Geometry>
|
|||
int32 numMorphTargets;
|
||||
int32 numTexCoordSets;
|
||||
|
||||
uint16 *triangles;
|
||||
Triangle *triangles;
|
||||
uint8 *colors;
|
||||
float32 *texCoords[8];
|
||||
|
||||
|
@ -481,6 +521,7 @@ struct Geometry : PluginBase<Geometry>
|
|||
bool32 hasColoredMaterial(void);
|
||||
void allocateData(void);
|
||||
void generateTriangles(int8 *adc = NULL);
|
||||
void buildMeshes(void);
|
||||
|
||||
enum Flags
|
||||
{
|
||||
|
@ -515,6 +556,7 @@ struct Skin
|
|||
void init(int32 numBones, int32 numUsedBones, int32 numVertices);
|
||||
void findNumWeights(int32 numVertices);
|
||||
void findUsedBones(int32 numVertices);
|
||||
static void setPipeline(Atomic *a, int32 type);
|
||||
};
|
||||
|
||||
struct SkinGlobals
|
||||
|
@ -769,6 +811,11 @@ struct UVAnimDictionary
|
|||
|
||||
extern UVAnimDictionary *currentUVAnimDictionary;
|
||||
|
||||
struct UVAnim
|
||||
{
|
||||
AnimInterpolator *interp[8];
|
||||
};
|
||||
|
||||
extern int32 uvAnimOffset;
|
||||
|
||||
void registerUVAnimPlugin(void);
|
||||
|
|
14
src/rwps2.h
14
src/rwps2.h
|
@ -172,13 +172,13 @@ void registerPDSPlugin(int32 n);
|
|||
|
||||
struct Ps2Raster : NativeRaster
|
||||
{
|
||||
uint32 tex0[2];
|
||||
uint32 tex1[2];
|
||||
uint32 miptbp1[2];
|
||||
uint32 miptbp2[2];
|
||||
uint32 texelSize;
|
||||
uint32 paletteSize;
|
||||
uint32 gsSize;
|
||||
uint32 tex0[2];
|
||||
uint32 tex1[2];
|
||||
uint32 miptbp1[2];
|
||||
uint32 miptbp2[2];
|
||||
uint32 texelSize;
|
||||
uint32 paletteSize;
|
||||
uint32 gsSize;
|
||||
int8 flags;
|
||||
|
||||
uint8 *data; //tmp
|
||||
|
|
|
@ -36,6 +36,42 @@ usage(void)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
dumpUVAnim(Animation *anim)
|
||||
{
|
||||
UVAnimCustomData *cust = (UVAnimCustomData*)anim->customData;
|
||||
printf(" %s", cust->name);
|
||||
for(int i = 0; i < 8; i++)
|
||||
printf(" %d", cust->nodeToUVChannel[i]);
|
||||
printf("\n %d %x\n", anim->numFrames, anim->interpInfo->id);
|
||||
UVAnimKeyFrame *kf = (UVAnimKeyFrame*)anim->keyframes;
|
||||
for(int i = 0; i < anim->numFrames; i++){
|
||||
printf(" %f\n", kf->time);
|
||||
printf(" %f %f %f %f %f %f\n", kf->uv[0], kf->uv[1], kf->uv[2], kf->uv[3], kf->uv[4], kf->uv[5]);
|
||||
kf++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpFrameHier(Frame *frame, int ind = 0)
|
||||
{
|
||||
for(int i = 0; i < ind; i++)
|
||||
printf(" ");
|
||||
char *name = gta::getNodeName(frame);
|
||||
HAnimData *hanim = HAnimData::get(frame);
|
||||
printf("*%s %d %d %s\n", name[0] ? name : "---", frame->objectList.count(), hanim->id, hanim->hierarchy ? "HIERARCHY" : "");
|
||||
if(hanim->hierarchy){
|
||||
HAnimHierarchy *h = hanim->hierarchy;
|
||||
for(int i = 0; i < h->numNodes; i++){
|
||||
name = h->nodeInfo[i].frame ? gta::getNodeName(h->nodeInfo[i].frame) : "";
|
||||
printf("\t\t%d %d\t%p %s\n", h->nodeInfo[i].id, h->nodeInfo[i].flags, h->nodeInfo[i].frame, name);
|
||||
}
|
||||
}
|
||||
for(Frame *child = frame->child;
|
||||
child; child = child->next)
|
||||
dumpFrameHier(child, ind+1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -106,7 +142,10 @@ main(int argc, char *argv[])
|
|||
currentUVAnimDictionary = dict;
|
||||
readChunkHeaderInfo(&in, &header);
|
||||
}
|
||||
assert(header.type == ID_CLUMP);
|
||||
if(header.type != ID_CLUMP){
|
||||
in.close();
|
||||
return 0;
|
||||
}
|
||||
debugFile = argv[0];
|
||||
c = Clump::streamRead(&in);
|
||||
assert(c != NULL);
|
||||
|
@ -132,6 +171,19 @@ main(int argc, char *argv[])
|
|||
// printf("%d %f %f %f\n", l->getType(), l->color.red, l->color.green, l->color.blue);
|
||||
//}
|
||||
|
||||
HAnimHierarchy *hier = HAnimHierarchy::find(c->getFrame());
|
||||
if(hier)
|
||||
hier->attach();
|
||||
dumpFrameHier(c->getFrame());
|
||||
|
||||
//if(currentUVAnimDictionary){
|
||||
// FORLIST(lnk, currentUVAnimDictionary->animations){
|
||||
// UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk);
|
||||
// Animation *anim = de->anim;
|
||||
// dumpUVAnim(anim);
|
||||
// }
|
||||
//}
|
||||
|
||||
int32 platform = findPlatform(c);
|
||||
if(platform){
|
||||
rw::platform = platform;
|
||||
|
@ -192,10 +244,10 @@ main(int argc, char *argv[])
|
|||
// out.close();
|
||||
// delete[] data;
|
||||
|
||||
c->destroy();
|
||||
if(currentUVAnimDictionary)
|
||||
currentUVAnimDictionary->destroy();
|
||||
//currentTexDictionary->destroy();
|
||||
c->destroy();
|
||||
currentTexDictionary->destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)</IncludePath>
|
||||
<LibraryPath>$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)</LibraryPath>
|
||||
<LibraryPath>$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(SolutionDir)$(Platform)\$(Configuration)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -202,6 +202,9 @@
|
|||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>librw.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy /y "$(TargetPath)" "C:\Users\aap\bin\"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="insttest.cpp" />
|
||||
|
|
|
@ -13,6 +13,7 @@ using namespace rw;
|
|||
#include "rsl.h"
|
||||
|
||||
char *argv0;
|
||||
int32 atmOffset;
|
||||
|
||||
void
|
||||
RslStream::relocate(void)
|
||||
|
@ -68,6 +69,33 @@ mapID(int32 id)
|
|||
return id;
|
||||
}
|
||||
|
||||
static RslFrame*
|
||||
findFrame(RslFrame *f, int32 id)
|
||||
{
|
||||
if(f == NULL) return NULL;
|
||||
if((f->nodeId & 0xFF) == (id & 0xFF))
|
||||
return f;
|
||||
RslFrame *ff = findFrame(f->next, id);
|
||||
if(ff) return ff;
|
||||
return findFrame(f->child, id);
|
||||
}
|
||||
|
||||
static RslFrame*
|
||||
findChild(RslFrame *f)
|
||||
{
|
||||
for(RslFrame *c = f->child; c; c = c->next)
|
||||
if(c->nodeId < 0)
|
||||
return c;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32 nextId;
|
||||
|
||||
struct Node {
|
||||
int32 id;
|
||||
int32 parent;
|
||||
};
|
||||
|
||||
Frame*
|
||||
convertFrame(RslFrame *f)
|
||||
{
|
||||
|
@ -91,20 +119,46 @@ convertFrame(RslFrame *f)
|
|||
HAnimData *hanim = PLUGINOFFSET(HAnimData, rwf, hAnimOffset);
|
||||
hanim->id = f->nodeId;
|
||||
if(f->hier){
|
||||
HAnimHierarchy *hier;
|
||||
hanim->hierarchy = hier = new HAnimHierarchy;
|
||||
hier->numNodes = f->hier->numNodes;
|
||||
hier->flags = f->hier->flags;
|
||||
hier->maxInterpKeyFrameSize = f->hier->maxKeyFrameSize;
|
||||
hier->parentFrame = rwf;
|
||||
hier->parentHierarchy = hier;
|
||||
hier->nodeInfo = new HAnimNodeInfo[hier->numNodes];
|
||||
for(int32 i = 0; i < hier->numNodes; i++){
|
||||
hier->nodeInfo[i].id = mapID((uint8)f->hier->pNodeInfo[i].id);
|
||||
hier->nodeInfo[i].index = f->hier->pNodeInfo[i].index;
|
||||
hier->nodeInfo[i].flags = f->hier->pNodeInfo[i].flags;
|
||||
hier->nodeInfo[i].frame = NULL;
|
||||
int32 numNodes = f->hier->numNodes;
|
||||
int32 *nodeFlags = new int32[numNodes];
|
||||
int32 *nodeIDs = new int32[numNodes];
|
||||
|
||||
nextId = 2000;
|
||||
Node *nodehier = new Node[numNodes];
|
||||
int32 stack[100];
|
||||
int32 sp = 0;
|
||||
stack[sp] = -1;
|
||||
// Match up nodes with frames to fix and assign IDs
|
||||
// NOTE: assignment can only work reliably when not more
|
||||
// than one child node needs an ID
|
||||
for(int32 i = 0; i < numNodes; i++){
|
||||
RslHAnimNodeInfo *ni = &f->hier->pNodeInfo[i];
|
||||
Node *n = &nodehier[i];
|
||||
n->parent = stack[sp];
|
||||
if(ni->flags & HAnimHierarchy::PUSH)
|
||||
sp++;
|
||||
stack[sp] = i;
|
||||
RslFrame *ff = findFrame(f, (uint8)ni->id);
|
||||
n->id = ff->nodeId;
|
||||
if(n->id < 0){
|
||||
ff = findFrame(f, nodehier[n->parent].id);
|
||||
ff = findChild(ff);
|
||||
n->id = ff->nodeId = nextId++;
|
||||
}
|
||||
//printf("%d %s %d %d\n", i, ff->name, n->id, n->parent);
|
||||
if(ni->flags & HAnimHierarchy::POP)
|
||||
sp--;
|
||||
|
||||
nodeFlags[i] = ni->flags;
|
||||
nodeIDs[i] = n->id;
|
||||
}
|
||||
|
||||
HAnimHierarchy *hier = HAnimHierarchy::create(numNodes, nodeFlags, nodeIDs, f->hier->flags, f->hier->maxKeyFrameSize);
|
||||
hanim->hierarchy = hier;
|
||||
|
||||
delete[] nodeFlags;
|
||||
delete[] nodeIDs;
|
||||
delete[] nodehier;
|
||||
}
|
||||
return rwf;
|
||||
}
|
||||
|
@ -302,6 +356,8 @@ convertAtomic(RslAtomic *atomic)
|
|||
Geometry *rwg = Geometry::create(0, 0, 0);
|
||||
rwa->geometry = rwg;
|
||||
|
||||
*PLUGINOFFSET(RslAtomic*, rwa, atmOffset) = atomic;
|
||||
|
||||
rwg->numMaterials = g->matList.numMaterials;
|
||||
rwg->materialList = new Material*[rwg->numMaterials];
|
||||
for(int32 i = 0; i < rwg->numMaterials; i++)
|
||||
|
@ -447,6 +503,41 @@ makeTextures(RslAtomic *atomic, void*)
|
|||
return atomic;
|
||||
}
|
||||
|
||||
void
|
||||
moveAtomics(Frame *f)
|
||||
{
|
||||
static char *names[] = { "", "hi_ok", "hi_dam" };
|
||||
if(f == NULL) return;
|
||||
int n = f->objectList.count();
|
||||
if(n > 1){
|
||||
char *oldname = gta::getNodeName(f);
|
||||
ObjectWithFrame **objs = new ObjectWithFrame*[n];
|
||||
int i = 0;
|
||||
FORLIST(lnk, f->objectList){
|
||||
ObjectWithFrame *obj = ObjectWithFrame::fromFrame(lnk);
|
||||
assert(obj->type == Atomic::ID);
|
||||
objs[i] = obj;
|
||||
obj->setFrame(NULL);
|
||||
i++;
|
||||
}
|
||||
for(i = 0; i < n; i++){
|
||||
Frame *ff = Frame::create();
|
||||
RslAtomic *rsla = *PLUGINOFFSET(RslAtomic*, objs[i], atmOffset);
|
||||
char *name = gta::getNodeName(ff);
|
||||
strncpy(name, oldname, 24);
|
||||
char *end = strrchr(name, '_');
|
||||
if(end){
|
||||
*(++end) = '\0';
|
||||
strcat(end, names[rsla->unk3&3]);
|
||||
}
|
||||
f->addChild(ff);
|
||||
objs[i]->setFrame(ff);
|
||||
}
|
||||
delete[] objs;
|
||||
}
|
||||
moveAtomics(f->next);
|
||||
moveAtomics(f->child);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -751,6 +842,7 @@ usage(void)
|
|||
fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n");
|
||||
fprintf(stderr, "\t-x extract textures to tga\n");
|
||||
fprintf(stderr, "\t-s don't unswizzle textures\n");
|
||||
fprintf(stderr, "\t-a fix Atomics placement inside hierarchy (mdl files)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -758,11 +850,13 @@ int
|
|||
main(int argc, char *argv[])
|
||||
{
|
||||
gta::attachPlugins();
|
||||
atmOffset = Atomic::registerPlugin(sizeof(void*), 0x1000000, NULL, NULL, NULL);
|
||||
rw::version = 0x34003;
|
||||
rw::platform = PLATFORM_D3D8;
|
||||
|
||||
assert(sizeof(void*) == 4);
|
||||
int extract = 0;
|
||||
int fixAtomics = 0;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'v':
|
||||
|
@ -774,6 +868,9 @@ main(int argc, char *argv[])
|
|||
case 'x':
|
||||
extract++;
|
||||
break;
|
||||
case 'a':
|
||||
fixAtomics++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND;
|
||||
|
@ -906,6 +1003,8 @@ main(int argc, char *argv[])
|
|||
}
|
||||
writeDff:
|
||||
rwc = convertClump(clump);
|
||||
if(fixAtomics)
|
||||
moveAtomics(rwc->getFrame());
|
||||
if(argc > 1)
|
||||
assert(stream.open(argv[1], "wb"));
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue