librw/src/rwobjects.h

671 lines
14 KiB
C
Raw Normal View History

2016-01-26 12:53:08 +00:00
#include <stddef.h>
namespace rw {
2014-12-23 14:59:14 +00:00
2016-01-11 10:23:26 +00:00
struct LLLink
{
LLLink *next;
LLLink *prev;
void init(void){
this->next = NULL;
this->prev = NULL;
}
void remove(void){
this->prev->next = this->next;
this->next->prev = this->prev;
}
};
#define LLLinkGetData(linkvar,type,entry) \
((type*)(((uint8*)(linkvar))-offsetof(type,entry)))
2016-01-14 22:49:00 +00:00
// Have to be careful since the link might be deleted.
#define FORLIST(_link, _list) \
2016-02-06 17:11:31 +00:00
for(rw::LLLink *_next = NULL, *_link = (_list).link.next; \
2016-01-14 22:49:00 +00:00
_next = (_link)->next, (_link) != (_list).end(); \
(_link) = _next)
2016-01-11 10:23:26 +00:00
struct LinkList
{
LLLink link;
void init(void){
this->link.next = &this->link;
this->link.prev = &this->link;
}
bool32 isEmpty(void){
return this->link.next == &this->link;
}
void add(LLLink *link){
link->next = this->link.next;
link->prev = &this->link;
this->link.next->prev = link;
this->link.next = link;
}
void append(LLLink *link){
link->next = &this->link;
link->prev = this->link.prev;
this->link.prev->next = link;
this->link.prev = link;
}
2016-01-11 10:23:26 +00:00
LLLink *end(void){
return &this->link;
}
2016-01-14 22:49:00 +00:00
int32 count(void){
int32 n = 0;
FORLIST(lnk, (*this))
n++;
return n;
}
2016-01-11 10:23:26 +00:00
};
2014-12-23 14:59:14 +00:00
struct Object
{
uint8 type;
uint8 subType;
uint8 flags;
2016-01-11 10:23:26 +00:00
uint8 privateFlags;
2014-12-23 14:59:14 +00:00
void *parent;
2016-01-11 10:23:26 +00:00
void init(uint8 type, uint8 subType){
this->type = type;
this->subType = subType;
this->flags = 0;
this->privateFlags = 0;
this->parent = NULL;
}
void copy(Object *o){
this->type = o->type;
this->subType = o->subType;
this->flags = o->flags;
this->privateFlags = o->privateFlags;
this->parent = NULL;
}
2014-12-23 14:59:14 +00:00
};
2016-01-11 10:23:26 +00:00
struct Frame : PluginBase<Frame>
2015-01-09 19:17:32 +00:00
{
typedef Frame *(*Callback)(Frame *f, void *data);
2016-01-13 07:58:15 +00:00
enum { ID = 0 };
enum { // private flags
HIERARCHYSYNCLTM = 0x01,
HIERARCHYSYNCOBJ = 0x02,
HIERARCHYSYNC = HIERARCHYSYNCLTM | HIERARCHYSYNCOBJ,
SUBTREESYNCLTM = 0x04,
SUBTREESYNCOBJ = 0x08,
SUBTREESYNC = SUBTREESYNCLTM | SUBTREESYNCOBJ,
SYNCLTM = HIERARCHYSYNCLTM | SUBTREESYNCLTM,
SYNCOBJ = HIERARCHYSYNCOBJ | SUBTREESYNCOBJ,
};
2016-01-11 10:23:26 +00:00
Object object;
LLLink inDirtyList;
2016-01-11 10:23:26 +00:00
LinkList objectList;
2016-02-14 19:56:05 +00:00
Matrix matrix;
Matrix ltm;
2015-01-09 19:17:32 +00:00
Frame *child;
Frame *next;
Frame *root;
static LinkList dirtyList;
2015-01-09 19:17:32 +00:00
static Frame *create(void);
Frame *cloneHierarchy(void);
void destroy(void);
void destroyHierarchy(void);
2016-01-24 00:42:51 +00:00
Frame *addChild(Frame *f, bool32 append = 0);
2015-01-09 19:17:32 +00:00
Frame *removeChild(void);
Frame *forAllChildren(Callback cb, void *data);
Frame *getParent(void){
2016-01-13 07:58:15 +00:00
return (Frame*)this->object.parent; }
2015-01-09 19:17:32 +00:00
int32 count(void);
2016-02-18 13:56:10 +00:00
bool32 dirty(void) {
return !!(this->root->object.privateFlags & HIERARCHYSYNC); }
2016-02-14 19:56:05 +00:00
Matrix *getLTM(void);
void updateObjects(void);
void syncHierarchyLTM(void);
void setHierarchyRoot(Frame *root);
Frame *cloneAndLink(Frame *clonedroot);
void purgeClone(void);
2015-01-09 19:17:32 +00:00
};
2015-12-18 00:10:42 +00:00
Frame **makeFrameList(Frame *frame, Frame **flist);
2016-06-16 13:08:09 +01:00
struct ObjectWithFrame
2016-01-11 10:23:26 +00:00
{
2016-06-16 13:08:09 +01:00
Object object;
2016-01-11 10:23:26 +00:00
LLLink inFrame;
void setFrame(Frame *f){
2016-06-16 13:08:09 +01:00
if(this->object.parent)
2016-01-11 10:23:26 +00:00
this->inFrame.remove();
2016-06-16 13:08:09 +01:00
this->object.parent = f;
2016-01-11 10:23:26 +00:00
if(f)
f->objectList.add(&this->inFrame);
}
2016-01-13 07:58:15 +00:00
static ObjectWithFrame *fromFrame(LLLink *lnk){
return LLLinkGetData(lnk, ObjectWithFrame, inFrame);
}
2016-01-11 10:23:26 +00:00
};
2014-12-25 15:02:57 +00:00
struct Image
{
int32 flags;
int32 width, height;
int32 depth;
int32 stride;
uint8 *pixels;
uint8 *palette;
static Image *create(int32 width, int32 height, int32 depth);
void destroy(void);
2014-12-25 15:02:57 +00:00
void allocate(void);
void free(void);
void setPixels(uint8 *pixels);
void setPalette(uint8 *palette);
bool32 hasAlpha(void);
static void setSearchPath(const char*);
static void printSearchPath(void);
static char *getFilename(const char*);
2014-12-25 15:02:57 +00:00
};
2014-12-25 18:37:36 +00:00
Image *readTGA(const char *filename);
void writeTGA(Image *image, const char *filename);
2014-12-25 15:02:57 +00:00
// used to emulate d3d and xbox textures
struct RasterLevels
{
int32 numlevels;
uint32 format;
struct Level {
int32 width, height, size;
uint8 *data;
} levels[1]; // 0 is illegal :/
};
struct Raster : PluginBase<Raster>
{
int32 platform;
int32 type; // hardly used
int32 flags;
int32 format;
int32 width, height, depth;
int32 stride;
uint8 *texels;
uint8 *palette;
static Raster *create(int32 width, int32 height, int32 depth, int32 format, int32 platform = 0);
void destroy(void);
static Raster *createFromImage(Image *image);
uint8 *lock(int32 level);
void unlock(int32 level);
int32 getNumLevels(void);
static int32 calculateNumLevels(int32 width, int32 height);
enum Format {
DEFAULT = 0,
C1555 = 0x0100,
C565 = 0x0200,
C4444 = 0x0300,
LUM8 = 0x0400,
C8888 = 0x0500,
C888 = 0x0600,
D16 = 0x0700,
D24 = 0x0800,
D32 = 0x0900,
C555 = 0x0A00,
AUTOMIPMAP = 0x1000,
PAL8 = 0x2000,
PAL4 = 0x4000,
MIPMAP = 0x8000
};
};
2016-02-06 17:11:31 +00:00
extern bool32 loadTextures;
#define IGNORERASTERIMP 0
2015-12-14 17:52:50 +00:00
struct TexDictionary;
2014-12-23 14:59:14 +00:00
struct Texture : PluginBase<Texture>
{
2016-01-11 10:23:26 +00:00
Raster *raster;
TexDictionary *dict;
LLLink inDict;
2014-12-23 14:59:14 +00:00
char name[32];
char mask[32];
uint32 filterAddressing; // VVVVUUUU FFFFFFFF
2014-12-23 14:59:14 +00:00
int32 refCount;
static Texture *create(Raster *raster);
void destroy(void);
static Texture *fromDict(LLLink *lnk){
2016-01-13 07:58:15 +00:00
return LLLinkGetData(lnk, Texture, inDict); }
static Texture *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
2015-01-20 18:22:57 +00:00
static Texture *read(const char *name, const char *mask);
static Texture *streamReadNative(Stream *stream);
void streamWriteNative(Stream *stream);
uint32 streamGetSizeNative(void);
2014-12-23 14:59:14 +00:00
static Texture *(*findCB)(const char *name);
static Texture *(*readCB)(const char *name, const char *mask);
2014-12-23 14:59:14 +00:00
enum FilterMode {
NEAREST = 1,
LINEAR,
MIPNEAREST,
MIPLINEAR,
LINEARMIPNEAREST,
LINEARMIPLINEAR
};
enum Addressing {
WRAP = 1,
MIRROR,
CLAMP,
BORDER
};
};
2016-06-16 13:08:09 +01:00
2016-01-09 21:01:21 +00:00
struct SurfaceProperties
{
float32 ambient;
float32 specular;
float32 diffuse;
};
2014-12-23 14:59:14 +00:00
struct Material : PluginBase<Material>
{
Texture *texture;
2016-01-13 07:58:15 +00:00
RGBA color;
2016-01-09 21:01:21 +00:00
SurfaceProperties surfaceProps;
2015-01-10 21:13:27 +00:00
Pipeline *pipeline;
2014-12-23 14:59:14 +00:00
int32 refCount;
static Material *create(void);
Material *clone(void);
void destroy(void);
static Material *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
};
void registerMaterialRightsPlugin(void);
2015-01-10 21:13:27 +00:00
2014-12-23 14:59:14 +00:00
struct Mesh
{
uint16 *indices;
uint32 numIndices;
Material *material;
};
struct MeshHeader
{
2016-01-24 00:42:51 +00:00
enum {
TRISTRIP = 1
};
2014-12-23 14:59:14 +00:00
uint32 flags;
uint16 numMeshes;
// RW has uint16 serialNum here
uint32 totalIndices;
Mesh *mesh; // RW has a byte offset here
2015-09-07 22:00:28 +01:00
void allocateIndices(void);
2015-12-20 12:05:32 +00:00
~MeshHeader(void);
2014-12-23 14:59:14 +00:00
};
struct MorphTarget
{
Sphere boundingSphere;
2014-12-23 14:59:14 +00:00
float32 *vertices;
float32 *normals;
};
struct InstanceDataHeader
{
uint32 platform;
};
2016-01-24 00:42:51 +00:00
struct Triangle
{
uint16 v[3];
uint16 matId;
};
2016-01-11 10:23:26 +00:00
struct Geometry : PluginBase<Geometry>
2014-12-23 14:59:14 +00:00
{
2016-01-13 07:58:15 +00:00
enum { ID = 8 };
2016-01-11 10:23:26 +00:00
Object object;
uint32 geoflags; // TODO: rename
2014-12-23 14:59:14 +00:00
int32 numTriangles;
int32 numVertices;
int32 numMorphTargets;
int32 numTexCoordSets;
2016-01-24 00:42:51 +00:00
Triangle *triangles;
2014-12-23 14:59:14 +00:00
uint8 *colors;
float32 *texCoords[8];
MorphTarget *morphTargets;
2016-01-11 10:23:26 +00:00
// TODO: struct
2014-12-23 14:59:14 +00:00
int32 numMaterials;
Material **materialList;
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);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
void addMorphTargets(int32 n);
2015-12-19 16:05:39 +00:00
void calculateBoundingSphere(void);
bool32 hasColoredMaterial(void);
2015-08-11 19:57:43 +01:00
void allocateData(void);
void generateTriangles(int8 *adc = NULL);
2016-01-24 00:42:51 +00:00
void buildMeshes(void);
void removeUnusedMaterials(void);
2014-12-23 14:59:14 +00:00
enum Flags
{
TRISTRIP = 0x01,
POSITIONS = 0x02,
TEXTURED = 0x04,
PRELIT = 0x08,
NORMALS = 0x10,
LIGHT = 0x20,
MODULATE = 0x40,
TEXTURED2 = 0x80,
NATIVE = 0x01000000,
NATIVEINSTANCE = 0x02000000
};
};
void registerMeshPlugin(void);
void registerNativeDataPlugin(void);
2015-01-10 21:13:27 +00:00
2014-12-23 14:59:14 +00:00
struct Clump;
2016-01-13 07:58:15 +00:00
struct Atomic : PluginBase<Atomic>
{
typedef void (*RenderCB)(Atomic *atomic);
2016-01-13 07:58:15 +00:00
enum { ID = 1 };
2016-02-14 19:56:05 +00:00
enum {
COLLISIONTEST = 0x01, // unused here
2016-02-18 13:56:10 +00:00
RENDER = 0x04,
// private
WORLDBOUNDDIRTY = 0x01
2016-02-14 19:56:05 +00:00
};
2016-01-13 07:58:15 +00:00
ObjectWithFrame object;
Geometry *geometry;
2016-02-18 13:56:10 +00:00
Sphere worldBoundingSphere;
2016-01-13 07:58:15 +00:00
Clump *clump;
LLLink inClump;
ObjPipeline *pipeline;
RenderCB renderCB;
2016-01-13 07:58:15 +00:00
static Atomic *create(void);
Atomic *clone(void);
void destroy(void);
2016-02-18 13:56:10 +00:00
void setFrame(Frame *f) {
this->object.setFrame(f);
2016-06-16 13:08:09 +01:00
this->object.object.privateFlags |= WORLDBOUNDDIRTY;
2016-02-18 13:56:10 +00:00
}
2016-06-16 13:08:09 +01:00
Frame *getFrame(void) { return (Frame*)this->object.object.parent; }
2016-01-13 07:58:15 +00:00
static Atomic *fromClump(LLLink *lnk){
return LLLinkGetData(lnk, Atomic, inClump); }
2016-06-14 22:07:16 +01:00
void removeFromClump(void);
2016-02-18 13:56:10 +00:00
Sphere *getWorldBoundingSphere(void);
2016-06-14 22:07:16 +01:00
ObjPipeline *getPipeline(void);
void render(void) { this->renderCB(this); }
2016-01-13 07:58:15 +00:00
static Atomic *streamReadClump(Stream *stream,
2016-02-18 13:56:10 +00:00
Frame **frameList, Geometry **geometryList);
2016-01-13 07:58:15 +00:00
bool streamWriteClump(Stream *stream,
Frame **frameList, int32 numframes);
uint32 streamGetSize(void);
static void defaultRenderCB(Atomic *atomic);
2016-01-13 07:58:15 +00:00
};
void registerAtomicRightsPlugin(void);
2016-01-11 10:23:26 +00:00
struct Light : PluginBase<Light>
2014-12-23 14:59:14 +00:00
{
2016-01-13 07:58:15 +00:00
enum { ID = 3 };
2016-01-11 10:23:26 +00:00
ObjectWithFrame object;
2014-12-23 14:59:14 +00:00
float32 radius;
2016-01-14 22:49:00 +00:00
RGBAf color;
2014-12-23 14:59:14 +00:00
float32 minusCosAngle;
2016-01-11 10:23:26 +00:00
// clump link handled by plugin in RW
2014-12-23 14:59:14 +00:00
Clump *clump;
LLLink inClump;
2014-12-23 14:59:14 +00:00
static Light *create(int32 type);
void destroy(void);
2016-01-11 10:23:26 +00:00
void setFrame(Frame *f) { this->object.setFrame(f); }
2016-06-16 13:08:09 +01:00
Frame *getFrame(void){ return (Frame*)this->object.object.parent; }
static Light *fromClump(LLLink *lnk){
2016-01-13 07:58:15 +00:00
return LLLinkGetData(lnk, Light, inClump); }
void setAngle(float32 angle);
float32 getAngle(void);
void setColor(float32 r, float32 g, float32 b);
2016-06-16 13:08:09 +01:00
int32 getType(void){ return this->object.object.subType; }
static Light *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
2016-01-13 07:58:15 +00:00
enum Type {
DIRECTIONAL = 1,
AMBIENT,
POINT = 0x80, // positioned
SPOT,
SOFTSPOT,
};
enum Flags {
LIGHTATOMICS = 1,
LIGHTWORLD = 2
};
2014-12-23 14:59:14 +00:00
};
2016-01-13 07:58:15 +00:00
struct Camera : PluginBase<Camera>
2014-12-23 14:59:14 +00:00
{
2016-01-13 07:58:15 +00:00
enum { ID = 4 };
2016-02-14 19:56:05 +00:00
enum { PERSPECTIVE = 1, PARALLEL };
2016-01-11 10:23:26 +00:00
ObjectWithFrame object;
2016-01-13 07:58:15 +00:00
V2d viewWindow;
V2d viewOffset;
2016-01-14 22:49:00 +00:00
float32 nearPlane, farPlane;
2016-01-13 07:58:15 +00:00
float32 fogPlane;
int32 projection;
2016-02-14 19:56:05 +00:00
float32 projMat[16];
2016-01-13 07:58:15 +00:00
2014-12-23 14:59:14 +00:00
Clump *clump;
LLLink inClump;
2014-12-23 14:59:14 +00:00
2016-01-13 07:58:15 +00:00
static Camera *create(void);
Camera *clone(void);
void destroy(void);
2016-01-11 10:23:26 +00:00
void setFrame(Frame *f) { this->object.setFrame(f); }
2016-06-16 13:08:09 +01:00
Frame *getFrame(void){ return (Frame*)this->object.object.parent; }
2016-01-13 07:58:15 +00:00
static Camera *fromClump(LLLink *lnk){
return LLLinkGetData(lnk, Camera, inClump); }
static Camera *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
2016-02-14 19:56:05 +00:00
void updateProjectionMatrix(void);
// fov in degrees
void setFOV(float32 fov, float32 ratio);
2014-12-23 14:59:14 +00:00
};
2016-01-11 10:23:26 +00:00
struct Clump : PluginBase<Clump>
2014-12-23 14:59:14 +00:00
{
2016-01-13 07:58:15 +00:00
enum { ID = 2 };
2016-01-14 22:49:00 +00:00
Object object;
LinkList atomics;
LinkList lights;
2016-01-13 07:58:15 +00:00
LinkList cameras;
2014-12-23 14:59:14 +00:00
static Clump *create(void);
Clump *clone(void);
void destroy(void);
2016-01-14 22:49:00 +00:00
int32 countAtomics(void) { return this->atomics.count(); }
void addAtomic(Atomic *a){
a->clump = this;
this->atomics.append(&a->inClump);
}
2016-01-14 22:49:00 +00:00
int32 countLights(void) { return this->lights.count(); }
void addLight(Light *l){
l->clump = this;
this->lights.append(&l->inClump);
}
2016-01-14 22:49:00 +00:00
int32 countCameras(void) { return this->cameras.count(); }
2016-01-13 07:58:15 +00:00
void addCamera(Camera *c){
c->clump = this;
this->cameras.append(&c->inClump);
}
2016-01-13 07:58:15 +00:00
void setFrame(Frame *f){
this->object.parent = f; }
Frame *getFrame(void){
2016-01-13 07:58:15 +00:00
return (Frame*)this->object.parent; }
static Clump *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
2014-12-23 14:59:14 +00:00
uint32 streamGetSize(void);
2016-02-14 19:56:05 +00:00
void render(void);
2014-12-23 14:59:14 +00:00
void frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf);
void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);
2014-12-23 14:59:14 +00:00
};
2015-09-17 09:44:07 +01:00
struct TexDictionary : PluginBase<TexDictionary>
2015-01-20 18:22:57 +00:00
{
2016-01-13 07:58:15 +00:00
enum { ID = 6 };
2016-01-11 10:23:26 +00:00
Object object;
LinkList textures;
2015-01-20 18:22:57 +00:00
static TexDictionary *create(void);
void destroy(void);
2016-01-14 22:49:00 +00:00
int32 count(void) { return this->textures.count(); }
void add(Texture *t){
t->dict = this;
this->textures.append(&t->inDict);
}
2015-01-20 18:22:57 +00:00
Texture *find(const char *name);
static TexDictionary *streamRead(Stream *stream);
void streamWrite(Stream *stream);
uint32 streamGetSize(void);
2015-01-20 18:22:57 +00:00
};
2016-01-13 07:58:15 +00:00
extern TexDictionary *currentTexDictionary;
struct Animation;
struct AnimInterpolatorInfo
{
int32 id;
int32 keyFrameSize;
int32 customDataSize;
void (*streamRead)(Stream *stream, Animation *anim);
void (*streamWrite)(Stream *stream, Animation *anim);
uint32 (*streamGetSize)(Animation *anim);
};
void registerAnimInterpolatorInfo(AnimInterpolatorInfo *interpInfo);
AnimInterpolatorInfo *findAnimInterpolatorInfo(int32 id);
struct Animation
{
AnimInterpolatorInfo *interpInfo;
int32 numFrames;
int32 flags;
float duration;
void *keyframes;
void *customData;
2016-01-14 22:49:00 +00:00
static Animation *create(AnimInterpolatorInfo*, int32 numFrames, int32 flags, float duration);
void destroy(void);
static Animation *streamRead(Stream *stream);
static Animation *streamReadLegacy(Stream *stream);
bool streamWrite(Stream *stream);
bool streamWriteLegacy(Stream *stream);
uint32 streamGetSize(void);
};
struct AnimInterpolator
{
// only a stub right now
Animation *anim;
AnimInterpolator(Animation *anim);
};
struct UVAnimKeyFrame
{
UVAnimKeyFrame *prev;
float time;
float uv[6];
};
2016-01-14 22:49:00 +00:00
struct UVAnimDictionary;
// RW does it differently...maybe we should implement RtDict
// and make it more general?
struct UVAnimCustomData
{
char name[32];
int32 nodeToUVChannel[8];
2016-01-14 22:49:00 +00:00
int32 refCount;
void destroy(Animation *anim);
};
// This should be more general probably
struct UVAnimDictEntry
{
Animation *anim;
LLLink inDict;
static UVAnimDictEntry *fromDict(LLLink *lnk){
return LLLinkGetData(lnk, UVAnimDictEntry, inDict); }
};
2016-01-14 22:49:00 +00:00
// This too
struct UVAnimDictionary
{
2016-01-14 22:49:00 +00:00
LinkList animations;
static UVAnimDictionary *create(void);
void destroy(void);
int32 count(void) { return this->animations.count(); }
void add(Animation *anim);
Animation *find(const char *name);
static UVAnimDictionary *streamRead(Stream *stream);
bool streamWrite(Stream *stream);
uint32 streamGetSize(void);
};
extern UVAnimDictionary *currentUVAnimDictionary;
2016-01-24 00:42:51 +00:00
struct UVAnim
{
AnimInterpolator *interp[8];
};
extern int32 uvAnimOffset;
void registerUVAnimPlugin(void);
}