Implemented MatFX.

This commit is contained in:
Angelo Papenhoff 2015-01-09 20:17:32 +01:00
parent e373b47041
commit e1bb20c800
8 changed files with 481 additions and 34 deletions

View File

@ -18,6 +18,9 @@ main(int argc, char *argv[])
// Rw::Version = 0x33002;
Rw::RegisterMaterialRightsPlugin();
Rw::RegisterMatFXPlugin();
Rw::RegisterAtomicRightsPlugin();
Rw::RegisterNodeNamePlugin();
Rw::RegisterBreakableModelPlugin();
Rw::RegisterExtraVertColorPlugin();
@ -26,6 +29,7 @@ main(int argc, char *argv[])
Rw::RegisterNativeDataPlugin();
// Rw::Ps2::RegisterNativeDataPlugin();
Rw::RegisterMeshPlugin();
Rw::Clump *c;
// ifstream in(argv[1], ios::binary);
@ -45,6 +49,7 @@ main(int argc, char *argv[])
in.open(data, len);
Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL);
Rw::DebugFile = argv[1];
c = Rw::Clump::streamRead(&in);
assert(c != NULL);

View File

@ -117,7 +117,9 @@ makeFrameList(Frame *frame, Frame **flist)
return flist;
}
//
// Clump
//
Clump::Clump(void)
{
@ -367,6 +369,9 @@ Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames)
frameList[i]->streamWritePlugins(stream);
}
//
// Atomic
//
Atomic::Atomic(void)
{
@ -430,6 +435,33 @@ Atomic::streamGetSize(void)
return 12 + 16 + 12 + this->streamGetPluginSize();
}
// Atomic Rights plugin
static void
readAtomicRights(Stream *stream, int32, void *, int32, int32)
{
uint32 buffer[2];
uint32 version;
stream->seek(-4);
version = stream->readU32();
stream->read(buffer, 8);
// printf("atomicrights: %s %X %X %X\n", DebugFile, LibraryIDUnpackVersion(version), buffer[0], buffer[1]);
printf("atomicrights: %X %X %X\n", LibraryIDUnpackVersion(version), buffer[0], buffer[1]);
}
void
RegisterAtomicRightsPlugin(void)
{
Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
Atomic::registerPluginStream(ID_RIGHTTORENDER,
(StreamRead)readAtomicRights,
NULL, NULL);
}
//
// Light
//
Light::Light(void)
{

View File

@ -269,7 +269,9 @@ Geometry::addMorphTargets(int32 n)
}
//
// Material
//
Material::Material(void)
{
@ -383,7 +385,29 @@ Material::streamGetSize(void)
return size;
}
// Material Rights plugin
static void
readMaterialRights(Stream *stream, int32, void *, int32, int32)
{
uint32 buffer[2];
stream->read(buffer, 8);
printf("materialrights: %X %X\n", buffer[0], buffer[1]);
}
void
RegisterMaterialRightsPlugin(void)
{
Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
Material::registerPluginStream(ID_RIGHTTORENDER,
(StreamRead)readMaterialRights,
NULL, NULL);
}
//
// Texture
//
Texture::Texture(void)
{

View File

@ -229,12 +229,12 @@ destroySkin(void *object, int32 offset, int32)
static void*
copySkin(void *dst, void *src, int32 offset, int32)
{
Geometry *geometry = (Geometry*)src;
assert(geometry->instData == NULL);
assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices);
Skin *srcskin = *PLUGINOFFSET(Skin*, src, offset);
if(srcskin == NULL)
return dst;
Geometry *geometry = (Geometry*)src;
assert(geometry->instData == NULL);
assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices);
Skin *dstskin = new Skin;
*PLUGINOFFSET(Skin*, dst, offset) = dstskin;
dstskin->numBones = srcskin->numBones;
@ -413,9 +413,330 @@ RegisterSkinPlugin(void)
Geometry::registerPlugin(sizeof(Skin*), ID_SKIN,
createSkin, destroySkin, copySkin);
Geometry::registerPluginStream(ID_SKIN,
(StreamRead)readSkin,
(StreamWrite)writeSkin,
(StreamGetSize)getSizeSkin);
readSkin, writeSkin, getSizeSkin);
}
// Atomic MatFX
static void*
createAtomicMatFX(void *object, int32 offset, int32)
{
*PLUGINOFFSET(int32, object, offset) = 0;
return object;
}
static void*
copyAtomicMatFX(void *dst, void *src, int32 offset, int32)
{
*PLUGINOFFSET(int32, dst, offset) = *PLUGINOFFSET(int32, src, offset);
return dst;
}
static void
readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
{
int32 flag;
// uint32 version;
//stream->seek(-4);
//version = stream->readU32();
stream->read(&flag, 4);
//printf("atomicMatFX: %X %X\n", LibraryIDUnpackVersion(version), flag);
*PLUGINOFFSET(int32, object, offset) = flag;
// TODO: set Pipeline
}
static void
writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
{
int32 flag;
flag = *PLUGINOFFSET(int32, object, offset);
stream->writeI32(flag);
}
static int32
getSizeAtomicMatFX(void *object, int32 offset, int32)
{
int32 flag;
flag = *PLUGINOFFSET(int32, object, offset);
return flag ? 4 : -1;
}
// Material MatFX
// TODO: Frames and Matrices?
static void
clearMatFX(MatFX *matfx)
{
for(int i = 0; i < 2; i++)
switch(matfx->fx[i].type){
case MatFX::BUMPMAP:
if(matfx->fx[i].bump.bumpedTex)
matfx->fx[i].bump.bumpedTex->decRef();
if(matfx->fx[i].bump.tex)
matfx->fx[i].bump.tex->decRef();
break;
case MatFX::ENVMAP:
if(matfx->fx[i].env.tex)
matfx->fx[i].env.tex->decRef();
break;
case MatFX::DUAL:
if(matfx->fx[i].dual.tex)
matfx->fx[i].dual.tex->decRef();
break;
}
memset(matfx, 0, sizeof(MatFX));
}
void
MatFX::setEffects(uint32 flags)
{
if(this->flags != 0 && this->flags != flags)
clearMatFX(this);
this->flags = flags;
switch(flags){
case BUMPMAP:
case ENVMAP:
case DUAL:
case UVTRANSFORM:
this->fx[0].type = flags;
this->fx[1].type = NOTHING;
break;
case BUMPENVMAP:
this->fx[0].type = BUMPMAP;
this->fx[1].type = ENVMAP;
break;
case DUALUVTRANSFORM:
this->fx[0].type = UVTRANSFORM;
this->fx[1].type = DUAL;
break;
}
}
int32
MatFX::getEffectIndex(uint32 type)
{
for(int i = 0; i < 2; i++)
if(this->fx[i].type == type)
return i;
return -1;
}
static void*
createMaterialMatFX(void *object, int32 offset, int32)
{
*PLUGINOFFSET(MatFX*, object, offset) = NULL;
return object;
}
static void*
destroyMaterialMatFX(void *object, int32 offset, int32)
{
MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
if(matfx){
clearMatFX(matfx);
delete matfx;
}
return object;
}
static void*
copyMaterialMatFX(void *dst, void *src, int32 offset, int32)
{
MatFX *srcfx = *PLUGINOFFSET(MatFX*, src, offset);
if(srcfx == NULL)
return dst;
MatFX *dstfx = new MatFX;
*PLUGINOFFSET(MatFX*, dst, offset) = dstfx;
memcpy(dstfx, srcfx, sizeof(MatFX));
for(int i = 0; i < 2; i++)
switch(dstfx->fx[i].type){
case MatFX::BUMPMAP:
if(dstfx->fx[i].bump.bumpedTex)
dstfx->fx[i].bump.bumpedTex->refCount++;
if(dstfx->fx[i].bump.tex)
dstfx->fx[i].bump.tex->refCount++;
break;
case MatFX::ENVMAP:
if(dstfx->fx[i].env.tex)
dstfx->fx[i].env.tex->refCount++;
break;
case MatFX::DUAL:
if(dstfx->fx[i].dual.tex)
dstfx->fx[i].dual.tex->refCount++;
break;
}
return dst;
}
static void
readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
{
Texture *tex, *bumpedTex;
float coefficient;
int32 fbAlpha;
int32 srcBlend, dstBlend;
int32 idx;
MatFX *matfx = new MatFX;
memset(matfx, 0, sizeof(MatFX));
*PLUGINOFFSET(MatFX*, object, offset) = matfx;
matfx->setEffects(stream->readU32());
for(int i = 0; i < 2; i++){
uint32 type = stream->readU32();
switch(type){
case MatFX::BUMPMAP:
coefficient = stream->readF32();
bumpedTex = tex = NULL;
if(stream->readI32()){
assert(FindChunk(stream, ID_TEXTURE,
NULL, NULL));
bumpedTex = Texture::streamRead(stream);
}
if(stream->readI32()){
assert(FindChunk(stream, ID_TEXTURE,
NULL, NULL));
tex = Texture::streamRead(stream);
}
idx = matfx->getEffectIndex(type);
assert(idx >= 0);
matfx->fx[idx].bump.bumpedTex = bumpedTex;
matfx->fx[idx].bump.tex = tex;
matfx->fx[idx].bump.coefficient = coefficient;
break;
case MatFX::ENVMAP:
coefficient = stream->readF32();
fbAlpha = stream->readI32();
tex = NULL;
if(stream->readI32()){
assert(FindChunk(stream, ID_TEXTURE,
NULL, NULL));
tex = Texture::streamRead(stream);
}
idx = matfx->getEffectIndex(type);
assert(idx >= 0);
matfx->fx[idx].env.tex = tex;
matfx->fx[idx].env.fbAlpha = fbAlpha;
matfx->fx[idx].env.coefficient = coefficient;
break;
case MatFX::DUAL:
srcBlend = stream->readI32();
dstBlend = stream->readI32();
tex = NULL;
if(stream->readI32()){
assert(FindChunk(stream, ID_TEXTURE,
NULL, NULL));
tex = Texture::streamRead(stream);
}
idx = matfx->getEffectIndex(type);
assert(idx >= 0);
matfx->fx[idx].dual.tex = tex;
matfx->fx[idx].dual.srcBlend = srcBlend;
matfx->fx[idx].dual.dstBlend = dstBlend;
break;
}
}
}
static void
writeMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
{
MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
stream->writeU32(matfx->flags);
for(int i = 0; i < 2; i++){
stream->writeU32(matfx->fx[i].type);
switch(matfx->fx[i].type){
case MatFX::BUMPMAP:
stream->writeF32(matfx->fx[i].bump.coefficient);
stream->writeI32(matfx->fx[i].bump.bumpedTex != NULL);
if(matfx->fx[i].bump.bumpedTex)
matfx->fx[i].bump.bumpedTex->streamWrite(stream);
stream->writeI32(matfx->fx[i].bump.tex != NULL);
if(matfx->fx[i].bump.tex)
matfx->fx[i].bump.tex->streamWrite(stream);
break;
case MatFX::ENVMAP:
stream->writeF32(matfx->fx[i].env.coefficient);
stream->writeI32(matfx->fx[i].env.fbAlpha);
stream->writeI32(matfx->fx[i].env.tex != NULL);
if(matfx->fx[i].env.tex)
matfx->fx[i].env.tex->streamWrite(stream);
break;
case MatFX::DUAL:
stream->writeI32(matfx->fx[i].dual.srcBlend);
stream->writeI32(matfx->fx[i].dual.dstBlend);
stream->writeI32(matfx->fx[i].dual.tex != NULL);
if(matfx->fx[i].dual.tex)
matfx->fx[i].dual.tex->streamWrite(stream);
break;
}
}
}
static int32
getSizeMaterialMatFX(void *object, int32 offset, int32)
{
MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
if(matfx == NULL)
return -1;
int32 size = 4 + 4 + 4;
for(int i = 0; i < 2; i++)
switch(matfx->fx[i].type){
case MatFX::BUMPMAP:
size += 4 + 4 + 4;
if(matfx->fx[i].bump.bumpedTex)
size += 12 +
matfx->fx[i].bump.bumpedTex->streamGetSize();
if(matfx->fx[i].bump.tex)
size += 12 +
matfx->fx[i].bump.tex->streamGetSize();
break;
case MatFX::ENVMAP:
size += 4 + 4 + 4;
if(matfx->fx[i].env.tex)
size += 12 +
matfx->fx[i].env.tex->streamGetSize();
break;
case MatFX::DUAL:
size += 4 + 4 + 4;
if(matfx->fx[i].dual.tex)
size += 12 +
matfx->fx[i].dual.tex->streamGetSize();
break;
}
return size;
}
void
RegisterMatFXPlugin(void)
{
Atomic::registerPlugin(sizeof(int32), ID_MATFX,
createAtomicMatFX, NULL, copyAtomicMatFX);
Atomic::registerPluginStream(ID_MATFX,
readAtomicMatFX,
writeAtomicMatFX,
getSizeAtomicMatFX);
Material::registerPlugin(sizeof(MatFX*), ID_MATFX,
createMaterialMatFX, destroyMaterialMatFX,
copyMaterialMatFX);
Material::registerPluginStream(ID_MATFX,
readMaterialMatFX,
writeMaterialMatFX,
getSizeMaterialMatFX);
}
}

View File

@ -14,6 +14,7 @@ namespace Rw {
int Version = 0x36003;
int Build = 0xFFFF;
char *DebugFile = NULL;
int32
Stream::writeI8(int8 val)

View File

@ -110,12 +110,16 @@ enum PluginID
ID_UVANIMDICT = 0x2B,
ID_SKIN = 0x116,
ID_MATFX = 0x120,
ID_PDS = 0x131,
ID_ADC = 0x134,
ID_MESH = 0x50E,
ID_NATIVEDATA = 0x510,
};
extern int Version;
extern int Build;
extern char *DebugFile;
inline uint32
LibraryIDPack(int version, int build)

View File

@ -1,5 +1,12 @@
namespace Rw {
// TODO: mostly
struct Pipeline
{
uint32 pluginID;
uint32 pluginData;
};
struct Object
{
uint8 type;
@ -8,6 +15,28 @@ struct Object
void *parent;
};
struct Frame : PluginBase<Frame>, Object
{
typedef Frame *(*Callback)(Frame *f, void *data);
float32 matrix[16];
float32 ltm[16];
Frame *child;
Frame *next;
Frame *root;
// temporary
int32 matflag;
Frame(void);
Frame(Frame *f);
~Frame(void);
Frame *addChild(Frame *f);
Frame *removeChild(void);
Frame *forAllChildren(Callback cb, void *data);
int32 count(void);
};
struct Image
{
int32 flags;
@ -74,6 +103,56 @@ struct Material : PluginBase<Material>
uint32 streamGetSize(void);
};
struct MatFX
{
enum Flags {
NOTHING = 0,
BUMPMAP,
ENVMAP,
BUMPENVMAP,
DUAL,
UVTRANSFORM,
DUALUVTRANSFORM
};
struct Bump {
Frame *frame;
Texture *bumpedTex;
Texture *tex;
float coefficient;
};
struct Env {
Frame *frame;
Texture *tex;
float coefficient;
int32 fbAlpha;
};
struct Dual {
Texture *tex;
int32 srcBlend;
int32 dstBlend;
};
struct UVtransform {
float *baseTransform;
float *dualTransform;
};
struct {
uint32 type;
union {
Bump bump;
Env env;
Dual dual;
UVtransform uvtransform;
};
} fx[2];
uint32 flags;
void setEffects(uint32 flags);
int32 getEffectIndex(uint32 type);
};
void RegisterMaterialRightsPlugin(void);
void RegisterMatFXPlugin(void);
struct Mesh
{
uint16 *indices;
@ -160,27 +239,9 @@ struct Skin
uint8 *data; // only used by delete
};
struct Frame : PluginBase<Frame>, Object
{
typedef Frame *(*Callback)(Frame *f, void *data);
float32 matrix[16];
float32 ltm[16];
Frame *child;
Frame *next;
Frame *root;
// temporary
int32 matflag;
Frame(void);
Frame(Frame *f);
~Frame(void);
Frame *addChild(Frame *f);
Frame *removeChild(void);
Frame *forAllChildren(Callback cb, void *data);
int32 count(void);
};
void RegisterMeshPlugin(void);
void RegisterNativeDataPlugin(void);
void RegisterSkinPlugin(void);
struct Clump;
@ -216,6 +277,8 @@ struct Atomic : PluginBase<Atomic>, Object
uint32 streamGetSize(void);
};
void RegisterAtomicRightsPlugin(void);
struct Clump : PluginBase<Clump>, Object
{
int32 numAtomics;
@ -237,8 +300,4 @@ private:
void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);
};
void RegisterMeshPlugin(void);
void RegisterNativeDataPlugin(void);
void RegisterSkinPlugin(void);
}

View File

@ -105,7 +105,8 @@ PluginBase<T>::streamWritePlugins(Stream *stream)
int size = this->streamGetPluginSize();
Rw::WriteChunkHeader(stream, Rw::ID_EXTENSION, size);
for(Plugin *p = this->s_plugins; p; p = p->next){
if((size = p->getSize(this, p->offset, p->size)) < 0)
if(p->getSize == NULL ||
(size = p->getSize(this, p->offset, p->size)) < 0)
continue;
Rw::WriteChunkHeader(stream, p->id, size);
p->write(stream, size, this, p->offset, p->size);