From c53d29b1cf67199429c67ebae5e07f3b019a7050 Mon Sep 17 00:00:00 2001 From: aap Date: Sun, 27 Aug 2017 17:13:10 +0200 Subject: [PATCH] implemented im2d for d3d, fun little software T&L renderer --- skeleton/skeleton.cpp | 4 +- skeleton/win.cpp | 17 +++-- src/camera.cpp | 7 ++ src/d3d/d3ddevice.cpp | 22 ++++-- src/d3d/d3dim2d.cpp | 102 +++++++++++++++++++++++++++ src/d3d/rwd3d.h | 18 +++++ src/d3d/rwd3dimpl.h | 6 ++ src/engine.cpp | 20 +++--- src/frame.cpp | 10 ++- src/gl/gl3device.cpp | 57 +++++++++------ src/gl/gl3im2d.cpp | 30 +++++--- src/gl/gl3raster.cpp | 21 +++++- src/gl/rwgl3.h | 18 ++++- src/gl/rwgl3impl.h | 2 +- src/gl/shaders/im2d.vert | 20 +++--- src/gl/shaders/im2d_gl3.inc | 20 +++--- src/rwbase.h | 28 ++++++++ src/rwengine.h | 8 +-- src/rwobjects.h | 66 ++++++++++-------- src/texture.cpp | 65 +++++++++++++---- tools/clumpview/camera.cpp | 4 +- tools/clumpview/main.cpp | 81 +++++++++++++++++----- tools/clumpview/maze.tga | Bin 0 -> 49196 bytes tools/clumpview/tests.cpp | 134 ++++++++++++++++++++++++++++++++++++ 24 files changed, 618 insertions(+), 142 deletions(-) create mode 100644 src/d3d/d3dim2d.cpp create mode 100644 tools/clumpview/maze.tga create mode 100644 tools/clumpview/tests.cpp diff --git a/skeleton/skeleton.cpp b/skeleton/skeleton.cpp index 6fa1096..89b6c76 100644 --- a/skeleton/skeleton.cpp +++ b/skeleton/skeleton.cpp @@ -17,10 +17,8 @@ InitRW(void) return false; if(!rw::Engine::start(&engineStartParams)) return false; - rw::engine->loadTextures = 1; - rw::TexDictionary::setCurrent(rw::TexDictionary::create()); - rw::Image::setSearchPath("."); + rw::Image::setSearchPath("./"); return true; } diff --git a/skeleton/win.cpp b/skeleton/win.cpp index cd4fd81..d1648af 100644 --- a/skeleton/win.cpp +++ b/skeleton/win.cpp @@ -127,11 +127,20 @@ MakeWindow(HINSTANCE instance, int width, int height, const char *title) return 0; } + int offx = 100; + int offy = 100; + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = width; + rect.bottom = height; + DWORD style = WS_OVERLAPPEDWINDOW; + AdjustWindowRect(&rect, style, FALSE); + rect.right += -rect.left; + rect.bottom += -rect.top; HWND win; - win = CreateWindow("librwD3D9", title, - WS_BORDER | WS_CAPTION | WS_SYSMENU | - WS_MINIMIZEBOX | WS_MAXIMIZEBOX, - 0, 0, width, height, 0, 0, instance, 0); + win = CreateWindow("librwD3D9", title, style, + offx, offy, rect.right, rect.bottom, 0, 0, instance, 0); if(!win){ MessageBox(0, "CreateWindow() - FAILED", 0, 0); return 0; diff --git a/src/camera.cpp b/src/camera.cpp index 489fe5b..94554d9 100755 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -284,6 +284,9 @@ Camera::create(void) cam->fogPlane = 5.0f; cam->projection = Camera::PERSPECTIVE; + cam->frameBuffer = nil; + cam->zBuffer = nil; + // clump extension cam->clump = nil; cam->inClump.init(); @@ -315,6 +318,10 @@ Camera::clone(void) cam->farPlane = this->farPlane; cam->fogPlane = this->fogPlane; cam->projection = this->projection; + + cam->frameBuffer = this->frameBuffer; + cam->zBuffer = this->zBuffer; + s_plglist.copy(cam, this); return cam; } diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp index d420914..783f8cc 100755 --- a/src/d3d/d3ddevice.cpp +++ b/src/d3d/d3ddevice.cpp @@ -10,6 +10,7 @@ #include "../rwobjects.h" #include "../rwengine.h" #include "rwd3d.h" +#include "rwd3dimpl.h" #define PLUGIN_ID 0 @@ -275,6 +276,7 @@ setRasterStage(uint32 stage, Raster *raster) void setTexture(uint32 stage, Texture *tex) { + // TODO: support mipmaps static DWORD filternomip[] = { 0, D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_LINEAR, @@ -289,10 +291,10 @@ setTexture(uint32 stage, Texture *tex) return; } if(tex->raster){ - setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->filterAddressing & 0xFF]); - setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]); - setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]); - setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]); + setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->getFilter()]); + setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->getFilter()]); + setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[tex->getAddressU()]); + setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[tex->getAddressV()]); } setRasterStage(stage, tex->raster); } @@ -528,6 +530,14 @@ initD3D(void) // setTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_CONSTANT); // setTextureStageState(0, D3DTSS_COLOROP, D3DTA_CONSTANT); + openIm2D(); + + return 1; +} + +static int +finalizeD3D(void) +{ return 1; } @@ -539,6 +549,8 @@ deviceSystem(DeviceReq req, void *arg0) return startD3D((EngineStartParams*)arg0); case DEVICEINIT: return initD3D(); + case DEVICEFINALIZE: + return finalizeD3D(); case DEVICESTOP: return stopD3D(); } @@ -553,7 +565,7 @@ Device renderdevice = { d3d::showRaster, d3d::setRwRenderState, d3d::getRwRenderState, - null::im2DRenderIndexedPrimitive, + d3d::im2DRenderIndexedPrimitive, d3d::deviceSystem, }; diff --git a/src/d3d/d3dim2d.cpp b/src/d3d/d3dim2d.cpp new file mode 100644 index 0000000..ae4182c --- /dev/null +++ b/src/d3d/d3dim2d.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include + +#include "../rwbase.h" +#include "../rwplg.h" +#include "../rwpipeline.h" +#include "../rwobjects.h" +#include "../rwengine.h" +#include "rwd3d.h" +#include "rwd3d9.h" + +namespace rw { +namespace d3d { + +#ifdef RW_D3D9 + +// might want to tweak this +#define NUMINDICES 10000 +#define NUMVERTICES 10000 + +static int primTypeMap[] = { + D3DPT_POINTLIST, // invalid + D3DPT_LINELIST, + D3DPT_LINESTRIP, + D3DPT_TRIANGLELIST, + D3DPT_TRIANGLESTRIP, + D3DPT_TRIANGLEFAN, + D3DPT_POINTLIST, // actually not supported! +}; + +static IDirect3DVertexDeclaration9 *im2ddecl; +static IDirect3DVertexBuffer9 *im2dvertbuf; +static IDirect3DIndexBuffer9 *im2dindbuf; + +void +openIm2D(void) +{ + D3DVERTEXELEMENT9 elements[4] = { + { 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 }, + { 0, offsetof(Im2DVertex, color), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, + { 0, offsetof(Im2DVertex, u), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, + D3DDECL_END() + }; + d3ddevice->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &im2ddecl); + im2dvertbuf = (IDirect3DVertexBuffer9*)createVertexBuffer(NUMVERTICES*sizeof(Im2DVertex), 0, D3DPOOL_MANAGED); + im2dindbuf = (IDirect3DIndexBuffer9*)createIndexBuffer(NUMINDICES*sizeof(uint16)); +} + +void +im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, void *indices, int32 numIndices) +{ + if(numVertices > NUMVERTICES || + numIndices > NUMINDICES){ + // TODO: error + return; + } + uint16 *lockedindices = lockIndices(im2dindbuf, 0, numIndices*sizeof(uint16), 0); + memcpy(lockedindices, indices, numIndices*sizeof(uint16)); + unlockIndices(im2dindbuf); + + uint8 *lockedvertices = lockVertices(im2dvertbuf, 0, numVertices*sizeof(Im2DVertex), D3DLOCK_NOSYSLOCK); + memcpy(lockedvertices, vertices, numVertices*sizeof(Im2DVertex)); + unlockVertices(im2dvertbuf); + + d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex)); + d3ddevice->SetIndices(im2dindbuf); + d3ddevice->SetVertexDeclaration(im2ddecl); + d3d::setTexture(0, engine->imtexture); + d3d::flushCache(); + + uint32 primCount = 0; + switch(primType){ + case PRIMTYPELINELIST: + primCount = numIndices/2; + break; + case PRIMTYPEPOLYLINE: + primCount = numIndices-1; + break; + case PRIMTYPETRILIST: + primCount = numIndices/3; + break; + case PRIMTYPETRISTRIP: + primCount = numIndices-2; + break; + case PRIMTYPETRIFAN: + primCount = numIndices-2; + break; + case PRIMTYPEPOINTLIST: + primCount = numIndices; + break; + } + d3ddevice->DrawIndexedPrimitive((D3DPRIMITIVETYPE)primTypeMap[primType], 0, + 0, numVertices, + 0, primCount); +} + +#endif +} +} diff --git a/src/d3d/rwd3d.h b/src/d3d/rwd3d.h index 836d8d3..f3a89df 100644 --- a/src/d3d/rwd3d.h +++ b/src/d3d/rwd3d.h @@ -21,6 +21,24 @@ extern IDirect3DDevice9 *d3ddevice; extern Device renderdevice; void lightingCB(void); + +struct Im2DVertex +{ + float32 x, y, z; + float32 w; + D3DCOLOR color; + float32 u, v; + + void setScreenX(float32 x) { this->x = x; } + void setScreenY(float32 y) { this->y = y; } + void setScreenZ(float32 z) { this->z = z; } + void setCameraZ(float32 z) { } + void setRecipCameraZ(float32 recipz) { this->w = recipz; } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { this->color = D3DCOLOR_ARGB(a, r, g, b); } + void setU(float32 u) { this->u = u; } + void setV(float32 v) { this->v = v; } +}; + #else enum { D3DLOCK_NOSYSLOCK = 0, // ignored diff --git a/src/d3d/rwd3dimpl.h b/src/d3d/rwd3dimpl.h index 0053181..a400119 100644 --- a/src/d3d/rwd3dimpl.h +++ b/src/d3d/rwd3dimpl.h @@ -1,6 +1,12 @@ namespace rw { namespace d3d { +#ifdef RW_D3D9 +void openIm2D(void); +void im2DRenderIndexedPrimitive(PrimitiveType primType, + void *vertices, int32 numVertices, void *indices, int32 numIndices); +#endif + void rasterCreate(Raster *raster); uint8 *rasterLock(Raster *raster, int32 level); void rasterUnlock(Raster *raster, int32 level); diff --git a/src/engine.cpp b/src/engine.cpp index b5c5366..3820295 100755 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -41,7 +41,7 @@ void *mustmalloc_h(size_t sz, uint32 hint) { void *ret; ret = rwMalloc(sz, hint); - if(ret) + if(ret || sz == 0) return ret; fprintf(stderr, "Error: out of memory\n"); exit(1); @@ -51,7 +51,7 @@ void *mustrealloc_h(void *p, size_t sz, uint32 hint) { void *ret; ret = rwRealloc(p, sz, hint); - if(ret) + if(ret || sz == 0) return ret; fprintf(stderr, "Error: out of memory\n"); exit(1); @@ -83,7 +83,8 @@ Engine::init(void) Engine::s_plglist.last = nil; // core plugin attach here - Engine::registerPlugin(0, ID_FRAMEMODULE, Frame::_open, Frame::_close); + Frame::registerModule(); + Texture::registerModule(); // driver plugin attach ps2::registerPlatformPlugins(); @@ -111,10 +112,7 @@ Engine::open(void) engine = (Engine*)rwNew(Engine::s_plglist.size, MEMDUR_GLOBAL); engine->currentCamera = nil; engine->currentWorld = nil; - engine->currentTexDictionary = nil; engine->imtexture = nil; - engine->loadTextures = 1; - engine->makeDummies = 1; // Initialize device // Device and possibly OS specific! @@ -177,10 +175,7 @@ void Engine::term(void) { // TODO - for(uint i = 0; i < NUM_PLATFORMS; i++) - Driver::s_plglist[i].destruct(rw::engine->driver[i]); - Engine::s_plglist.destruct(engine); - Engine::state = Opened; + Engine::state = Dead; } void @@ -197,7 +192,10 @@ void Engine::stop(void) { engine->device.system(DEVICESTOP, nil); - Engine::state = Dead; + for(uint i = 0; i < NUM_PLATFORMS; i++) + Driver::s_plglist[i].destruct(rw::engine->driver[i]); + Engine::s_plglist.destruct(engine); + Engine::state = Opened; } namespace null { diff --git a/src/frame.cpp b/src/frame.cpp index 7e92c4e..8387730 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -13,10 +13,14 @@ namespace rw { PluginList Frame::s_plglist = { sizeof(Frame), sizeof(Frame), nil, nil }; -void *Frame::_open(void *object, int32 offset, int32 size) { engine->frameDirtyList.init(); return object; } -void *Frame::_close(void *object, int32 offset, int32 size) { return object; } - +static void *frameOpen(void *object, int32 offset, int32 size) { engine->frameDirtyList.init(); return object; } +static void *frameClose(void *object, int32 offset, int32 size) { return object; } +void +Frame::registerModule(void) +{ + Engine::registerPlugin(0, ID_FRAMEMODULE, frameOpen, frameClose); +} Frame* Frame::create(void) diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 538787d..cb2c647 100755 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -70,7 +70,6 @@ static UniformObject uniformObject; int32 u_matColor; int32 u_surfaceProps; - Shader *simpleShader; static bool32 stateDirty = 1; @@ -304,6 +303,17 @@ setActiveTexture(int32 n) void setTexture(int32 n, Texture *tex) { + // TODO: support mipmaps + static GLint filternomip[] = { + 0, GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR, + GL_NEAREST, GL_LINEAR + }; + + static GLint wrap[] = { + 0, GL_REPEAT, GL_MIRRORED_REPEAT, + GL_CLAMP, GL_CLAMP_TO_BORDER + }; bool32 alpha; setActiveTexture(GL_TEXTURE0+n); if(tex == nil || tex->raster->platform != PLATFORM_GL3 || @@ -315,6 +325,13 @@ setTexture(int32 n, Texture *tex) nativeRasterOffset); glBindTexture(GL_TEXTURE_2D, natras->texid); alpha = natras->hasAlpha; + if(tex->filterAddressing != natras->filterAddressing){ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filternomip[tex->getFilter()]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filternomip[tex->getFilter()]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap[tex->getAddressU()]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap[tex->getAddressV()]); + natras->filterAddressing = tex->filterAddressing; + } } if(n == 0){ @@ -518,25 +535,6 @@ initOpenGL(void) glGenVertexArrays(1, &vao); glBindVertexArray(vao); - byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF}; - glGenTextures(1, &whitetex); - glBindTexture(GL_TEXTURE_2D, whitetex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); - - im2DInit(); - - return 1; -} - -static int -finalizeOpenGL(void) -{ -#include "shaders/simple_gl3.inc" - simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); - glGenBuffers(1, &ubo_state); glBindBuffer(GL_UNIFORM_BUFFER, ubo_state); glBindBufferBase(GL_UNIFORM_BUFFER, gl3::findBlock("State"), ubo_state); @@ -558,6 +556,25 @@ finalizeOpenGL(void) GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); + byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + glGenTextures(1, &whitetex); + glBindTexture(GL_TEXTURE_2D, whitetex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel); + +#include "shaders/simple_gl3.inc" + simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); + + openIm2D(); + + return 1; +} + +static int +finalizeOpenGL(void) +{ return 1; } diff --git a/src/gl/gl3im2d.cpp b/src/gl/gl3im2d.cpp index 699fdc7..60143a4 100644 --- a/src/gl/gl3im2d.cpp +++ b/src/gl/gl3im2d.cpp @@ -16,19 +16,20 @@ namespace rw { namespace gl3 { -uint32 im2DVbo, im2DIbo; +static uint32 im2DVbo, im2DIbo; +static int32 u_xform; -#define STARTINDICES 1024 -#define STARTVERTICES 1024 +#define STARTINDICES 10000 +#define STARTVERTICES 10000 static Shader *im2dShader; static AttribDesc attribDesc[3] = { - { ATTRIB_POS, GL_FLOAT, GL_FALSE, 3, + { ATTRIB_POS, GL_FLOAT, GL_FALSE, 4, sizeof(Im2DVertex), 0 }, { ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4, sizeof(Im2DVertex), offsetof(Im2DVertex, r) }, { ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2, - sizeof(Im2DVertex), offsetof(Im2DVertex, r) }, + sizeof(Im2DVertex), offsetof(Im2DVertex, u) }, }; static int primTypeMap[] = { @@ -42,8 +43,10 @@ static int primTypeMap[] = { }; void -im2DInit(void) +openIm2D(void) { + u_xform = registerUniform("u_xform"); + #include "shaders/im2d_gl3.inc" im2dShader = Shader::fromStrings(im2d_vert_src, im2d_frag_src); @@ -65,6 +68,11 @@ im2DRenderIndexedPrimitive(PrimitiveType primType, void *vertices, int32 numVertices, void *indices, int32 numIndices) { + GLfloat xform[4]; + Camera *cam; + cam = (Camera*)engine->currentCamera; + + // TODO: fixed size glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_DYNAMIC_DRAW); @@ -73,9 +81,15 @@ im2DRenderIndexedPrimitive(PrimitiveType primType, glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_DYNAMIC_DRAW); - setAttribPointers(attribDesc, 3); - im2dShader->use(); + xform[0] = 2.0f/cam->frameBuffer->width; + xform[1] = -2.0f/cam->frameBuffer->height; + xform[2] = -1.0f; + xform[3] = 1.0f; + im2dShader->use(); + setAttribPointers(attribDesc, 3); + + glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform); setTexture(0, engine->imtexture); flushCache(); diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index b8f14e9..5a65941 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -23,9 +23,27 @@ int32 nativeRasterOffset; void rasterCreate(Raster *raster) { + switch(raster->type){ + case Raster::CAMERA: + // TODO: set/check width, height, depth, format? + raster->flags |= Raster::DONTALLOCATE; + break; + case Raster::ZBUFFER: + // TODO: set/check width, height, depth, format? + raster->flags |= Raster::DONTALLOCATE; + break; + case Raster::TEXTURE: + // continue below + break; + default: + assert(0 && "unsupported format"); + } + if(raster->flags & Raster::DONTALLOCATE) return; + assert(raster->type == Raster::TEXTURE); + #ifdef RW_OPENGL Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset); switch(raster->format & 0xF00){ @@ -54,11 +72,10 @@ rasterCreate(Raster *raster) glGenTextures(1, &natras->texid); glBindTexture(GL_TEXTURE_2D, natras->texid); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, raster->width, raster->height, 0, natras->format, natras->type, nil); + natras->filterAddressing = ~0; glBindTexture(GL_TEXTURE_2D, 0); #endif diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index d7d817f..3a8de4c 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -78,11 +78,23 @@ struct InstanceDataHeader : rw::InstanceDataHeader InstanceData *inst; }; +#ifdef RW_GL3 + struct Im2DVertex { - float32 x, y, z; + float32 x, y, z, w; uint8 r, g, b, a; float32 u, v; + + void setScreenX(float32 x) { this->x = x; } + void setScreenY(float32 y) { this->y = y; } + void setScreenZ(float32 z) { this->z = z; } + void setCameraZ(float32 z) { this->w = z; } + void setRecipCameraZ(float32 recipz) { } + void setColor(uint8 r, uint8 g, uint8 b, uint8 a) { + this->r = r; this->g = g; this->b = b; this->a = a; } + void setU(float32 u) { this->u = u; } + void setV(float32 v) { this->v = v; } }; void setAttribPointers(AttribDesc *attribDescs, int32 numAttribs); @@ -105,6 +117,8 @@ void setTexture(int32 n, Texture *tex); void flushCache(void); +#endif + class ObjPipeline : public rw::ObjPipeline { public: @@ -136,6 +150,8 @@ struct Gl3Raster uint32 texid; bool32 hasAlpha; + // cached filtermode and addressing + uint32 filterAddressing; }; void registerNativeRaster(void); diff --git a/src/gl/rwgl3impl.h b/src/gl/rwgl3impl.h index 7a83321..e79955a 100644 --- a/src/gl/rwgl3impl.h +++ b/src/gl/rwgl3impl.h @@ -5,7 +5,7 @@ namespace gl3 { extern Shader *simpleShader; extern uint32 im2DVbo, im2DIbo; -void im2DInit(void); +void openIm2D(void); void im2DRenderIndexedPrimitive(PrimitiveType primType, void *vertices, int32 numVertices, void *indices, int32 numIndices); diff --git a/src/gl/shaders/im2d.vert b/src/gl/shaders/im2d.vert index 2e776c9..6547571 100644 --- a/src/gl/shaders/im2d.vert +++ b/src/gl/shaders/im2d.vert @@ -1,13 +1,15 @@ #version 330 -layout(std140) uniform Im2DState -{ - int u_alphaTest; - float u_alphaRef; - mat4 u_xform; -}; +//layout(std140) uniform Im2DState +//{ +// int u_alphaTest; +// float u_alphaRef; +// mat4 u_xform; +//}; -layout(location = 0) in vec3 in_pos; +uniform vec4 u_xform; + +layout(location = 0) in vec4 in_pos; layout(location = 2) in vec4 in_color; layout(location = 3) in vec2 in_tex0; @@ -17,7 +19,9 @@ out vec2 v_tex0; void main(void) { - gl_Position = vec4(in_pos, 1.0); + gl_Position = in_pos; + gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw; + gl_Position.xyz *= gl_Position.w; v_color = in_color; v_tex0 = in_tex0; } diff --git a/src/gl/shaders/im2d_gl3.inc b/src/gl/shaders/im2d_gl3.inc index 6230350..ee1cbcb 100644 --- a/src/gl/shaders/im2d_gl3.inc +++ b/src/gl/shaders/im2d_gl3.inc @@ -1,14 +1,16 @@ const char *im2d_vert_src = "#version 330\n" -"layout(std140) uniform Im2DState\n" -"{\n" -" int u_alphaTest;\n" -" float u_alphaRef;\n" -" mat4 u_xform;\n" -"};\n" +"//layout(std140) uniform Im2DState\n" +"//{\n" +"// int u_alphaTest;\n" +"// float u_alphaRef;\n" +"// mat4 u_xform;\n" +"//};\n" -"layout(location = 0) in vec3 in_pos;\n" +"uniform vec4 u_xform;\n" + +"layout(location = 0) in vec4 in_pos;\n" "layout(location = 2) in vec4 in_color;\n" "layout(location = 3) in vec2 in_tex0;\n" @@ -18,7 +20,9 @@ const char *im2d_vert_src = "void\n" "main(void)\n" "{\n" -" gl_Position = vec4(in_pos, 1.0);\n" +" gl_Position = in_pos;\n" +" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n" +" gl_Position.xyz *= gl_Position.w;\n" " v_color = in_color;\n" " v_tex0 = in_tex0;\n" "}\n" diff --git a/src/rwbase.h b/src/rwbase.h index e221c30..69a7922 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -8,6 +8,19 @@ #ifdef RW_GL3 #define RW_OPENGL +#define RWDEVICE gl3 +#endif + +#ifdef RW_D3D9 +#define RWDEVICE d3d +#endif + +#ifdef RW_D3D8 +#define RWDEVICE d3d +#endif + +#ifdef RW_PS2 +#define RWDEVICE ps2 #endif #ifdef RW_WDGL @@ -64,7 +77,21 @@ struct RGBAf float32 blue; float32 alpha; }; +inline RGBAf makeRGBAf(float32 r, float32 g, float32 b, float32 a) { RGBAf c = { r, g, b, a }; return c; } inline bool32 equal(const RGBAf &c1, const RGBAf &c2) { return c1.red == c2.red && c1.green == c2.green && c1.blue == c2.blue && c1.alpha == c2.alpha; } +inline RGBAf add(const RGBAf &a, const RGBAf &b) { return makeRGBAf(a.red+b.red, a.green+b.green, a.blue+b.blue, a.alpha+b.alpha); } +inline RGBAf modulate(const RGBAf &a, const RGBAf &b) { return makeRGBAf(a.red*b.red, a.green*b.green, a.blue*b.blue, a.alpha*b.alpha); } +inline RGBAf scale(const RGBAf &a, float32 f) { return makeRGBAf(a.red*f, a.green*f, a.blue*f, a.alpha*f); } +inline void clamp(RGBAf *a) { + if(a->red > 1.0f) a->red = 1.0f; + if(a->red < 0.0f) a->red = 0.0f; + if(a->green > 1.0f) a->green = 1.0f; + if(a->green < 0.0f) a->green = 0.0f; + if(a->blue > 1.0f) a->blue = 1.0f; + if(a->blue < 0.0f) a->blue = 0.0f; + if(a->alpha > 1.0f) a->alpha = 1.0f; + if(a->alpha < 0.0f) a->alpha = 0.0f; +} inline void convColor(RGBA *i, RGBAf *f){ int32 c; @@ -467,6 +494,7 @@ enum CoreModuleID { ID_NAMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x00), ID_FRAMEMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x03), + ID_TEXTUREMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x08), }; #define ECODE(c, s) c, diff --git a/src/rwengine.h b/src/rwengine.h index 42af5f5..539c242 100755 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -135,11 +135,6 @@ struct Engine Texture *imtexture; LinkList frameDirtyList; - TexDictionary *currentTexDictionary; - // load textures from files - bool32 loadTextures; - // create dummy textures to store just names - bool32 makeDummies; // Dynamically allocated because of plugins Driver *driver[NUM_PLATFORMS]; Device device; @@ -170,6 +165,9 @@ inline void SetRenderState(int32 state, uint32 value){ inline uint32 GetRenderState(int32 state){ return engine->device.getRenderState(state); } +inline float32 GetNearZ(void) { return engine->device.zNear; } +inline float32 GetFarZ(void) { return engine->device.zNear; } + // These must be macros because we might want to pass __FILE__ and __LINE__ later #define rwMalloc(s, h) rw::Engine::memfuncs.rwmalloc(s,h) #define rwMallocT(t, s, h) (t*)rw::Engine::memfuncs.rwmalloc((s)*sizeof(t),h) diff --git a/src/rwobjects.h b/src/rwobjects.h index 89f12fb..d3ad3d3 100755 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -137,8 +137,7 @@ struct Frame void purgeClone(void); #ifndef RWPUBLIC - static void *_open(void*, int32, int32); - static void *_close(void*, int32, int32); + static void registerModule(void); #endif static void syncDirty(void); }; @@ -282,30 +281,6 @@ struct TexDictionary; struct Texture { - PLUGINBASE - Raster *raster; - TexDictionary *dict; - LLLink inDict; - char name[32]; - char mask[32]; - uint32 filterAddressing; // VVVVUUUU FFFFFFFF - int32 refCount; - - static Texture *create(Raster *raster); - void destroy(void); - static Texture *fromDict(LLLink *lnk){ - return LLLinkGetData(lnk, Texture, inDict); } - 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); - enum FilterMode { NEAREST = 1, LINEAR, @@ -320,6 +295,40 @@ struct Texture CLAMP, BORDER }; + + PLUGINBASE + Raster *raster; + TexDictionary *dict; + LLLink inDict; + char name[32]; + char mask[32]; + uint32 filterAddressing; // VVVVUUUU FFFFFFFF + int32 refCount; + + static Texture *create(Raster *raster); + 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); + +#ifndef RWPUBLIC + static void registerModule(void); +#endif }; @@ -624,12 +633,15 @@ struct Camera V3d frustumCorners[8]; BBox frustumBoundBox; + Raster *frameBuffer; + Raster *zBuffer; + // clump link handled by plugin in RW Clump *clump; LLLink inClump; // world extension - /* 3 unknowns */ + /* RW: frustum sectors, space, position */ World *world; ObjectWithFrame::Sync originalSync; void (*originalBeginUpdate)(Camera*); diff --git a/src/texture.cpp b/src/texture.cpp index e2d7cd0..33eb082 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -15,19 +15,54 @@ #include "d3d/rwd3d8.h" #include "d3d/rwd3d9.h" -#ifdef _WIN32 -/* srsly? */ -#define strdup _strdup -#endif - #define PLUGIN_ID 0 +// TODO: maintain a global list of all texdicts + namespace rw { PluginList TexDictionary::s_plglist = { sizeof(TexDictionary), sizeof(TexDictionary), nil, nil }; PluginList Texture::s_plglist = { sizeof(Texture), sizeof(Texture), nil, nil }; PluginList Raster::s_plglist = { sizeof(Raster), sizeof(Raster), nil, nil }; +struct TextureGlobals +{ + TexDictionary *initialTexDict; + TexDictionary *currentTexDict; + // load textures from files + bool32 loadTextures; + // create dummy textures to store just names + bool32 makeDummies; +}; +int32 textureModuleOffset; + +#define TEXTUREGLOBAL(v) (PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->v) + +static void* +textureOpen(void *object, int32 offset, int32 size) +{ + TexDictionary *texdict; + textureModuleOffset = offset; + texdict = TexDictionary::create(); + TEXTUREGLOBAL(initialTexDict) = texdict; + TexDictionary::setCurrent(texdict); + TEXTUREGLOBAL(loadTextures) = 1; + TEXTUREGLOBAL(makeDummies) = 0; + return object; +} +static void* +textureClose(void *object, int32 offset, int32 size) +{ + TEXTUREGLOBAL(initialTexDict)->destroy(); + return object; +} + +void +Texture::registerModule(void) +{ + Engine::registerPlugin(sizeof(TextureGlobals), ID_TEXTUREMODULE, textureOpen, textureClose); +} + // // TexDictionary // @@ -49,8 +84,8 @@ TexDictionary::create(void) void TexDictionary::destroy(void) { - if(engine->currentTexDictionary == this) - engine->currentTexDictionary = nil; + if(TEXTUREGLOBAL(currentTexDict) == this) + TEXTUREGLOBAL(currentTexDict) = nil; FORLIST(lnk, this->textures) Texture::fromDict(lnk)->destroy(); s_plglist.destruct(this); @@ -145,13 +180,13 @@ TexDictionary::streamGetSize(void) void TexDictionary::setCurrent(TexDictionary *txd) { - engine->currentTexDictionary = txd; + PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->currentTexDict = txd; } TexDictionary* TexDictionary::getCurrent(void) { - return engine->currentTexDictionary; + return PLUGINOFFSET(TextureGlobals, engine, textureModuleOffset)->currentTexDict; } // @@ -200,8 +235,8 @@ Texture::destroy(void) static Texture* defaultFindCB(const char *name) { - if(engine->currentTexDictionary) - return engine->currentTexDictionary->find(name); + if(TEXTUREGLOBAL(currentTexDict)) + return TEXTUREGLOBAL(currentTexDict)->find(name); // TODO: RW searches *all* TXDs otherwise return nil; } @@ -238,11 +273,11 @@ Texture::read(const char *name, const char *mask) tex->refCount++; return tex; } - if(engine->loadTextures){ + if(TEXTUREGLOBAL(loadTextures)){ tex = Texture::readCB(name, mask); if(tex == nil) goto dummytex; - }else dummytex: if(engine->makeDummies){ + }else dummytex: if(TEXTUREGLOBAL(makeDummies)){ tex = Texture::create(nil); if(tex == nil) return nil; @@ -252,10 +287,10 @@ Texture::read(const char *name, const char *mask) raster = Raster::create(0, 0, 0, Raster::DONTALLOCATE); tex->raster = raster; } - if(tex && engine->currentTexDictionary){ + if(tex && TEXTUREGLOBAL(currentTexDict)){ if(tex->dict) tex->inDict.remove(); - engine->currentTexDictionary->add(tex); + TEXTUREGLOBAL(currentTexDict)->add(tex); } return tex; } diff --git a/tools/clumpview/camera.cpp b/tools/clumpview/camera.cpp index 27185aa..cf45f5f 100644 --- a/tools/clumpview/camera.cpp +++ b/tools/clumpview/camera.cpp @@ -13,8 +13,8 @@ void Camera::update(void) { if(m_rwcam){ - m_rwcam->nearPlane = m_near; - m_rwcam->farPlane = m_far; + m_rwcam->setNearPlane(m_near); + m_rwcam->setFarPlane(m_far); m_rwcam->setFOV(m_fov, m_aspectRatio); rw::Frame *f = m_rwcam->getFrame(); diff --git a/tools/clumpview/main.cpp b/tools/clumpview/main.cpp index c56eab0..7c5905c 100644 --- a/tools/clumpview/main.cpp +++ b/tools/clumpview/main.cpp @@ -5,10 +5,16 @@ rw::V3d zero = { 0.0f, 0.0f, 0.0f }; Camera *camera; -rw::Clump *clump; -rw::World *world; +struct SceneGlobals { + rw::World *world; + rw::Camera *camera; + rw::Clump *clump; +} Scene; +rw::Texture *tex; rw::EngineStartParams engineStartParams; +void tlTest(rw::Clump *clump); + void Init(void) { @@ -152,6 +158,8 @@ InitRW(void) if(!sk::InitRW()) return false; + tex = rw::Texture::read("maze", nil); + char *filename = "teapot.dff"; if(sk::args.argc > 1) filename = sk::args.argv[1]; @@ -161,31 +169,43 @@ InitRW(void) return false; } rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL); - clump = rw::Clump::streamRead(&in); - assert(clump); + Scene.clump = rw::Clump::streamRead(&in); + assert(Scene.clump); in.close(); - clump->getFrame()->translate(&zero, rw::COMBINEREPLACE); + // TEST - Set texture to the all materials of the clump + FORLIST(lnk, Scene.clump->atomics){ + rw::Atomic *a = rw::Atomic::fromClump(lnk); + for(int i = 0; i < a->geometry->matList.numMaterials; i++) + a->geometry->matList.materials[i]->setTexture(tex); + } - dumpUserData(clump); - setupClump(clump); + Scene.clump->getFrame()->translate(&zero, rw::COMBINEREPLACE); - world = rw::World::create(); + dumpUserData(Scene.clump); + setupClump(Scene.clump); + + Scene.world = rw::World::create(); rw::Light *ambient = rw::Light::create(rw::Light::AMBIENT); ambient->setColor(0.2f, 0.2f, 0.2f); - world->addLight(ambient); + Scene.world->addLight(ambient); rw::V3d xaxis = { 1.0f, 0.0f, 0.0f }; rw::Light *direct = rw::Light::create(rw::Light::DIRECTIONAL); direct->setColor(0.8f, 0.8f, 0.8f); direct->setFrame(rw::Frame::create()); direct->getFrame()->rotate(&xaxis, 180.0f, rw::COMBINEREPLACE); - world->addLight(direct); + Scene.world->addLight(direct); camera = new Camera; - camera->m_rwcam = rw::Camera::create(); - camera->m_rwcam->setFrame(rw::Frame::create()); + Scene.camera = rw::Camera::create(); + camera->m_rwcam = Scene.camera; + Scene.camera->frameBuffer = + rw::Raster::create(sk::globals.width, sk::globals.height, 0, rw::Raster::CAMERA); + Scene.camera->zBuffer = + rw::Raster::create(sk::globals.width, sk::globals.height, 0, rw::Raster::ZBUFFER); + Scene.camera->setFrame(rw::Frame::create()); camera->m_aspectRatio = 640.0f/480.0f; camera->m_near = 0.1f; camera->m_far = 450.0f; @@ -196,7 +216,7 @@ InitRW(void) // camera->setPosition(Vec3(0.0f, -1.0f, 3.0f)); camera->update(); - world->addCamera(camera->m_rwcam); + Scene.world->addCamera(camera->m_rwcam); return true; } @@ -204,15 +224,37 @@ InitRW(void) void im2dtest(void) { - static rw::gl3::Im2DVertex verts[] = { - { -0.5, -0.5, 0.0, 255, 0, 0, 255, 0.0, 0.0 }, - { 0.5, -0.5, 0.0, 0, 255, 0, 255, 0.0, 0.0 }, - { -0.5, 0.5, 0.0, 0, 0, 255, 255, 0.0, 0.0 }, - { 0.5, 0.5, 0.0, 0, 255, 255, 255, 0.0, 0.0 }, + using namespace rw::RWDEVICE; + int i; + static struct + { + float x, y; + rw::uint8 r, g, b, a; + float u, v; + } vs[4] = { + { 0.0f, 0.0f, 255, 0, 0, 128, 0.0f, 0.0f }, + { 640.0f, 0.0f, 0, 255, 0, 128, 1.0f, 0.0f }, + { 0.0f, 480.0f, 0, 0, 255, 128, 0.0f, 1.0f }, + { 640.0f, 480.0f, 0, 255, 255, 128, 1.0f, 1.0f }, }; + static Im2DVertex verts[4]; static short indices[] = { 0, 1, 2, 3 }; + + for(i = 0; i < 4; i++){ + verts[i].setScreenX(vs[i].x); + verts[i].setScreenY(vs[i].y); + verts[i].setScreenZ(rw::GetNearZ()); + verts[i].setCameraZ(Scene.camera->nearPlane); + verts[i].setRecipCameraZ(1.0f/Scene.camera->nearPlane); + verts[i].setColor(vs[i].r, vs[i].g, vs[i].b, vs[i].a); + verts[i].setU(vs[i].u); + verts[i].setV(vs[i].v); + } + + rw::engine->imtexture = tex; + rw::SetRenderState(rw::VERTEXALPHA, 1); rw::engine->device.im2DRenderIndexedPrimitive(rw::PRIMTYPETRISTRIP, &verts, 4, &indices, 4); } @@ -225,8 +267,9 @@ Draw(float timeDelta) camera->update(); camera->m_rwcam->beginUpdate(); - clump->render(); + Scene.clump->render(); im2dtest(); +// tlTest(Scene.clump); camera->m_rwcam->endUpdate(); camera->m_rwcam->showRaster(); diff --git a/tools/clumpview/maze.tga b/tools/clumpview/maze.tga new file mode 100644 index 0000000000000000000000000000000000000000..4714c424fafd622d3898cb4d6cec18e673a88e9d GIT binary patch literal 49196 zcmeH}TaG0)5JX$7f=@O8y8vk<1QIW?9Ci+aim^(kl}C1k-F5H9Js(}+$arMVPrto= z^>+OH_4e<-ufO?w|LhCw3+xN*3+xN*3+xO0?=SG*A4p$*;T~U}m;ZjfTx?W9Toz+s z*TL7z#YPpxNiha?9ell9Y*ay<6k}l5!Pm>hMiswg=Y5^Cr+comiF2j(L}x3{p7(Xmp6L*d*0VMd%EX3 zn>bfmPjt5O?0H}3?CGBCY~oyLk?0U6J`C2i&cbR4Ce9PJuxju@c4>W%kD*pRoH$R^ z!m2?p54Nd}53mkh>#RFFn>bI@!m2?p54Nd}53mkh>#RFFn>bI@!m2?p54Nd}53mkh z>#RFFn>bI@!fFb{;_zI@A_y?ag%#jBX9RV^q)(#tde7+W8&zzwX`-$A9PiKQ>>E{V zvT35N`t19kFOyu@wda)g->!A`z1#W4wa%V>&fl&A>+o#*`5VK|Vi<6p_QRYJ)Zhzj ziWLCcrpLz+i($YaXACzu&8qx)y8&hdeP1h=?H;!+`FL zVL;b93oAg^g00|?Cx!tLF~njR(48?1=vrrC1?XC^6-+!6ZPlme-E(^!s+q+3n$}h8 z*y;j3@7}7%p_)mYuW4Pij;$`x^X{#B9IBbb`I^>M>)7f7J@4MC$Dx`@oUdtJwT`VW z(DUxCdK{{m#QB=mRTEiQ4MCg>T4yl~xK0b_3J&#w$&ePqLvUTLJ9|mjf~_DTFgB5e z)euZtd5}9NS~yn_5g41u!fFU6tvtw`6D^!8hzN{LWMMS~lU5$&&WRSz6+{Ha5*AiN zFv(4{UecXiTe0q$uvKEudy<=Iy_-9`wqo5gVXMTR_arybdN+4=ZN<80!d8hr?@4Z= z^=|I$+KP40gsl>L-jm!!>)qVhwH5206IoadL6m<+Emmj{yR`S?VOr)q z(ICpV_v2$C3#%dMt=#HCw5ZV_%D4C9VOr)q(ICpV_v2$C3#%dMt=#HC zw5ZV_%D4C9BVl3n6foJ>wblBrO4us#k>8VjU0ZGKs)Vf)ANf7m*R|Ewu1eS{@sZz? zeO+5^?W%;W5+C_J+1Itz)=)Wwi4TLlON$zS-fAKXs|L}>VN)F+J`DCQEouOItBEYE z8blw5O?7(19$-{mgWckx#1wC;S3^kD&SDtwE-h*RqE!W*?I+)}>rWUO#h?8Or>^hj_KBg9}Du|O}4D33Xndj}&-~qU6V|&W&aSO;UFB@$nZJ8( z!g{yF*|k-!tDLPo^LNipSnrlNySB=8m9v#+{_eR6>)jG(*H*c%8e%a#5u!Yt6Bbs0 zi8HhnoR|o!i4f)CoUpJ0Oq`*u;KW2&O@t^9=Y)k7VB!pI1t%uLY9d5=I43Nu0260u zD>yL`Rudu0!#QDL1(-NPTfvV{teW({-_<$Et+q=%U0WsQ@1C2m-fe|*;^|u7C1E`` zVZGG~=fu;szDvS-Zo+!270!vLYkil5_1uK@Rx6x`JTVN2@?aC_&dz$SYn>f(hE;+DcxSTzWf_I`YTb(m-q=Oov)&JJ~kRf8~T@5cvNhlw_EPI6uA z>`-S|H3*aTetdv+m}nE{B-gdh4t0iAgD`3D`Nwwdx#7Oj`AX}qaZWjZuS?v{=Q~&5 z`%34_th>fJ<@~)aaXX*yTz%t82}DFa&T!J$ok7!f`^kzJRYI73^(r?`Wc z#A-e~#3s(rR&c0~4Dxbl`1IrV-@W|<=1z +#include + +using namespace rw; + +// +// This is a test to implement T&L in software and render with Im2D + +#define MAX_LIGHTS 8 + +struct Directional { + V3d at; + RGBAf color; +}; +static Directional directionals[MAX_LIGHTS]; +static int32 numDirectionals; +static RGBAf ambLight; + +static void +enumLights(Matrix *lightmat) +{ + int32 n; + World *world; + + world = (World*)engine->currentWorld; + ambLight.red = 0.0; + ambLight.green = 0.0; + ambLight.blue = 0.0; + ambLight.alpha = 0.0; + numDirectionals = 0; + // only unpositioned lights right now + FORLIST(lnk, world->directionalLights){ + Light *l = Light::fromWorld(lnk); + if(l->getType() == Light::DIRECTIONAL){ + if(numDirectionals >= MAX_LIGHTS) + continue; + n = numDirectionals++; + V3d::transformVectors(&directionals[n].at, &l->getFrame()->getLTM()->at, 1, lightmat); + directionals[n].color = l->color; + directionals[n].color.alpha = 0.0f; + }else if(l->getType() == Light::AMBIENT){ + ambLight.red += l->color.red; + ambLight.green += l->color.green; + ambLight.blue += l->color.blue; + } + } +} + +static void +drawAtomic(Atomic *a) +{ + using namespace RWDEVICE; + Im2DVertex *im2dverts; + V3d *xvert; + Matrix xform; + Matrix lightmat; + Camera *cam = (Camera*)engine->currentCamera; + Geometry *g = a->geometry; + MeshHeader *mh = g->meshHeader; + Mesh *m = mh->getMeshes(); + int32 width = cam->frameBuffer->width; + int32 height = cam->frameBuffer->height; + RGBA *prelight; + V3d *normals; + TexCoords *texcoords; + + Matrix::mult(&xform, a->getFrame()->getLTM(), &cam->viewMatrix); + Matrix::invert(&lightmat, a->getFrame()->getLTM()); + + enumLights(&lightmat); + + xvert = rwNewT(V3d, g->numVertices, MEMDUR_FUNCTION); + im2dverts = rwNewT(Im2DVertex, g->numVertices, MEMDUR_FUNCTION); + + prelight = g->colors; + normals = g->morphTargets[0].normals; + texcoords = g->texCoords[0]; + + V3d::transformPoints(xvert, g->morphTargets[0].vertices, g->numVertices, &xform); + for(int32 i = 0; i < g->numVertices; i++){ + float32 recipZ = 1.0f/xvert[i].z; + + im2dverts[i].setScreenX(xvert[i].x * recipZ * width); + im2dverts[i].setScreenY((xvert[i].y * recipZ * height)); + im2dverts[i].setScreenZ(recipZ * cam->zScale + cam->zShift); + im2dverts[i].setCameraZ(xvert[i].z); + im2dverts[i].setRecipCameraZ(recipZ); + im2dverts[i].setColor(255, 0, 0, 255); + im2dverts[i].setU(texcoords[i].u); + im2dverts[i].setV(texcoords[i].v); + } + for(int32 i = 0; i < mh->numMeshes; i++){ + for(int32 j = 0; j < m[i].numIndices; j++){ + int32 idx = m[i].indices[j]; + RGBA col; + RGBAf colf, color; + if(prelight) + convColor(&color, &prelight[idx]); + else{ + color.red = color.green = color.blue = 0.0f; + color.alpha = 1.0f; + } + color = add(color, ambLight); + if(normals) + for(int32 k = 0; k < numDirectionals; k++){ + float32 f = dot(normals[idx], neg(directionals[k].at)); + if(f <= 0.0f) continue; + colf = scale(directionals[k].color, f); + color = add(color, colf); + } + convColor(&colf, &m[i].material->color); + color = modulate(color, colf); + clamp(&color); + convColor(&col, &color); + im2dverts[idx].setColor(col.red, col.green, col.blue, col.alpha); + } + + engine->imtexture = m[i].material->texture; + rw::engine->device.im2DRenderIndexedPrimitive(rw::PRIMTYPETRILIST, + im2dverts, g->numVertices, m[i].indices, m[i].numIndices); + } + + rwFree(xvert); + rwFree(im2dverts); +} + +void +tlTest(Clump *clump) +{ + FORLIST(lnk, clump->atomics){ + Atomic *a = Atomic::fromClump(lnk); + drawAtomic(a); + } +}