summaryrefslogtreecommitdiff
path: root/src/rwobjects.h
diff options
context:
space:
mode:
authorclaude-bot <[email protected]>2026-07-13 12:40:03 +0000
committerclaude-bot <[email protected]>2026-07-13 12:40:03 +0000
commit847962910f0bff071f3bf07c9abb87764fb6cac3 (patch)
treeddcd429e134c7fd5f72ddc97ced175de8d66fcd0 /src/rwobjects.h
downloadlibrw-847962910f0bff071f3bf07c9abb87764fb6cac3.tar.gz
librw-847962910f0bff071f3bf07c9abb87764fb6cac3.zip
Import aap/librw @ masterHEADmaster
Snapshot for re3/reVC vendoring, per @lzcnt. Source: https://github.com/aap/librw (master).
Diffstat (limited to 'src/rwobjects.h')
-rw-r--r--src/rwobjects.h906
1 files changed, 906 insertions, 0 deletions
diff --git a/src/rwobjects.h b/src/rwobjects.h
new file mode 100644
index 0000000..da95a5c
--- /dev/null
+++ b/src/rwobjects.h
@@ -0,0 +1,906 @@
+#include <stddef.h>
+
+namespace rw {
+
+struct Object
+{
+ uint8 type;
+ uint8 subType;
+ uint8 flags;
+ uint8 privateFlags;
+ void *parent;
+
+ void init(uint8 type, uint8 subType){
+ this->type = type;
+ this->subType = subType;
+ this->flags = 0;
+ this->privateFlags = 0;
+ this->parent = nil;
+ }
+ void copy(Object *o){
+ this->type = o->type;
+ this->subType = o->subType;
+ this->flags = o->flags;
+ this->privateFlags = o->privateFlags;
+ this->parent = nil;
+ }
+};
+
+struct Frame
+{
+ PLUGINBASE
+ typedef Frame *(*Callback)(Frame *f, void *data);
+ enum { ID = 0 };
+ enum { // private flags
+ // The hierarchy has unsynched frames
+ HIERARCHYSYNCLTM = 0x01, // LTM not synched
+ HIERARCHYSYNCOBJ = 0x02, // attached objects not synched
+ HIERARCHYSYNC = HIERARCHYSYNCLTM | HIERARCHYSYNCOBJ,
+ // This frame is not synched
+ SUBTREESYNCLTM = 0x04,
+ SUBTREESYNCOBJ = 0x08,
+ SUBTREESYNC = SUBTREESYNCLTM | SUBTREESYNCOBJ,
+ SYNCLTM = HIERARCHYSYNCLTM | SUBTREESYNCLTM,
+ SYNCOBJ = HIERARCHYSYNCOBJ | SUBTREESYNCOBJ
+ // STATIC = 0x10
+ };
+
+ Object object;
+ LLLink inDirtyList;
+ LinkList objectList;
+ Matrix matrix;
+ Matrix ltm;
+
+ Frame *child;
+ Frame *next;
+ Frame *root;
+
+ static int32 numAllocated;
+
+ static Frame *create(void);
+ Frame *cloneHierarchy(void);
+ void destroy(void);
+ void destroyHierarchy(void);
+ Frame *addChild(Frame *f, bool32 append = 0);
+ Frame *removeChild(void);
+ Frame *forAllChildren(Callback cb, void *data);
+ Frame *getParent(void) const {
+ return (Frame*)this->object.parent; }
+ int32 count(void);
+ bool32 dirty(void) const {
+ return !!(this->root->object.privateFlags & HIERARCHYSYNC); }
+ Matrix *getLTM(void);
+ void rotate(const V3d *axis, float32 angle, CombineOp op = rw::COMBINEPOSTCONCAT);
+ void rotate(const Quat *q, CombineOp op = rw::COMBINEPOSTCONCAT);
+ void translate(const V3d *trans, CombineOp op = rw::COMBINEPOSTCONCAT);
+ void scale(const V3d *scale, CombineOp op = rw::COMBINEPOSTCONCAT);
+ void transform(const Matrix *mat, CombineOp op = rw::COMBINEPOSTCONCAT);
+ void updateObjects(void);
+
+
+ void syncHierarchyLTM(void);
+ void setHierarchyRoot(Frame *root);
+ Frame *cloneAndLink(void);
+ void purgeClone(void);
+
+#ifndef RWPUBLIC
+ static void registerModule(void);
+#endif
+ static void syncDirty(void);
+};
+
+struct FrameList_
+{
+ int32 numFrames;
+ Frame **frames;
+
+ FrameList_ *streamRead(Stream *stream);
+ void streamWrite(Stream *stream);
+ static uint32 streamGetSize(Frame *f);
+};
+Frame **makeFrameList(Frame *frame, Frame **flist);
+
+struct ObjectWithFrame
+{
+ typedef void (*Sync)(ObjectWithFrame*);
+
+ Object object;
+ LLLink inFrame;
+ Sync syncCB;
+
+ void setFrame(Frame *f){
+ if(this->object.parent)
+ this->inFrame.remove();
+ this->object.parent = f;
+ if(f){
+ f->objectList.add(&this->inFrame);
+ f->updateObjects();
+ }
+ }
+ void sync(void){ this->syncCB(this); }
+ static ObjectWithFrame *fromFrame(LLLink *lnk){
+ return LLLinkGetData(lnk, ObjectWithFrame, inFrame);
+ }
+};
+
+struct Image
+{
+ int32 flags;
+ int32 width, height;
+ int32 depth;
+ int32 bpp; // bytes per pixel
+ int32 stride;
+ uint8 *pixels;
+ uint8 *palette;
+
+ static int32 numAllocated;
+
+ static Image *create(int32 width, int32 height, int32 depth);
+ void destroy(void);
+ void allocate(void);
+ void free(void);
+ void setPixels(uint8 *pixels);
+ void setPixelsDXT(int32 type, uint8 *pixels);
+ void setPalette(uint8 *palette);
+ void compressPalette(void); // turn 8 bit into 4 bit if possible
+ bool32 hasAlpha(void);
+ void convertTo32(void);
+ void palettize(int32 depth);
+ void unpalettize(bool forceAlpha = false);
+ void makeMask(void);
+ void applyMask(Image *mask);
+ void removeMask(void);
+ Image *extractMask(void);
+
+ static void setSearchPath(const char*);
+ static void printSearchPath(void);
+ static char *getFilename(const char*);
+ static Image *read(const char *imageName);
+ static Image *readMasked(const char *imageName, const char *maskName);
+
+
+ typedef Image *(*fileRead)(const char *afilename);
+ typedef void (*fileWrite)(Image *image, const char *filename);
+ static bool32 registerFileFormat(const char *ext, fileRead read, fileWrite write);
+
+#ifndef RWPUBLIC
+ static void registerModule(void);
+#endif
+};
+
+Image *readTGA(const char *filename);
+void writeTGA(Image *image, const char *filename);
+Image *readBMP(const char *filename);
+void writeBMP(Image *image, const char *filename);
+Image *readPNG(const char *filename);
+void writePNG(Image *image, const char *filename);
+
+enum { QUANTDEPTH = 8 };
+
+struct ColorQuant
+{
+ struct Node {
+ uint32 r, g, b, a;
+ int32 numPixels;
+ Node *parent;
+ Node *children[16];
+ LLLink link;
+
+ void destroy(void);
+ void addColor(RGBA color);
+ bool isLeaf(void) { for(int32 i = 0; i < 16; i++) if(this->children[i]) return false; return true; }
+ };
+
+ Node *root;
+ LinkList leaves;
+
+ void init(void);
+ void destroy(void);
+ Node *createNode(int32 level);
+ Node *getNode(Node *root, uint32 addr, int32 level);
+ Node *findNode(Node *root, uint32 addr, int32 level);
+ void reduceNode(Node *node);
+ void addColor(RGBA color);
+ uint8 findColor(RGBA color);
+ void addImage(Image *img);
+ void makePalette(int32 numColors, RGBA *colors);
+ void matchImage(uint8 *dstPixels, uint32 dstStride, Image *src);
+};
+
+// 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
+{
+ enum { FLIPWAITVSYNCH = 1 };
+
+ PLUGINBASE
+ int32 platform;
+
+ // TODO: use bytes
+ int32 type;
+ int32 flags;
+ int32 privateFlags;
+ int32 format;
+ int32 width, height, depth;
+ int32 stride;
+ uint8 *pixels;
+ uint8 *palette;
+ // remember for locked rasters
+ uint8 *originalPixels;
+ int32 originalWidth;
+ int32 originalHeight;
+ int32 originalStride;
+ // subraster
+ Raster *parent;
+ int32 offsetX, offsetY;
+
+ static int32 numAllocated;
+
+ static Raster *create(int32 width, int32 height, int32 depth,
+ int32 format, int32 platform = 0);
+ void subRaster(Raster *parent, Rect *r);
+ void destroy(void);
+ static bool32 imageFindRasterFormat(Image *image, int32 type,
+ int32 *pWidth, int32 *pHeight, int32 *pDepth, int32 *pFormat, int32 platform = 0);
+ Raster *setFromImage(Image *image, int32 platform = 0);
+ static Raster *createFromImage(Image *image, int32 platform = 0);
+ Image *toImage(void);
+ uint8 *lock(int32 level, int32 lockMode);
+ void unlock(int32 level);
+ uint8 *lockPalette(int32 lockMode);
+ void unlockPalette(void);
+ int32 getNumLevels(void);
+ static int32 calculateNumLevels(int32 width, int32 height);
+ static bool formatHasAlpha(int32 format);
+
+ void show(uint32 flags);
+
+ static Raster *pushContext(Raster *raster);
+ static Raster *popContext(void);
+ static Raster *getCurrentContext(void);
+ bool32 renderFast(int32 x, int32 y);
+
+ static Raster *convertTexToCurrentPlatform(Raster *ras);
+#ifndef RWPUBLIC
+ static void registerModule(void);
+#endif
+
+ 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
+ };
+ enum Type {
+ NORMAL = 0x00,
+ ZBUFFER = 0x01,
+ CAMERA = 0x02,
+ TEXTURE = 0x04,
+ CAMERATEXTURE = 0x05,
+ DONTALLOCATE = 0x80
+ };
+ enum LockMode {
+ LOCKWRITE = 1,
+ LOCKREAD = 2,
+ LOCKNOFETCH = 4, // don't fetch pixel data
+ LOCKRAW = 8,
+ };
+
+ enum
+ {
+ // from RW
+ PRIVATELOCK_READ = 0x02,
+ PRIVATELOCK_WRITE = 0x04,
+ PRIVATELOCK_READ_PALETTE = 0x08,
+ PRIVATELOCK_WRITE_PALETTE = 0x10,
+ };
+};
+
+void conv_RGBA8888_from_RGBA8888(uint8 *out, uint8 *in);
+void conv_BGRA8888_from_RGBA8888(uint8 *out, uint8 *in);
+void conv_RGBA8888_from_RGB888(uint8 *out, uint8 *in);
+void conv_BGRA8888_from_RGB888(uint8 *out, uint8 *in);
+void conv_RGB888_from_RGB888(uint8 *out, uint8 *in);
+void conv_BGR888_from_RGB888(uint8 *out, uint8 *in);
+void conv_ARGB1555_from_ARGB1555(uint8 *out, uint8 *in);
+void conv_ARGB1555_from_RGB555(uint8 *out, uint8 *in);
+void conv_RGBA5551_from_ARGB1555(uint8 *out, uint8 *in);
+void conv_ARGB1555_from_RGBA5551(uint8 *out, uint8 *in);
+void conv_RGBA8888_from_ARGB1555(uint8 *out, uint8 *in);
+void conv_ABGR1555_from_ARGB1555(uint8 *out, uint8 *in);
+inline void conv_8_from_8(uint8 *out, uint8 *in) { *out = *in; }
+// some swaps are the same, so these are just more descriptive names
+inline void conv_RGBA8888_from_BGRA8888(uint8 *out, uint8 *in) { conv_BGRA8888_from_RGBA8888(out, in); }
+inline void conv_RGB888_from_BGR888(uint8 *out, uint8 *in) { conv_BGR888_from_RGB888(out, in); }
+inline void conv_ARGB1555_from_ABGR1555(uint8 *out, uint8 *in) { conv_ABGR1555_from_ARGB1555(out, in); }
+
+void expandPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
+void compressPal4(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
+void expandPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
+void compressPal4_BE(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
+void copyPal8(uint8 *dst, uint32 dststride, uint8 *src, uint32 srcstride, int32 w, int32 h);
+
+void flipDXT(int32 type, uint8 *dst, uint8 *src, uint32 width, uint32 height);
+
+
+#define IGNORERASTERIMP 0
+
+struct TexDictionary;
+
+struct Texture
+{
+ enum FilterMode {
+ NEAREST = 1,
+ LINEAR,
+ MIPNEAREST, // one mipmap
+ MIPLINEAR,
+ LINEARMIPNEAREST, // mipmap interpolated
+ LINEARMIPLINEAR
+ };
+ enum Addressing {
+ WRAP = 1,
+ MIRROR,
+ CLAMP,
+ BORDER
+ };
+
+ PLUGINBASE
+ Raster *raster;
+ TexDictionary *dict;
+ LLLink inDict;
+ char name[32];
+ char mask[32];
+ uint32 filterAddressing; // VVVVUUUU FFFFFFFF
+ int32 refCount;
+
+ LLLink inGlobalList; // actually not in RW
+
+ static int32 numAllocated;
+
+ static Texture *create(Raster *raster);
+ void addRef(void) { this->refCount++; }
+ void destroy(void);
+ static Texture *fromDict(LLLink *lnk){
+ return LLLinkGetData(lnk, Texture, inDict); }
+ FilterMode getFilter(void) { return (FilterMode)(filterAddressing & 0xFF); }
+ void setFilter(FilterMode f) { filterAddressing = (filterAddressing & ~0xFF) | f; }
+ Addressing getAddressU(void) { return (Addressing)((filterAddressing >> 8) & 0xF); }
+ Addressing getAddressV(void) { return (Addressing)((filterAddressing >> 12) & 0xF); }
+ void setAddressU(Addressing u) { filterAddressing = (filterAddressing & ~0xF00) | u<<8; }
+ void setAddressV(Addressing v) { filterAddressing = (filterAddressing & ~0xF000) | v<<12; }
+ static Texture *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+ static Texture *read(const char *name, const char *mask);
+ static Texture *streamReadNative(Stream *stream);
+ void streamWriteNative(Stream *stream);
+ uint32 streamGetSizeNative(void);
+
+ static Texture *(*findCB)(const char *name);
+ static Texture *(*readCB)(const char *name, const char *mask);
+ static void setLoadTextures(bool32); // default: true
+ static void setCreateDummies(bool32); // default: false
+ static void setMipmapping(bool32); // default: false
+ static void setAutoMipmapping(bool32); // default: false
+ static bool32 getMipmapping(void);
+ static bool32 getAutoMipmapping(void);
+
+ void setMaxAnisotropy(int32 maxaniso); // only if plugin is attached
+ int32 getMaxAnisotropy(void);
+
+#ifndef RWPUBLIC
+ static void registerModule(void);
+#endif
+};
+
+extern int32 anisotOffset;
+#define GETANISOTROPYEXT(texture) PLUGINOFFSET(int32, texture, rw::anisotOffset)
+void registerAnisotropyPlugin(void);
+int32 getMaxSupportedMaxAnisotropy(void);
+
+struct SurfaceProperties
+{
+ float32 ambient;
+ float32 specular;
+ float32 diffuse;
+};
+
+struct Material
+{
+ PLUGINBASE
+ Texture *texture;
+ RGBA color;
+ SurfaceProperties surfaceProps;
+ Pipeline *pipeline;
+ int32 refCount;
+
+ static int32 numAllocated;
+
+ static Material *create(void);
+ void addRef(void) { this->refCount++; }
+ Material *clone(void);
+ void destroy(void);
+ void setTexture(Texture *tex);
+ static Material *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+};
+
+void registerMaterialRightsPlugin(void);
+
+struct Mesh
+{
+ uint16 *indices;
+ uint32 numIndices;
+ Material *material;
+};
+
+struct MeshHeader
+{
+ enum {
+ TRISTRIP = 1
+ };
+ uint32 flags;
+ uint16 numMeshes;
+ uint16 serialNum;
+ uint32 totalIndices;
+ uint32 pad; // needed for alignment of Meshes
+ // after this the meshes
+
+ Mesh *getMeshes(void) { return (Mesh*)(this+1); }
+ void setupIndices(void);
+ uint32 guessNumTriangles(void);
+};
+
+struct Geometry;
+
+struct MorphTarget
+{
+ Geometry *parent;
+ Sphere boundingSphere;
+ V3d *vertices;
+ V3d *normals;
+
+ Sphere calculateBoundingSphere(void) const;
+};
+
+struct InstanceDataHeader
+{
+ uint32 platform;
+};
+
+struct Triangle
+{
+ uint16 v[3];
+ 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 flags;
+ uint16 lockedSinceInst;
+ int32 numTriangles;
+ int32 numVertices;
+ int32 numMorphTargets;
+ int32 numTexCoordSets;
+
+ Triangle *triangles;
+ RGBA *colors;
+ TexCoords *texCoords[8];
+
+ MorphTarget *morphTargets;
+ MaterialList matList;
+
+ MeshHeader *meshHeader;
+ InstanceDataHeader *instData;
+
+ int32 refCount;
+
+ static int32 numAllocated;
+
+ static Geometry *create(int32 numVerts, int32 numTris, uint32 flags);
+ void addRef(void) { this->refCount++; }
+ void destroy(void);
+ void lock(int32 lockFlags);
+ void unlock(void);
+ void addMorphTargets(int32 n);
+ void calculateBoundingSphere(void);
+ bool32 hasColoredMaterial(void);
+ void allocateData(void);
+ MeshHeader *allocateMeshes(int32 numMeshes, uint32 numIndices, bool32 noIndices);
+ void generateTriangles(int8 *adc = nil);
+ void buildMeshes(void);
+ void buildTristrips(void); // private, used by buildMeshes
+ void correctTristripWinding(void);
+ void removeUnusedMaterials(void);
+ static Geometry *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+
+ enum Flags
+ {
+ TRISTRIP = 0x01,
+ POSITIONS = 0x02,
+ TEXTURED = 0x04,
+ PRELIT = 0x08,
+ NORMALS = 0x10,
+ LIGHT = 0x20,
+ MODULATE = 0x40,
+ TEXTURED2 = 0x80,
+ // When this flag is set the geometry has
+ // native geometry. When streamed out this geometry
+ // is written out instead of the platform independent data.
+ // When streamed in with this flag, the geometry is mostly empty.
+ NATIVE = 0x01000000,
+ // Just for documentation: RW sets this flag
+ // to prevent rendering when executing a pipeline,
+ // so only instancing will occur.
+ // librw's pipelines are different so it's unused here.
+ 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);
+void registerNativeDataPlugin(void);
+
+struct Clump;
+struct World;
+
+struct Atomic
+{
+ PLUGINBASE
+ typedef void (*RenderCB)(Atomic *atomic);
+ enum { ID = 1 };
+ enum {
+ // flags
+ COLLISIONTEST = 0x01, // unused here
+ RENDER = 0x04,
+ // private flags
+ WORLDBOUNDDIRTY = 0x01,
+ // for setGeometry
+ SAMEBOUNDINGSPHERE = 0x01
+ };
+
+ ObjectWithFrame object;
+ Geometry *geometry;
+ Sphere boundingSphere;
+ Sphere worldBoundingSphere;
+ Clump *clump;
+ LLLink inClump;
+ ObjPipeline *pipeline;
+ RenderCB renderCB;
+
+ World *world;
+ ObjectWithFrame::Sync originalSync;
+
+ static int32 numAllocated;
+
+ static Atomic *create(void);
+ Atomic *clone(void);
+ void destroy(void);
+ void setFrame(Frame *f) {
+ this->object.setFrame(f);
+ this->object.object.privateFlags |= WORLDBOUNDDIRTY;
+ }
+ Frame *getFrame(void) const { return (Frame*)this->object.object.parent; }
+ static Atomic *fromClump(LLLink *lnk){
+ return LLLinkGetData(lnk, Atomic, inClump); }
+ void setGeometry(Geometry *geo, uint32 flags);
+ Sphere *getWorldBoundingSphere(void);
+ ObjPipeline *getPipeline(void);
+ void instance(void);
+ void uninstance(void);
+ void render(void) { this->renderCB(this); }
+ void setRenderCB(RenderCB renderCB){
+ this->renderCB = renderCB;
+ if(this->renderCB == nil)
+ this->renderCB = defaultRenderCB;
+ };
+ void setFlags(uint32 flags) { this->object.object.flags = flags; }
+ uint32 getFlags(void) const { return this->object.object.flags; }
+ static Atomic *streamReadClump(Stream *stream,
+ FrameList_ *frameList, Geometry **geometryList);
+ bool streamWriteClump(Stream *stream, FrameList_ *frmlst);
+ uint32 streamGetSize(void);
+
+ static void defaultRenderCB(Atomic *atomic);
+};
+
+void registerAtomicRightsPlugin(void);
+
+struct Light
+{
+ PLUGINBASE
+ enum { ID = 3 };
+ ObjectWithFrame object;
+ float32 radius;
+ RGBAf color;
+ float32 minusCosAngle;
+ LLLink inWorld;
+
+ // clump extension
+ Clump *clump;
+ LLLink inClump;
+
+ // world extension
+ World *world;
+ ObjectWithFrame::Sync originalSync;
+
+ static int32 numAllocated;
+
+ static Light *create(int32 type);
+ void destroy(void);
+ void setFrame(Frame *f) { this->object.setFrame(f); }
+ Frame *getFrame(void) const { return (Frame*)this->object.object.parent; }
+ static Light *fromClump(LLLink *lnk){
+ return LLLinkGetData(lnk, Light, inClump); }
+ static Light *fromWorld(LLLink *lnk){
+ return LLLinkGetData(lnk, Light, inWorld); }
+ void setAngle(float32 angle);
+ float32 getAngle(void);
+ void setColor(float32 r, float32 g, float32 b);
+ int32 getType(void){ return this->object.object.subType; }
+ void setFlags(uint32 flags) { this->object.object.flags = flags; }
+ uint32 getFlags(void) { return this->object.object.flags; }
+ static Light *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+
+ enum Type {
+ DIRECTIONAL = 1,
+ AMBIENT,
+ POINT = 0x80, // positioned
+ SPOT,
+ SOFTSPOT
+ };
+ enum Flags {
+ LIGHTATOMICS = 1,
+ LIGHTWORLD = 2
+ };
+};
+
+struct FrustumPlane
+{
+ Plane plane;
+ /* Used for BBox tests:
+ * 0 = inf is closer to normal direction
+ * 1 = sup is closer to normal direction */
+ uint8 closestX;
+ uint8 closestY;
+ uint8 closestZ;
+};
+
+struct Camera
+{
+ PLUGINBASE
+ enum { ID = 4 };
+ enum { PERSPECTIVE = 1, PARALLEL };
+ enum { CLEARIMAGE = 0x1, CLEARZ = 0x2, CLEARSTENCIL = 0x4 };
+ // return value of frustumTestSphere
+ enum { SPHEREOUTSIDE, SPHEREBOUNDARY, SPHEREINSIDE };
+
+ ObjectWithFrame object;
+ void (*beginUpdateCB)(Camera*);
+ void (*endUpdateCB)(Camera*);
+ V2d viewWindow;
+ V2d viewOffset;
+ float32 nearPlane, farPlane;
+ float32 fogPlane;
+ int32 projection;
+
+ Matrix viewMatrix;
+ float32 zScale, zShift;
+
+ FrustumPlane frustumPlanes[6];
+ V3d frustumCorners[8];
+ BBox frustumBoundBox;
+
+ Raster *frameBuffer;
+ Raster *zBuffer;
+
+ // Device dependent view and projection matrices
+ // optional
+ RawMatrix devView;
+ RawMatrix devProj;
+
+ // clump link handled by plugin in RW
+ Clump *clump;
+ LLLink inClump;
+
+ // world extension
+ /* RW: frustum sectors, space, position */
+ World *world;
+ ObjectWithFrame::Sync originalSync;
+ void (*originalBeginUpdate)(Camera*);
+ void (*originalEndUpdate)(Camera*);
+
+ static int32 numAllocated;
+
+ static Camera *create(void);
+ Camera *clone(void);
+ void destroy(void);
+ void setFrame(Frame *f) { this->object.setFrame(f); }
+ Frame *getFrame(void)const { return (Frame*)this->object.object.parent; }
+ static Camera *fromClump(LLLink *lnk){
+ return LLLinkGetData(lnk, Camera, inClump); }
+ void beginUpdate(void) { this->beginUpdateCB(this); }
+ void endUpdate(void) { this->endUpdateCB(this); }
+ void clear(RGBA *col, uint32 mode);
+ void showRaster(uint32 flags);
+ void setNearPlane(float32);
+ void setFarPlane(float32);
+ void setViewWindow(const V2d *window);
+ void setViewOffset(const V2d *offset);
+ void setProjection(int32 proj);
+ int32 frustumTestSphere(const Sphere *s) const;
+ static Camera *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+
+ // fov in degrees
+ void setFOV(float32 fov, float32 ratio);
+};
+
+struct Clump
+{
+ PLUGINBASE
+ enum { ID = 2 };
+ Object object;
+ LinkList atomics;
+ LinkList lights;
+ LinkList cameras;
+
+ World *world;
+ LLLink inWorld;
+
+ static int32 numAllocated;
+
+ static Clump *create(void);
+ Clump *clone(void);
+ void destroy(void);
+ static Clump *fromWorld(LLLink *lnk){
+ return LLLinkGetData(lnk, Clump, inWorld); }
+ int32 countAtomics(void) { return this->atomics.count(); }
+ void addAtomic(Atomic *a);
+ void removeAtomic(Atomic *a);
+ int32 countLights(void) { return this->lights.count(); }
+ void addLight(Light *l);
+ void removeLight(Light *l);
+ int32 countCameras(void) { return this->cameras.count(); }
+ void addCamera(Camera *c);
+ void removeCamera(Camera *c);
+ void setFrame(Frame *f){
+ this->object.parent = f; }
+ Frame *getFrame(void) const {
+ return (Frame*)this->object.parent; }
+ static Clump *streamRead(Stream *stream);
+ bool streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+ void render(void);
+};
+
+// used by enumerateLights for lighting callback
+struct WorldLights
+{
+ int32 numAmbients;
+ RGBAf ambient; // all ambients added
+ int32 numDirectionals;
+ Light **directionals; // only directionals
+ int32 numLocals;
+ Light **locals; // points, (soft)spots
+};
+
+// A bit of a stub right now
+struct World
+{
+ PLUGINBASE
+ enum { ID = 7 };
+ Object object;
+ LinkList localLights; // these have positions (type >= 0x80)
+ LinkList globalLights; // these do not (type < 0x80)
+ LinkList clumps;
+
+ static int32 numAllocated;
+
+ static World *create(BBox *bbox = nil); // TODO: should probably make this non-optional
+ void destroy(void);
+ void addLight(Light *light);
+ void removeLight(Light *light);
+ void addCamera(Camera *cam);
+ void removeCamera(Camera *cam);
+ void addAtomic(Atomic *atomic);
+ void removeAtomic(Atomic *atomic);
+ void addClump(Clump *clump);
+ void removeClump(Clump *clump);
+ void render(void);
+ void enumerateLights(Atomic *atomic, WorldLights *lightData);
+ void enumerateLights(WorldLights *lightData);
+};
+
+struct TexDictionary
+{
+ PLUGINBASE
+ enum { ID = 6 };
+ Object object;
+ LinkList textures;
+ LLLink inGlobalList;
+
+ static int32 numAllocated;
+
+ static TexDictionary *create(void);
+ static TexDictionary *fromLink(LLLink *lnk){
+ return LLLinkGetData(lnk, TexDictionary, inGlobalList); }
+ void destroy(void);
+ int32 count(void) { return this->textures.count(); }
+ void add(Texture *t);
+ void addFront(Texture *t);
+ void remove(Texture *t);
+ Texture *find(const char *name);
+ static TexDictionary *streamRead(Stream *stream);
+ void streamWrite(Stream *stream);
+ uint32 streamGetSize(void);
+
+ static void setCurrent(TexDictionary *txd);
+ static TexDictionary *getCurrent(void);
+};
+
+}