diff --git a/librw.sln b/librw.sln
new file mode 100644
index 0000000..4af86ec
--- /dev/null
+++ b/librw.sln
@@ -0,0 +1,60 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "librw", "librw.vcxproj", "{30552BB0-3B19-49A4-ABF4-87CF68AF9E38}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dumprwtree", "tools\dumprwtree\dumprwtree.vcxproj", "{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dffwrite", "tools\dffwrite\dffwrite.vcxproj", "{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}"
+ ProjectSection(ProjectDependencies) = postProject
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "insttest", "tools\insttest\insttest.vcxproj", "{2592ED29-F258-4949-AB45-7B873BF697F7}"
+ ProjectSection(ProjectDependencies) = postProject
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d9", "tools\d3d9\d3d9.vcxproj", "{E5D477C8-4CAF-43BF-B7E3-6689503D469F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug - null|Win32 = Debug - null|Win32
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Debug - null|Win32.Build.0 = Debug - null|Win32
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Debug|Win32.ActiveCfg = Debug|Win32
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Debug|Win32.Build.0 = Debug|Win32
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Release|Win32.ActiveCfg = Release|Win32
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}.Release|Win32.Build.0 = Release|Win32
+ {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
+ {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.ActiveCfg = Release|Win32
+ {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.Build.0 = Release|Win32
+ {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
+ {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.ActiveCfg = Release|Win32
+ {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.Build.0 = Release|Win32
+ {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
+ {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.Build.0 = Debug - null|Win32
+ {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32
+ {2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.Build.0 = Debug|Win32
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.ActiveCfg = Release|Win32
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/librw.vcxproj b/librw.vcxproj
new file mode 100644
index 0000000..15cb3ef
--- /dev/null
+++ b/librw.vcxproj
@@ -0,0 +1,127 @@
+
+
+
+
+ Debug - null
+ Win32
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {30552BB0-3B19-49A4-ABF4-87CF68AF9E38}
+ librw
+
+
+
+ StaticLibrary
+ true
+ v120_xp
+ MultiByte
+
+
+ StaticLibrary
+ true
+ v120_xp
+ MultiByte
+
+
+ StaticLibrary
+ false
+ v120_xp
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .lib
+
+
+ .lib
+
+
+ .lib
+
+
+
+ Level3
+ Disabled
+ true
+ _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)
+
+
+ true
+
+
+
+
+ Level3
+ Disabled
+ true
+ _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ _USING_V110_SDK71_;_CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rw.h b/rw.h
index d6e861e..8a98324 100644
--- a/rw.h
+++ b/rw.h
@@ -3,5 +3,6 @@
#include "src/rwpipeline.h"
#include "src/rwobjects.h"
#include "src/rwps2.h"
-#include "src/rwogl.h"
#include "src/rwxbox.h"
+#include "src/rwd3d9.h"
+#include "src/rwogl.h"
diff --git a/src/clump.cpp b/src/clump.cpp
index 11f0396..d857282 100644
--- a/src/clump.cpp
+++ b/src/clump.cpp
@@ -11,6 +11,8 @@
#include "rwobjects.h"
#include "rwps2.h"
#include "rwogl.h"
+#include "rwxbox.h"
+#include "rwd3d9.h"
using namespace std;
@@ -534,6 +536,10 @@ Atomic::init(void)
ps2::makeDefaultPipeline();
defaultPipelines[platformIdx[PLATFORM_OGL]] =
gl::makeDefaultPipeline();
+ defaultPipelines[platformIdx[PLATFORM_XBOX]] =
+ xbox::makeDefaultPipeline();
+ defaultPipelines[platformIdx[PLATFORM_D3D9]] =
+ d3d9::makeDefaultPipeline();
}
// Atomic Rights plugin
diff --git a/src/d3d9.cpp b/src/d3d9.cpp
new file mode 100644
index 0000000..f7118a2
--- /dev/null
+++ b/src/d3d9.cpp
@@ -0,0 +1,558 @@
+#include
+#include
+#include
+#include
+
+#include
+
+#include "rwbase.h"
+#include "rwplugin.h"
+#include "rwpipeline.h"
+#include "rwobjects.h"
+#include "rwd3d9.h"
+
+using namespace std;
+
+namespace rw {
+namespace d3d9 {
+
+#ifdef RW_D3D9
+IDirect3DDevice9 *device = NULL;
+#else
+enum {
+ D3DLOCK_NOSYSLOCK = 0, // ignored
+ D3DPOOL_MANAGED = 0, // ignored
+ D3DPT_TRIANGLELIST = 4,
+ D3DPT_TRIANGLESTRIP = 5,
+
+
+ D3DDECLTYPE_FLOAT1 = 0, // 1D float expanded to (value, 0., 0., 1.)
+ D3DDECLTYPE_FLOAT2 = 1, // 2D float expanded to (value, value, 0., 1.)
+ D3DDECLTYPE_FLOAT3 = 2, // 3D float expanded to (value, value, value, 1.)
+ D3DDECLTYPE_FLOAT4 = 3, // 4D float
+ D3DDECLTYPE_D3DCOLOR = 4, // 4D packed unsigned bytes mapped to 0. to 1. range
+ // Input is in D3DCOLOR format (ARGB) expanded to (R, G, B, A)
+ D3DDECLTYPE_UBYTE4 = 5, // 4D unsigned byte
+ D3DDECLTYPE_SHORT2 = 6, // 2D signed short expanded to (value, value, 0., 1.)
+ D3DDECLTYPE_SHORT4 = 7, // 4D signed short
+
+ D3DDECLTYPE_UBYTE4N = 8, // Each of 4 bytes is normalized by dividing to 255.0
+ D3DDECLTYPE_SHORT2N = 9, // 2D signed short normalized (v[0]/32767.0,v[1]/32767.0,0,1)
+ D3DDECLTYPE_SHORT4N = 10, // 4D signed short normalized (v[0]/32767.0,v[1]/32767.0,v[2]/32767.0,v[3]/32767.0)
+ D3DDECLTYPE_USHORT2N = 11, // 2D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,0,1)
+ D3DDECLTYPE_USHORT4N = 12, // 4D unsigned short normalized (v[0]/65535.0,v[1]/65535.0,v[2]/65535.0,v[3]/65535.0)
+ D3DDECLTYPE_UDEC3 = 13, // 3D unsigned 10 10 10 format expanded to (value, value, value, 1)
+ D3DDECLTYPE_DEC3N = 14, // 3D signed 10 10 10 format normalized and expanded to (v[0]/511.0, v[1]/511.0, v[2]/511.0, 1)
+ D3DDECLTYPE_FLOAT16_2 = 15, // Two 16-bit floating point values, expanded to (value, value, 0, 1)
+ D3DDECLTYPE_FLOAT16_4 = 16, // Four 16-bit floating point values
+ D3DDECLTYPE_UNUSED = 17, // When the type field in a decl is unused.
+
+
+ D3DDECLMETHOD_DEFAULT = 0,
+
+
+ D3DDECLUSAGE_POSITION = 0,
+ D3DDECLUSAGE_BLENDWEIGHT, // 1
+ D3DDECLUSAGE_BLENDINDICES, // 2
+ D3DDECLUSAGE_NORMAL, // 3
+ D3DDECLUSAGE_PSIZE, // 4
+ D3DDECLUSAGE_TEXCOORD, // 5
+ D3DDECLUSAGE_TANGENT, // 6
+ D3DDECLUSAGE_BINORMAL, // 7
+ D3DDECLUSAGE_TESSFACTOR, // 8
+ D3DDECLUSAGE_POSITIONT, // 9
+ D3DDECLUSAGE_COLOR, // 10
+ D3DDECLUSAGE_FOG, // 11
+ D3DDECLUSAGE_DEPTH, // 12
+ D3DDECLUSAGE_SAMPLE, // 13
+};
+#define D3DDECL_END() {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0}
+#define D3DCOLOR_ARGB(a,r,g,b) \
+ ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
+#endif
+
+int vertFormatMap[] = {
+ -1, VERT_FLOAT2, VERT_FLOAT3, -1, VERT_ARGB
+};
+
+uint16*
+lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags)
+{
+#ifdef RW_D3D9
+ uint16 *indices;
+ IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
+ ibuf->Lock(offset, size, (void**)&indices, flags);
+ return indices;
+#else
+ return (uint16*)indexBuffer;
+#endif
+}
+
+void
+unlockIndices(void *indexBuffer)
+{
+#ifdef RW_D3D9
+ IDirect3DIndexBuffer9 *ibuf = (IDirect3DIndexBuffer9*)indexBuffer;
+ ibuf->Unlock();
+#endif
+}
+
+uint8*
+lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags)
+{
+#ifdef RW_D3D9
+ uint8 *verts;
+ IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
+ vertbuf->Lock(offset, size, (void**)&verts, flags);
+ return verts;
+#else
+ return (uint8*)vertexBuffer;
+#endif
+}
+
+void
+unlockVertices(void *vertexBuffer)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexBuffer9 *vertbuf = (IDirect3DVertexBuffer9*)vertexBuffer;
+ vertbuf->Unlock();
+#endif
+}
+
+void*
+createVertexDeclaration(VertexElement *elements)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexDeclaration9 *decl = 0;
+ device->CreateVertexDeclaration((D3DVERTEXELEMENT9*)elements, &decl);
+ return decl;
+#else
+ int n = 0;
+ VertexElement *e = (VertexElement*)elements;
+ while(e[n++].stream != 0xFF)
+ ;
+ e = new VertexElement[n];
+ memcpy(e, elements, n*sizeof(VertexElement));
+ return e;
+#endif
+}
+
+uint32
+getDeclaration(void *declaration, VertexElement *elements)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexDeclaration9 *decl = (IDirect3DVertexDeclaration9*)declaration;
+ UINT numElt;
+ decl->GetDeclaration((D3DVERTEXELEMENT9*)elements, &numElt);
+ return numElt;
+#else
+ int n = 0;
+ VertexElement *e = (VertexElement*)declaration;
+ while(e[n++].stream != 0xFF)
+ ;
+ if(elements)
+ memcpy(elements, declaration, n*sizeof(VertexElement));
+ return n;
+#endif
+}
+
+void*
+createIndexBuffer(uint32 length)
+{
+#ifdef RW_D3D9
+ IDirect3DIndexBuffer9 *ibuf;
+ device->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0);
+ return ibuf;
+#else
+ return new uint8[length];
+#endif
+}
+
+void*
+createVertexBuffer(uint32 length, int32 pool)
+{
+#ifdef RW_D3D9
+ IDirect3DVertexBuffer9 *vbuf;
+ device->CreateVertexBuffer(length, D3DUSAGE_WRITEONLY, 0, (D3DPOOL)pool, &vbuf, 0);
+ return vbuf;
+#else
+ return new uint8[length];
+#endif
+}
+
+void*
+destroyNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ assert(geometry->instData != NULL);
+ assert(geometry->instData->platform == PLATFORM_D3D9);
+ // TODO
+ InstanceDataHeader *header =
+ (InstanceDataHeader*)geometry->instData;
+ delete header;
+ return object;
+}
+
+void
+readNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ uint32 vers;
+ assert(findChunk(stream, ID_STRUCT, NULL, &vers));
+ assert(stream->readU32() == PLATFORM_D3D9);
+ InstanceDataHeader *header = new InstanceDataHeader;
+ geometry->instData = header;
+ header->platform = PLATFORM_D3D9;
+ int32 size = stream->readI32();
+ uint8 *data = new uint8[size];
+ stream->read(data, size);
+ uint8 *p = data;
+ header->serialNumber = *(uint32*)p; p += 4;
+ header->numMeshes = *(uint32*)p; p += 4;
+ header->indexBuffer = NULL; p += 4;
+ header->primType = *(uint32*)p; p += 4;
+ p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
+ header->useOffsets = *(bool32*)p; p += 4;
+ header->vertexDeclaration = NULL; p += 4;
+ header->totalNumIndex = *(uint32*)p; p += 4;
+ header->totalNumVertex = *(uint32*)p; p += 4;
+ header->inst = new InstanceData[header->numMeshes];
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ inst->numIndex = *(uint32*)p; p += 4;
+ inst->minVert = *(uint32*)p; p += 4;
+ uint32 matid = *(uint32*)p; p += 4;
+ inst->material = geometry->materialList[matid];
+ inst->vertexAlpha = *(bool32*)p; p += 4;
+ inst->vertexShader = NULL; p += 4;
+ inst->baseIndex = 0; p += 4;
+ inst->numVertices = *(uint32*)p; p += 4;
+ inst->startIndex = *(uint32*)p; p += 4;
+ inst->numPrimitives = *(uint32*)p; p += 4;
+ inst++;
+ }
+
+ VertexElement elements[10];
+ uint32 numDeclarations = stream->readU32();
+ stream->read(elements, numDeclarations*8);
+ header->vertexDeclaration = createVertexDeclaration(elements);
+
+ header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16));
+
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ stream->read(indices, 2*header->totalNumIndex);
+ unlockIndices(header->indexBuffer);
+
+ VertexStream *s;
+ p = data;
+ for(int i = 0; i < 2; i++){
+ stream->read(p, 16);
+ s = &header->vertexStream[i];
+ s->vertexBuffer = (void*)*(uint32*)p; p += 4;
+ s->offset = 0; p += 4;
+ s->stride = *(uint32*)p; p += 4;
+ s->geometryFlags = *(uint16*)p; p += 2;
+ s->managed = *p++;
+ s->dynamicLock = *p++;
+
+ if(s->vertexBuffer == NULL)
+ continue;
+ // TODO: unset managed flag when using morph targets.
+ // also uses different buffer type and locks differently
+ s->vertexBuffer = createVertexBuffer(s->stride*header->totalNumVertex, D3DPOOL_MANAGED);
+
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->read(verts, s->stride*header->totalNumVertex);
+ unlockVertices(s->vertexBuffer);
+ }
+
+ // TODO: somehow depends on number of streams used (baseIndex = minVert when more than one)
+ inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ inst->baseIndex = inst->minVert + header->vertexStream[0].offset / header->vertexStream[0].stride;
+ inst++;
+ }
+
+ delete[] data;
+}
+
+void
+writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ writeChunkHeader(stream, ID_STRUCT, len-12);
+ assert(geometry->instData != NULL);
+ assert(geometry->instData->platform == PLATFORM_D3D9);
+ stream->writeU32(PLATFORM_D3D9);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ int32 size = 64 + geometry->meshHeader->numMeshes*36;
+ uint8 *data = new uint8[size];
+ stream->writeI32(size);
+
+ uint8 *p = data;
+ *(uint32*)p = header->serialNumber; p += 4;
+ *(uint32*)p = header->numMeshes; p += 4;
+ p += 4; // skip index buffer
+ *(uint32*)p = header->primType; p += 4;
+ p += 16*2; // skip vertex streams, they're repeated with the vertex buffers
+ *(bool32*)p = header->useOffsets; p += 4;
+ p += 4; // skip vertex declaration
+ *(uint32*)p = header->totalNumIndex; p += 4;
+ *(uint32*)p = header->totalNumVertex; p += 4;
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ *(uint32*)p = inst->numIndex; p += 4;
+ *(uint32*)p = inst->minVert; p += 4;
+ int32 matid = findPointer(inst->material, (void**)geometry->materialList, geometry->numMaterials);
+ *(int32*)p = matid; p += 4;
+ *(bool32*)p = inst->vertexAlpha; p += 4;
+ *(uint32*)p = 0; p += 4; // vertex shader
+ *(uint32*)p = inst->baseIndex; p += 4; // not used but meh...
+ *(uint32*)p = inst->numVertices; p += 4;
+ *(uint32*)p = inst->startIndex; p += 4;
+ *(uint32*)p = inst->numPrimitives; p += 4;
+ inst++;
+ }
+ stream->write(data, size);
+
+ VertexElement elements[10];
+ uint32 numElt = getDeclaration(header->vertexDeclaration, elements);
+ stream->writeU32(numElt);
+ stream->write(elements, 8*numElt);
+
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ stream->write(indices, 2*header->totalNumIndex);
+ unlockIndices(header->indexBuffer);
+
+ VertexStream *s;
+ for(int i = 0; i < 2; i++){
+ s = &header->vertexStream[i];
+ p = data;
+ *(uint32*)p = s->vertexBuffer ? 0xbadeaffe : 0; p += 4;
+ *(uint32*)p = s->offset; p += 4;
+ *(uint32*)p = s->stride; p += 4;
+ *(uint16*)p = s->geometryFlags; p += 2;
+ *p++ = s->managed;
+ *p++ = s->dynamicLock;
+ stream->write(data, 16);
+
+ if(s->vertexBuffer == NULL)
+ continue;
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ stream->write(verts, s->stride*header->totalNumVertex);
+ unlockVertices(s->vertexBuffer);
+ }
+
+ delete[] data;
+}
+
+int32
+getSizeNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ assert(geometry->instData != NULL);
+ assert(geometry->instData->platform == PLATFORM_D3D9);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ int32 size = 12 + 4 + 4 + 64 + header->numMeshes*36;
+ uint32 numElt = getDeclaration(header->vertexDeclaration, NULL);
+ size += 4 + numElt*8;
+ size += 2*header->totalNumIndex;
+ size += 0x10 + header->vertexStream[0].stride*header->totalNumVertex;
+ size += 0x10 + header->vertexStream[1].stride*header->totalNumVertex;
+ return size;
+}
+
+void
+registerNativeDataPlugin(void)
+{
+ Geometry::registerPlugin(0, ID_NATIVEDATA,
+ NULL, destroyNativeData, NULL);
+ Geometry::registerPluginStream(ID_NATIVEDATA,
+ readNativeData,
+ writeNativeData,
+ getSizeNativeData);
+}
+
+ObjPipeline::ObjPipeline(uint32 platform)
+ : rw::ObjPipeline(platform),
+ instanceCB(NULL), uninstanceCB(NULL) { }
+
+void
+ObjPipeline::instance(Atomic *atomic)
+{
+ Geometry *geo = atomic->geometry;
+ if(geo->geoflags & Geometry::NATIVE)
+ return;
+ geo->geoflags |= Geometry::NATIVE;
+ InstanceDataHeader *header = new InstanceDataHeader;
+ MeshHeader *meshh = geo->meshHeader;
+ geo->instData = header;
+ header->platform = PLATFORM_D3D9;
+
+ header->serialNumber = 0;
+ header->numMeshes = meshh->numMeshes;
+ header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
+ header->useOffsets = 0;
+ header->totalNumVertex = geo->numVertices;
+ header->totalNumIndex = meshh->totalIndices;
+ header->inst = new InstanceData[header->numMeshes];
+
+ header->indexBuffer = createIndexBuffer(header->totalNumIndex*sizeof(uint16));
+
+ uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0);
+ InstanceData *inst = header->inst;
+ Mesh *mesh = meshh->mesh;
+ uint32 startindex = 0;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
+ &inst->minVert, &inst->numVertices);
+ inst->numIndex = mesh->numIndices;
+ inst->material = mesh->material;
+ inst->vertexAlpha = 0;
+ inst->vertexShader = NULL;
+ inst->baseIndex = inst->minVert;
+ inst->startIndex = startindex;
+ inst->numPrimitives = header->primType == D3DPT_TRIANGLESTRIP ? inst->numIndex-2 : inst->numIndex/3;
+ if(inst->minVert == 0)
+ memcpy(&indices[inst->startIndex], mesh->indices, inst->numIndex*sizeof(uint16));
+ else
+ for(uint32 j = 0; j < inst->numIndex; j++)
+ indices[inst->startIndex+j] = mesh->indices[j]-inst->minVert;
+ startindex += inst->numIndex;
+ mesh++;
+ inst++;
+ }
+ unlockIndices(header->indexBuffer);
+
+ VertexStream *s;
+ for(int i = 0; i < 2; i++){
+ s = &header->vertexStream[i];
+ s->vertexBuffer = NULL;
+ s->offset = 0;
+ s->stride = 0;
+ s->geometryFlags = 0;
+ s->managed = 0;
+ s->dynamicLock = 0;
+ }
+
+ this->instanceCB(geo, header);
+}
+
+void
+ObjPipeline::uninstance(Atomic *atomic)
+{
+ assert(0 && "can't uninstance");
+}
+
+void
+defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ VertexElement dcl[6];
+
+ VertexStream *s = &header->vertexStream[0];
+ s->offset = 0;
+ s->managed = 1;
+ s->geometryFlags = 0;
+ s->dynamicLock = 0;
+
+ int i = 0;
+ dcl[i++] = {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0};
+ uint32 stride = 12;
+ s->geometryFlags |= 0x2;
+
+ bool isPrelit = (geo->geoflags & Geometry::PRELIT) != 0;
+ if(isPrelit){
+ dcl[i++] = {0, stride, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0};
+ s->geometryFlags |= 0x8;
+ stride += 4;
+ }
+
+ bool isTextured = (geo->geoflags & (Geometry::TEXTURED | Geometry::TEXTURED2)) != 0;
+ if(isTextured){
+ dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0};
+ s->geometryFlags |= 0x10;
+ stride += 8;
+ }
+
+ bool hasNormals = (geo->geoflags & Geometry::NORMALS) != 0;
+ if(hasNormals){
+ dcl[i++] = {0, stride, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0};
+ s->geometryFlags |= 0x4;
+ stride += 12;
+ }
+ dcl[i] = D3DDECL_END();
+ header->vertexStream[0].stride = stride;
+
+ header->vertexDeclaration = createVertexDeclaration((VertexElement*)dcl);
+
+ s->vertexBuffer = createVertexBuffer(header->totalNumVertex*s->stride, D3DPOOL_MANAGED);
+
+ uint8 *verts = lockVertices(s->vertexBuffer, 0, 0, D3DLOCK_NOSYSLOCK);
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_POSITION || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].vertices,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+
+ if(isPrelit){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_COLOR || dcl[i].usageIndex != 0; i++)
+ ;
+ instColor(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->colors,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ if(isTextured){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_TEXCOORD || dcl[i].usageIndex != 0; i++)
+ ;
+ instV2d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->texCoords[0],
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+
+ if(hasNormals){
+ for(i = 0; dcl[i].usage != D3DDECLUSAGE_NORMAL || dcl[i].usageIndex != 0; i++)
+ ;
+ instV3d(vertFormatMap[dcl[i].type], verts + dcl[i].offset,
+ geo->morphTargets[0].normals,
+ header->totalNumVertex,
+ header->vertexStream[dcl[i].stream].stride);
+ }
+ unlockVertices(s->vertexBuffer);
+}
+
+ObjPipeline*
+makeDefaultPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
+ pipe->instanceCB = defaultInstanceCB;
+ return pipe;
+}
+
+ObjPipeline*
+makeSkinPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->pluginID = ID_SKIN;
+ pipe->pluginData = 1;
+ return pipe;
+}
+
+ObjPipeline*
+makeMatFXPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_D3D9);
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->pluginID = ID_MATFX;
+ pipe->pluginData = 0;
+ return pipe;
+}
+
+}
+}
diff --git a/src/image.cpp b/src/image.cpp
index 1a59e57..c60820a 100755
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -223,7 +223,7 @@ Image::setSearchPath(const char *path)
::free(searchPaths);
numSearchPaths = 0;
if(path)
- searchPaths = p = strdup(path);
+ searchPaths = p = _strdup(path);
else{
searchPaths = NULL;
return;
@@ -258,7 +258,7 @@ Image::getFilename(const char *name)
if(f){
fclose(f);
printf("found %s\n", name);
- return strdup(name);
+ return _strdup(name);
}
return NULL;
}else
diff --git a/src/ogl.cpp b/src/ogl.cpp
index b89a0a3..2a1f7fd 100644
--- a/src/ogl.cpp
+++ b/src/ogl.cpp
@@ -54,74 +54,51 @@ printAttribInfo(AttribDesc *attribs, int n)
}
*/
-void*
-destroyNativeData(void *object, int32, int32)
+#ifdef RW_OPENGL
+void
+uploadGeo(Geometry *geo)
{
- Geometry *geometry = (Geometry*)object;
- assert(geometry->instData->platform == PLATFORM_OGL);
- InstanceDataHeader *header =
- (InstanceDataHeader*)geometry->instData;
- delete[] header->attribs;
- delete[] header->data;
- delete header;
- return object;
+ InstanceDataHeader *inst = (InstanceDataHeader*)geo->instData;
+ MeshHeader *meshHeader = geo->meshHeader;
+
+ glGenBuffers(1, &inst->vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, inst->vbo);
+ glBufferData(GL_ARRAY_BUFFER, inst->dataSize,
+ inst->data, GL_STATIC_DRAW);
+
+ glGenBuffers(1, &inst->ibo);
+ glBindBuffer(GL_ARRAY_BUFFER, inst->ibo);
+ glBufferData(GL_ARRAY_BUFFER, meshHeader->totalIndices*2,
+ 0, GL_STATIC_DRAW);
+ GLintptr offset = 0;
+ for(uint32 i = 0; i < meshHeader->numMeshes; i++){
+ Mesh *mesh = &meshHeader->mesh[i];
+ glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2,
+ mesh->indices);
+ offset += mesh->numIndices*2;
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void
-readNativeData(Stream *stream, int32, void *object, int32, int32)
+setAttribPointers(InstanceDataHeader *inst)
{
- Geometry *geometry = (Geometry*)object;
- InstanceDataHeader *header = new InstanceDataHeader;
- geometry->instData = header;
- header->platform = PLATFORM_OGL;
- header->vbo = 0;
- header->ibo = 0;
- header->numAttribs = stream->readU32();
- header->attribs = new AttribDesc[header->numAttribs];
- stream->read(header->attribs,
- header->numAttribs*sizeof(AttribDesc));
- header->dataSize = header->attribs[0].stride*geometry->numVertices;
- header->data = new uint8[header->dataSize];
- stream->read(header->data, header->dataSize);
+ static GLenum attribType[] = {
+ GL_FLOAT,
+ GL_BYTE, GL_UNSIGNED_BYTE,
+ GL_SHORT, GL_UNSIGNED_SHORT
+ };
+ for(int32 i = 0; i < inst->numAttribs; i++){
+ AttribDesc *a = &inst->attribs[i];
+ glEnableVertexAttribArray(a->index);
+ glVertexAttribPointer(a->index, a->size, attribType[a->type],
+ a->normalized, a->stride,
+ (void*)(uint64)a->offset);
+ }
}
+#endif
void
-printPipeinfo(Atomic *a)
-{
- Geometry *g = a->geometry;
- if(g->instData == NULL || g->instData->platform != PLATFORM_OGL)
- return;
- int32 plgid = 0;
- if(a->pipeline)
- plgid = a->pipeline->pluginID;
- printf("%s %x: ", debugFile, plgid);
- InstanceDataHeader *h = (InstanceDataHeader*)g->instData;
- for(int i = 0; i < h->numAttribs; i++)
- printf("%x(%x) ", h->attribs[i].index, h->attribs[i].type);
- printf("\n");
-}
-
-void
-writeNativeData(Stream *stream, int32, void *object, int32, int32)
-{
- Geometry *geometry = (Geometry*)object;
- assert(geometry->instData->platform == PLATFORM_OGL);
- InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
- stream->writeU32(header->numAttribs);
- stream->write(header->attribs, header->numAttribs*sizeof(AttribDesc));
- stream->write(header->data, header->dataSize);
-}
-
-int32
-getSizeNativeData(void *object, int32, int32)
-{
- Geometry *geometry = (Geometry*)object;
- assert(geometry->instData->platform == PLATFORM_OGL);
- InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
- return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
-}
-
-static void
packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
{
int8 *i8dst;
@@ -175,6 +152,138 @@ packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale=1.0f)
}
}
+void
+unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
+{
+ int8 *i8src;
+ uint16 *u16src;
+ int16 *i16src;
+
+ switch(a->type){
+ case 0: // float
+ memcpy(dst, src, a->size*4);
+ break;
+
+ // TODO: maybe have loop inside if?
+ case 1: // byte
+ i8src = (int8*)src;
+ for(int i = 0; i < a->size; i++){
+ if(!a->normalized)
+ dst[i] = i8src[i]/scale;
+ else
+ dst[i] = i8src[i]/127.0f;
+ }
+ break;
+
+ case 2: // ubyte
+ for(int i = 0; i < a->size; i++){
+ if(!a->normalized)
+ dst[i] = src[i]/scale;
+ else
+ dst[i] = src[i]/255.0f;
+ }
+ break;
+
+ case 3: // short
+ i16src = (int16*)src;
+ for(int i = 0; i < a->size; i++){
+ if(!a->normalized)
+ dst[i] = i16src[i]/scale;
+ else
+ dst[i] = i16src[i]/32767.0f;
+ }
+ break;
+
+ case 4: // ushort
+ u16src = (uint16*)src;
+ for(int i = 0; i < a->size; i++){
+ if(!a->normalized)
+ dst[i] = u16src[i]/scale;
+ else
+ dst[i] = u16src[i]/65435.0f;
+ }
+ break;
+ }
+}
+
+void*
+destroyNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ assert(geometry->instData->platform == PLATFORM_OGL);
+ InstanceDataHeader *header =
+ (InstanceDataHeader*)geometry->instData;
+ delete[] header->attribs;
+ delete[] header->data;
+ delete header;
+ return object;
+}
+
+void
+readNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ InstanceDataHeader *header = new InstanceDataHeader;
+ geometry->instData = header;
+ header->platform = PLATFORM_OGL;
+ header->vbo = 0;
+ header->ibo = 0;
+ header->numAttribs = stream->readU32();
+ header->attribs = new AttribDesc[header->numAttribs];
+ stream->read(header->attribs,
+ header->numAttribs*sizeof(AttribDesc));
+ header->dataSize = header->attribs[0].stride*geometry->numVertices;
+ header->data = new uint8[header->dataSize];
+ stream->read(header->data, header->dataSize);
+}
+
+void
+writeNativeData(Stream *stream, int32, void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ assert(geometry->instData->platform == PLATFORM_OGL);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ stream->writeU32(header->numAttribs);
+ stream->write(header->attribs, header->numAttribs*sizeof(AttribDesc));
+ stream->write(header->data, header->dataSize);
+}
+
+int32
+getSizeNativeData(void *object, int32, int32)
+{
+ Geometry *geometry = (Geometry*)object;
+ assert(geometry->instData->platform == PLATFORM_OGL);
+ InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
+ return 4 + header->numAttribs*sizeof(AttribDesc) + header->dataSize;
+}
+
+void
+registerNativeDataPlugin(void)
+{
+ Geometry::registerPlugin(0, ID_NATIVEDATA,
+ NULL, destroyNativeData, NULL);
+ Geometry::registerPluginStream(ID_NATIVEDATA,
+ readNativeData,
+ writeNativeData,
+ getSizeNativeData);
+}
+
+void
+printPipeinfo(Atomic *a)
+{
+ Geometry *g = a->geometry;
+ if(g->instData == NULL || g->instData->platform != PLATFORM_OGL)
+ return;
+ int32 plgid = 0;
+ if(a->pipeline)
+ plgid = a->pipeline->pluginID;
+ printf("%s %x: ", debugFile, plgid);
+ InstanceDataHeader *h = (InstanceDataHeader*)g->instData;
+ for(int i = 0; i < h->numAttribs; i++)
+ printf("%x(%x) ", h->attribs[i].index, h->attribs[i].type);
+ printf("\n");
+}
+
ObjPipeline::ObjPipeline(uint32 platform)
: rw::ObjPipeline(platform), numCustomAttribs(0),
instanceCB(NULL), uninstanceCB(NULL) { }
@@ -305,60 +414,6 @@ ObjPipeline::instance(Atomic *atomic)
geo->geoflags |= Geometry::NATIVE;
}
-static void
-unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale=1.0f)
-{
- int8 *i8src;
- uint16 *u16src;
- int16 *i16src;
-
- switch(a->type){
- case 0: // float
- memcpy(dst, src, a->size*4);
- break;
-
- // TODO: maybe have loop inside if?
- case 1: // byte
- i8src = (int8*)src;
- for(int i = 0; i < a->size; i++){
- if(!a->normalized)
- dst[i] = i8src[i]/scale;
- else
- dst[i] = i8src[i]/127.0f;
- }
- break;
-
- case 2: // ubyte
- for(int i = 0; i < a->size; i++){
- if(!a->normalized)
- dst[i] = src[i]/scale;
- else
- dst[i] = src[i]/255.0f;
- }
- break;
-
- case 3: // short
- i16src = (int16*)src;
- for(int i = 0; i < a->size; i++){
- if(!a->normalized)
- dst[i] = i16src[i]/scale;
- else
- dst[i] = i16src[i]/32767.0f;
- }
- break;
-
- case 4: // ushort
- u16src = (uint16*)src;
- for(int i = 0; i < a->size; i++){
- if(!a->normalized)
- dst[i] = u16src[i]/scale;
- else
- dst[i] = u16src[i]/65435.0f;
- }
- break;
- }
-}
-
void
ObjPipeline::uninstance(Atomic *atomic)
{
@@ -438,70 +493,20 @@ makeDefaultPipeline(void)
return pipe;
}
-#ifdef RW_OPENGL
-void
-uploadGeo(Geometry *geo)
-{
- InstanceDataHeader *inst = (InstanceDataHeader*)geo->instData;
- MeshHeader *meshHeader = geo->meshHeader;
-
- glGenBuffers(1, &inst->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, inst->vbo);
- glBufferData(GL_ARRAY_BUFFER, inst->dataSize,
- inst->data, GL_STATIC_DRAW);
-
- glGenBuffers(1, &inst->ibo);
- glBindBuffer(GL_ARRAY_BUFFER, inst->ibo);
- glBufferData(GL_ARRAY_BUFFER, meshHeader->totalIndices*2,
- 0, GL_STATIC_DRAW);
- GLintptr offset = 0;
- for(uint32 i = 0; i < meshHeader->numMeshes; i++){
- Mesh *mesh = &meshHeader->mesh[i];
- glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2,
- mesh->indices);
- offset += mesh->numIndices*2;
- }
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-}
-
-void
-setAttribPointers(InstanceDataHeader *inst)
-{
- static GLenum attribType[] = {
- GL_FLOAT,
- GL_BYTE, GL_UNSIGNED_BYTE,
- GL_SHORT, GL_UNSIGNED_SHORT
- };
- for(int32 i = 0; i < inst->numAttribs; i++){
- AttribDesc *a = &inst->attribs[i];
- glEnableVertexAttribArray(a->index);
- glVertexAttribPointer(a->index, a->size, attribType[a->type],
- a->normalized, a->stride,
- (void*)(uint64)a->offset);
- }
-}
-#endif
-
// Skin
void
readNativeSkin(Stream *stream, int32, void *object, int32 offset)
{
- uint8 header[4];
uint32 vers;
Geometry *geometry = (Geometry*)object;
assert(findChunk(stream, ID_STRUCT, NULL, &vers));
assert(stream->readU32() == PLATFORM_OGL);
- stream->read(header, 4);
Skin *skin = new Skin;
*PLUGINOFFSET(Skin*, geometry, offset) = skin;
- skin->numBones = header[0];
-
- // should be 0
- skin->numUsedBones = header[1];
- skin->maxIndex = header[2];
- assert(skin->numUsedBones == 0);
- assert(skin->maxIndex == 0);
+ skin->numBones = stream->readI32();
+ skin->numUsedBones = 0;
+ skin->maxIndex = 0;
int32 size = skin->numBones*64 + 15;
uint8 *data = new uint8[size];
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index a05573c..09b74d7 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -54,4 +54,71 @@ ObjPipeline::render(Atomic*)
fprintf(stderr, "This pipeline can't render\n");
}
+// helper functions
+
+void
+findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices)
+{
+ uint32 min = 0xFFFFFFFF;
+ uint32 max = 0;
+ while(numIndices--){
+ if(*indices < min)
+ min = *indices;
+ if(*indices > max)
+ max = *indices;
+ indices++;
+ }
+ *minVert = min;
+ *numVertices = max - min + 1;
+}
+
+void
+instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride)
+{
+ if(type == VERT_FLOAT3)
+ for(uint32 i = 0; i < numVertices; i++){
+ memcpy(dst, src, 12);
+ dst += stride;
+ src += 3;
+ }
+ else if(type == VERT_COMPNORM)
+ for(uint32 i = 0; i < numVertices; i++){
+ uint32 n = ((((uint32)(src[2] * 511.0f)) & 0x3ff) << 22) |
+ ((((uint32)(src[1] * 1023.0f)) & 0x7ff) << 11) |
+ ((((uint32)(src[0] * 1023.0f)) & 0x7ff) << 0);
+ *(uint32*)dst = n;
+ dst += stride;
+ src += 3;
+ }
+ else
+ assert(0 && "unsupported instV3d type");
+}
+
+void
+instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride)
+{
+ assert(type == VERT_FLOAT2);
+ for(uint32 i = 0; i < numVertices; i++){
+ memcpy(dst, src, 8);
+ dst += stride;
+ src += 2;
+ }
+}
+
+bool32
+instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride)
+{
+ assert(type == VERT_ARGB);
+ bool32 hasAlpha = 0;
+ for(uint32 i = 0; i < numVertices; i++){
+ uint32 col = COLOR_ARGB(src[3], src[0], src[1], src[2]);
+ if(src[3] < 0xFF)
+ hasAlpha = 1;
+ memcpy(dst, &col, 4);
+ dst += stride;
+ src += 4;
+ }
+ return hasAlpha;
+}
+
}
diff --git a/src/plugins.cpp b/src/plugins.cpp
index 500929f..8f1f576 100644
--- a/src/plugins.cpp
+++ b/src/plugins.cpp
@@ -11,6 +11,7 @@
#include "rwobjects.h"
#include "rwps2.h"
#include "rwxbox.h"
+#include "rwd3d9.h"
#include "rwogl.h"
using namespace std;
@@ -261,6 +262,10 @@ destroyNativeData(void *object, int32 offset, int32 size)
return object;
if(geometry->instData->platform == PLATFORM_PS2)
return ps2::destroyNativeData(object, offset, size);
+ if(geometry->instData->platform == PLATFORM_XBOX)
+ return xbox::destroyNativeData(object, offset, size);
+ if(geometry->instData->platform == PLATFORM_D3D9)
+ return d3d9::destroyNativeData(object, offset, size);
if(geometry->instData->platform == PLATFORM_OGL)
return gl::destroyNativeData(object, offset, size);
return object;
@@ -278,13 +283,14 @@ readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
readChunkHeaderInfo(stream, &header);
if(header.type == ID_STRUCT &&
libraryIDPack(header.version, header.build) == libid){
- // must be PS2 or Xbox
platform = stream->readU32();
stream->seek(-16);
if(platform == PLATFORM_PS2)
ps2::readNativeData(stream, len, object, o, s);
else if(platform == PLATFORM_XBOX)
xbox::readNativeData(stream, len, object, o, s);
+ else if(platform == PLATFORM_D3D9)
+ d3d9::readNativeData(stream, len, object, o, s);
else{
fprintf(stderr, "unknown platform %d\n", platform);
stream->seek(len);
@@ -305,6 +311,8 @@ writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s)
ps2::writeNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_XBOX)
xbox::writeNativeData(stream, len, object, o, s);
+ else if(geometry->instData->platform == PLATFORM_D3D9)
+ d3d9::writeNativeData(stream, len, object, o, s);
else if(geometry->instData->platform == PLATFORM_OGL)
gl::writeNativeData(stream, len, object, o, s);
}
@@ -319,6 +327,8 @@ getSizeNativeData(void *object, int32 offset, int32 size)
return ps2::getSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_XBOX)
return xbox::getSizeNativeData(object, offset, size);
+ else if(geometry->instData->platform == PLATFORM_D3D9)
+ return d3d9::getSizeNativeData(object, offset, size);
else if(geometry->instData->platform == PLATFORM_OGL)
return gl::getSizeNativeData(object, offset, size);
return -1;
@@ -408,10 +418,10 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
skin->numBones = header[0];
// both values unused in/before 33002, used in/after 34003
+ // probably rw::version >= 0x34000
skin->numUsedBones = header[1];
skin->maxIndex = header[2];
- // probably rw::version >= 0x34000
bool oldFormat = skin->numUsedBones == 0;
skin->allocateData(geometry->numVertices);
@@ -490,6 +500,8 @@ getSizeSkin(void *object, int32 offset, int32)
return xbox::getSizeNativeSkin(object, offset);
if(geometry->instData->platform == PLATFORM_OGL)
return gl::getSizeNativeSkin(object, offset);
+ if(geometry->instData->platform == PLATFORM_D3D9)
+ return -1;
assert(0 && "unsupported native skin platform");
}
@@ -525,6 +537,10 @@ registerSkinPlugin(void)
ps2::makeSkinPipeline();
skinGlobals.pipelines[platformIdx[PLATFORM_OGL]] =
gl::makeSkinPipeline();
+ skinGlobals.pipelines[platformIdx[PLATFORM_XBOX]] =
+ xbox::makeSkinPipeline();
+ skinGlobals.pipelines[platformIdx[PLATFORM_D3D9]] =
+ d3d9::makeSkinPipeline();
skinGlobals.offset = Geometry::registerPlugin(sizeof(Skin*), ID_SKIN,
createSkin,
@@ -909,6 +925,10 @@ registerMatFXPlugin(void)
ps2::makeMatFXPipeline();
matFXGlobals.pipelines[platformIdx[PLATFORM_OGL]] =
gl::makeMatFXPipeline();
+ matFXGlobals.pipelines[platformIdx[PLATFORM_XBOX]] =
+ xbox::makeMatFXPipeline();
+ matFXGlobals.pipelines[platformIdx[PLATFORM_D3D9]] =
+ d3d9::makeMatFXPipeline();
matFXGlobals.atomicOffset =
Atomic::registerPlugin(sizeof(int32), ID_MATFX,
diff --git a/src/rwbase.cpp b/src/rwbase.cpp
index ace5979..1988076 100644
--- a/src/rwbase.cpp
+++ b/src/rwbase.cpp
@@ -20,6 +20,8 @@ int build = 0xFFFF;
int platform = PLATFORM_PS2;
#elif RW_OPENGL
int platform = PLATFORM_OGL;
+#elif RW_D3D9
+ int platform = PLATFORM_D3D9;
#else
int platform = PLATFORM_NULL;
#endif
diff --git a/src/rwd3d9.h b/src/rwd3d9.h
new file mode 100644
index 0000000..9a9b87a
--- /dev/null
+++ b/src/rwd3d9.h
@@ -0,0 +1,95 @@
+#ifdef RW_D3D9
+#include
+#endif
+
+namespace rw {
+namespace d3d9 {
+
+struct VertexElement
+{
+ uint16 stream;
+ uint16 offset;
+ uint8 type;
+ uint8 method;
+ uint8 usage;
+ uint8 usageIndex;
+};
+
+struct VertexStream
+{
+ void *vertexBuffer;
+ uint32 offset;
+ uint32 stride;
+ uint16 geometryFlags;
+ uint8 managed;
+ uint8 dynamicLock;
+};
+
+struct InstanceData
+{
+ uint32 numIndex;
+ uint32 minVert;
+ Material *material;
+ bool32 vertexAlpha;
+ void *vertexShader;
+ uint32 baseIndex;
+ uint32 numVertices;
+ uint32 startIndex;
+ uint32 numPrimitives;
+};
+
+struct InstanceDataHeader : rw::InstanceDataHeader
+{
+ uint32 serialNumber;
+ uint32 numMeshes;
+ void *indexBuffer;
+ uint32 primType;
+ VertexStream vertexStream[2];
+ bool32 useOffsets;
+ void *vertexDeclaration;
+ uint32 totalNumIndex;
+ uint32 totalNumVertex;
+
+ InstanceData *inst;
+};
+
+#ifdef RW_D3D9
+extern IDirect3DDevice9 *device;
+#endif
+
+extern int vertFormatMap[];
+
+uint16 *lockIndices(void *indexBuffer, uint32 offset, uint32 size, uint32 flags);
+void unlockIndices(void *indexBuffer);
+uint8 *lockVertices(void *vertexBuffer, uint32 offset, uint32 size, uint32 flags);
+void unlockVertices(void *vertexBuffer);
+void *createVertexDeclaration(VertexElement *elements);
+uint32 getDeclaration(void *declaration, VertexElement *elements);
+void *createIndexBuffer(uint32 length);
+void *createVertexBuffer(uint32 length, int32 pool);
+
+void *destroyNativeData(void *object, int32, int32);
+void readNativeData(Stream *stream, int32 len, void *object, int32, int32);
+void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
+int32 getSizeNativeData(void *object, int32, int32);
+void registerNativeDataPlugin(void);
+
+class ObjPipeline : public rw::ObjPipeline
+{
+public:
+ void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
+ void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
+
+ ObjPipeline(uint32 platform);
+ virtual void instance(Atomic *atomic);
+ virtual void uninstance(Atomic *atomic);
+};
+
+ObjPipeline *makeDefaultPipeline(void);
+
+ObjPipeline *makeSkinPipeline(void);
+
+ObjPipeline *makeMatFXPipeline(void);
+
+}
+}
diff --git a/src/rwogl.h b/src/rwogl.h
index 4c0bbe9..f1cd89b 100644
--- a/src/rwogl.h
+++ b/src/rwogl.h
@@ -1,6 +1,8 @@
namespace rw {
namespace gl {
+// NOTE: This is not really RW OpenGL! It's specific to WarDrum's GTA ports
+
struct AttribDesc
{
// arguments to glVertexAttribPointer (should use OpenGL types here)
@@ -26,12 +28,19 @@ struct InstanceDataHeader : rw::InstanceDataHeader
uint32 ibo;
};
+// only RW_OPENGL
+void uploadGeo(Geometry *geo);
+void setAttribPointers(InstanceDataHeader *inst);
+
+void packattrib(uint8 *dst, float32 *src, AttribDesc *a, float32 scale);
+void unpackattrib(float *dst, uint8 *src, AttribDesc *a, float32 scale);
+
void *destroyNativeData(void *object, int32, int32);
void readNativeData(Stream *stream, int32 len, void *object, int32, int32);
void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
+void registerNativeDataPlugin(void);
-void instance(Atomic *atomic);
void printPipeinfo(Atomic *a);
class ObjPipeline : public rw::ObjPipeline
@@ -48,10 +57,6 @@ public:
ObjPipeline *makeDefaultPipeline(void);
-// only RW_OPENGL
-void uploadGeo(Geometry *geo);
-void setAttribPointers(InstanceDataHeader *inst);
-
// Skin plugin
void readNativeSkin(Stream *stream, int32, void *object, int32 offset);
diff --git a/src/rwpipeline.h b/src/rwpipeline.h
index 861d714..5502ccf 100644
--- a/src/rwpipeline.h
+++ b/src/rwpipeline.h
@@ -30,4 +30,27 @@ public:
virtual void render(Atomic *atomic);
};
+void findMinVertAndNumVertices(uint16 *indices, uint32 numIndices, uint32 *minVert, uint32 *numVertices);
+
+// everything xbox, d3d8 and d3d9 may want to use
+enum {
+ VERT_BYTE2 = 1,
+ VERT_BYTE3,
+ VERT_SHORT2,
+ VERT_SHORT3,
+ VERT_NORMSHORT2,
+ VERT_NORMSHORT3,
+ VERT_FLOAT2,
+ VERT_FLOAT3,
+ VERT_ARGB,
+ VERT_COMPNORM
+};
+
+#define COLOR_ARGB(a,r,g,b) \
+ ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
+
+void instV3d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride);
+void instV2d(int type, uint8 *dst, float *src, uint32 numVertices, uint32 stride);
+bool32 instColor(int type, uint8 *dst, uint8 *src, uint32 numVertices, uint32 stride);
+
}
diff --git a/src/rwplugin.h b/src/rwplugin.h
index c005107..54f13bb 100644
--- a/src/rwplugin.h
+++ b/src/rwplugin.h
@@ -13,9 +13,9 @@ typedef void (*RightsCallback)(void *object, int32 offset, int32 size, uint32 da
struct Plugin
{
- int offset;
- int size;
- uint id;
+ int32 offset;
+ int32 size;
+ uint32 id;
Constructor constructor;
Destructor destructor;
CopyConstructor copy;
@@ -29,8 +29,8 @@ struct Plugin
template
struct PluginBase
{
- static int s_defaultSize;
- static int s_size;
+ static int32 s_defaultSize;
+ static int32 s_size;
static Plugin *s_plugins;
void constructPlugins(void);
@@ -41,12 +41,12 @@ struct PluginBase
int streamGetPluginSize(void);
void assertRights(uint32 pluginID, uint32 data);
- static int registerPlugin(int size, uint id,
+ static int registerPlugin(int32 size, uint32 id,
Constructor, Destructor, CopyConstructor);
- static int registerPluginStream(uint id,
+ static int registerPluginStream(uint32 id,
StreamRead, StreamWrite, StreamGetSize);
- static int setStreamRightsCallback(uint id, RightsCallback cb);
- static int getPluginOffset(uint id);
+ static int setStreamRightsCallback(uint32 id, RightsCallback cb);
+ static int getPluginOffset(uint32 id);
static void *operator new(size_t size);
static void operator delete(void *p);
};
@@ -118,11 +118,11 @@ PluginBase::streamWritePlugins(Stream *stream)
}
}
-template int
+template int32
PluginBase::streamGetPluginSize(void)
{
- int size = 0;
- int plgsize;
+ int32 size = 0;
+ int32 plgsize;
for(Plugin *p = this->s_plugins; p; p = p->next)
if(p->getSize &&
(plgsize = p->getSize(this, p->offset, p->size)) >= 0)
@@ -142,8 +142,8 @@ PluginBase::assertRights(uint32 pluginID, uint32 data)
}
}
-template int
-PluginBase::registerPlugin(int size, uint id,
+template int32
+PluginBase::registerPlugin(int32 size, uint32 id,
Constructor ctor, Destructor dtor, CopyConstructor cctor)
{
Plugin *p = new Plugin;
@@ -165,8 +165,8 @@ PluginBase::registerPlugin(int size, uint id,
return p->offset;
}
-template int
-PluginBase::registerPluginStream(uint id,
+template int32
+PluginBase::registerPluginStream(uint32 id,
StreamRead read, StreamWrite write, StreamGetSize getSize)
{
for(Plugin *p = PluginBase::s_plugins; p; p = p->next)
@@ -179,8 +179,8 @@ PluginBase::registerPluginStream(uint id,
return -1;
}
-template int
-PluginBase::setStreamRightsCallback(uint id, RightsCallback cb)
+template int32
+PluginBase::setStreamRightsCallback(uint32 id, RightsCallback cb)
{
for(Plugin *p = PluginBase::s_plugins; p; p = p->next)
if(p->id == id){
@@ -190,8 +190,8 @@ PluginBase::setStreamRightsCallback(uint id, RightsCallback cb)
return -1;
}
-template int
-PluginBase::getPluginOffset(uint id)
+template int32
+PluginBase::getPluginOffset(uint32 id)
{
for(Plugin *p = PluginBase::s_plugins; p; p = p->next)
if(p->id == id)
diff --git a/src/rwxbox.h b/src/rwxbox.h
index 7162ab9..ebea38a 100644
--- a/src/rwxbox.h
+++ b/src/rwxbox.h
@@ -33,14 +33,37 @@ void writeNativeData(Stream *stream, int32 len, void *object, int32, int32);
int32 getSizeNativeData(void *object, int32, int32);
void registerNativeDataPlugin(void);
+class ObjPipeline : public rw::ObjPipeline
+{
+public:
+ void (*instanceCB)(Geometry *geo, InstanceDataHeader *header);
+ void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
+
+ ObjPipeline(uint32 platform);
+ virtual void instance(Atomic *atomic);
+ virtual void uninstance(Atomic *atomic);
+};
+
+ObjPipeline *makeDefaultPipeline(void);
+
// Skin plugin
void readNativeSkin(Stream *stream, int32, void *object, int32 offset);
void writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset);
int32 getSizeNativeSkin(void *object, int32 offset);
+ObjPipeline *makeSkinPipeline(void);
+
+ObjPipeline *makeMatFXPipeline(void);
+
// Vertex Format plugin
+extern uint32 vertexFormatSizes[6];
+
+uint32 *getVertexFmt(Geometry *g);
+uint32 makeVertexFmt(int32 flags, uint32 numTexSets);
+uint32 getVertexFmtStride(uint32 fmt);
+
void registerVertexFormatPlugin(void);
}
diff --git a/src/xbox.cpp b/src/xbox.cpp
index 92f6398..27b20aa 100644
--- a/src/xbox.cpp
+++ b/src/xbox.cpp
@@ -16,6 +16,11 @@ using namespace std;
namespace rw {
namespace xbox {
+enum {
+ D3DPT_TRIANGLELIST = 5,
+ D3DPT_TRIANGLESTRIP = 6,
+};
+
void*
destroyNativeData(void *object, int32, int32)
{
@@ -24,6 +29,7 @@ destroyNativeData(void *object, int32, int32)
assert(geometry->instData->platform == PLATFORM_XBOX);
InstanceDataHeader *header =
(InstanceDataHeader*)geometry->instData;
+ // TODO
delete header;
return object;
}
@@ -84,12 +90,11 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32)
assert(geometry->instData != NULL);
assert(geometry->instData->platform == PLATFORM_XBOX);
stream->writeU32(PLATFORM_XBOX);
+ assert(rw::version >= 0x35000 && "can't write native Xbox data < 0x35000");
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
// we just fill header->data and write that
uint8 *p = header->data+0x18;
- //uint8 *end = (uint8*)header->begin->indexBuffer;
- //memset(p, 0xAB, end-p);
*(int32*)p = header->size; p += 4;
*(uint16*)p = header->serialNumber; p += 2;
*(uint16*)p = header->numMeshes; p += 2;
@@ -137,6 +142,124 @@ registerNativeDataPlugin(void)
getSizeNativeData);
}
+ObjPipeline::ObjPipeline(uint32 platform)
+ : rw::ObjPipeline(platform),
+ instanceCB(NULL), uninstanceCB(NULL) { }
+
+void
+ObjPipeline::instance(Atomic *atomic)
+{
+ Geometry *geo = atomic->geometry;
+ if(geo->geoflags & Geometry::NATIVE)
+ return;
+ geo->geoflags |= Geometry::NATIVE;
+ InstanceDataHeader *header = new InstanceDataHeader;
+ MeshHeader *meshh = geo->meshHeader;
+ geo->instData = header;
+ header->platform = PLATFORM_XBOX;
+
+ header->size = 0x24 + meshh->numMeshes*0x18 + 0x10;
+ Mesh *mesh = meshh->mesh;
+ for(uint32 i = 0; i < meshh->numMeshes; i++)
+ header->size += (mesh++->numIndices*2 + 0xF) & ~0xF;
+ // The 0x18 byte are the resentryheader.
+ // We don't have it but it's used for alignment.
+ header->data = new uint8[header->size + 0x18];
+ header->serialNumber = 0;
+ header->numMeshes = meshh->numMeshes;
+ header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST;
+ header->numVertices = geo->numVertices;
+ header->vertexAlpha = 0;
+ // set by the instanceCB
+ header->stride = 0;
+ header->vertexBuffer = NULL;
+
+ InstanceData *inst = new InstanceData[header->numMeshes];
+ header->begin = inst;
+ mesh = meshh->mesh;
+ uint8 *indexbuf = (uint8*)header->data + ((0x18 + 0x24 + header->numMeshes*0x18 + 0xF)&~0xF);
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
+ &inst->minVert, (uint32*)&inst->numVertices);
+ inst->numIndices = mesh->numIndices;
+ inst->indexBuffer = indexbuf;
+ memcpy(inst->indexBuffer, mesh->indices, inst->numIndices*sizeof(uint16));
+ indexbuf += (inst->numIndices*2 + 0xF) & ~0xF;
+ inst->material = mesh->material;
+ inst->vertexShader = 0; // TODO?
+ mesh++;
+ inst++;
+ }
+ header->end = inst;
+
+ this->instanceCB(geo, header);
+}
+
+void
+ObjPipeline::uninstance(Atomic *atomic)
+{
+ assert(0 && "can't uninstance");
+}
+
+int v3dFormatMap[] = {
+ -1, VERT_BYTE3, VERT_SHORT3, VERT_NORMSHORT3, VERT_COMPNORM, VERT_FLOAT3
+};
+
+int v2dFormatMap[] = {
+ -1, VERT_BYTE2, VERT_SHORT2, VERT_NORMSHORT2, VERT_COMPNORM, VERT_FLOAT2
+};
+
+void
+defaultInstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ uint32 *vertexFmt = getVertexFmt(geo);
+ if(*vertexFmt == 0)
+ *vertexFmt = makeVertexFmt(geo->geoflags, geo->numTexCoordSets);
+ header->stride = getVertexFmtStride(*vertexFmt);
+ header->vertexBuffer = new uint8[header->stride*header->numVertices];
+ uint32 offset = 0;
+ uint8 *dst = (uint8*)header->vertexBuffer;
+
+ uint32 fmt = *vertexFmt;
+ uint32 sel = fmt & 0xF;
+ instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].vertices,
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+
+ sel = (fmt >> 4) & 0xF;
+ if(sel){
+ instV3d(v3dFormatMap[sel], dst, geo->morphTargets[0].normals,
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 3*vertexFormatSizes[sel];
+ }
+
+ if(fmt & 0x1000000){
+ header->vertexAlpha = instColor(VERT_ARGB, dst, geo->colors,
+ header->numVertices, header->stride);
+ dst += 4;
+ }
+
+ for(int i = 0; i < 4; i++){
+ sel = (fmt >> (i*4 + 8)) & 0xF;
+ if(sel == 0)
+ break;
+ instV2d(v2dFormatMap[sel], dst, geo->texCoords[i],
+ header->numVertices, header->stride);
+ dst += sel == 4 ? 4 : 2*vertexFormatSizes[sel];
+ }
+
+ if(fmt & 0xE000000)
+ assert(0 && "can't instance tangents or whatever it is");
+}
+
+ObjPipeline*
+makeDefaultPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
+ pipe->instanceCB = defaultInstanceCB;
+ return pipe;
+}
+
// Skin plugin
struct NativeSkin
@@ -213,14 +336,87 @@ getSizeNativeSkin(void *object, int32 offset)
Skin *skin = *PLUGINOFFSET(Skin*, object, offset);
if(skin == NULL)
return -1;
- assert(skin->platformData);
+ if(skin->platformData == NULL)
+ return -1;
NativeSkin *natskin = (NativeSkin*)skin->platformData;
return 12 + 8 + 2*256*4 + 4*4 +
natskin->stride*geometry->numVertices + skin->numBones*64 + 12;
}
+void
+skinInstanceCB(Geometry *geo, InstanceDataHeader *header)
+{
+ defaultInstanceCB(geo, header);
+}
+
+ObjPipeline*
+makeSkinPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
+ pipe->instanceCB = skinInstanceCB;
+ pipe->pluginID = ID_SKIN;
+ pipe->pluginData = 1;
+ return pipe;
+}
+
+ObjPipeline*
+makeMatFXPipeline(void)
+{
+ ObjPipeline *pipe = new ObjPipeline(PLATFORM_XBOX);
+ pipe->instanceCB = defaultInstanceCB;
+ pipe->pluginID = ID_MATFX;
+ pipe->pluginData = 0;
+ return pipe;
+}
+
// Vertex Format Plugin
+static int32 vertexFmtOffset;
+
+uint32 vertexFormatSizes[6] = {
+ 0, 1, 2, 2, 4, 4
+};
+
+uint32*
+getVertexFmt(Geometry *g)
+{
+ return PLUGINOFFSET(uint32, g, vertexFmtOffset);
+}
+
+uint32
+makeVertexFmt(int32 flags, uint32 numTexSets)
+{
+ if(numTexSets > 4)
+ numTexSets = 4;
+ uint32 fmt = 0x5; // FLOAT3
+ if(flags & Geometry::NORMALS)
+ fmt |= 0x40; // NORMPACKED3
+ for(uint32 i = 0; i < numTexSets; i++)
+ fmt |= 0x500 << i*4; // FLOAT2
+ if(flags & Geometry::PRELIT)
+ fmt |= 0x1000000; // D3DCOLOR
+ return fmt;
+}
+
+uint32
+getVertexFmtStride(uint32 fmt)
+{
+ uint32 stride = 0;
+ uint32 v = fmt & 0xF;
+ uint32 n = (fmt >> 4) & 0xF;
+ stride += v == 4 ? 4 : 3*vertexFormatSizes[v];
+ stride += n == 4 ? 4 : 3*vertexFormatSizes[n];
+ if(fmt & 0x1000000)
+ stride += 4;
+ for(int i = 0; i < 4; i++){
+ uint32 t = (fmt >> (i*4 + 8)) & 0xF;
+ stride += t == 4 ? 4 : 2*vertexFormatSizes[t];
+ }
+ if(fmt & 0xE000000)
+ stride += 8;
+ return stride;
+}
+
static void*
createVertexFmt(void *object, int32 offset, int32)
{
@@ -239,9 +435,8 @@ static void
readVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
{
uint32 fmt = stream->readU32();
-// printf("vertexfmt: %X\n", fmt);
*PLUGINOFFSET(uint32, object, offset) = fmt;
- // TODO: create and attach "vertex shader"
+ // TODO: ? create and attach "vertex shader"
}
static void
@@ -253,14 +448,15 @@ writeVertexFmt(Stream *stream, int32, void *object, int32 offset, int32)
static int32
getSizeVertexFmt(void*, int32, int32)
{
- // TODO: make dependent on platform
+ if(rw::platform != PLATFORM_XBOX)
+ return -1;
return 4;
}
void
registerVertexFormatPlugin(void)
{
- Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT,
+ vertexFmtOffset = Geometry::registerPlugin(sizeof(uint32), ID_VERTEXFMT,
createVertexFmt, NULL, copyVertexFmt);
Geometry::registerPluginStream(ID_VERTEXFMT,
readVertexFmt,
diff --git a/tools/d3d9/camera.cpp b/tools/d3d9/camera.cpp
new file mode 100644
index 0000000..3fb9ada
--- /dev/null
+++ b/tools/d3d9/camera.cpp
@@ -0,0 +1,169 @@
+#include "math/math.h"
+#include "camera.h"
+
+using namespace std;
+
+void
+Camera::look(void)
+{
+ projMat = Mat4::perspective(fov, aspectRatio, n, f);
+ viewMat = Mat4::lookat(position, target, up);
+
+// state->mat4(PMAT,true)->val = Mat4::perspective(fov, aspectRatio, n, f);
+// Mat4 mv = Mat4::lookat(position, target, up);
+// state->mat4(MVMAT, true)->val = mv;
+// state->mat3(NORMALMAT, true)->val = Mat3(mv);
+}
+
+void
+Camera::setPosition(Vec3 q)
+{
+ position = q;
+}
+
+Vec3
+Camera::getPosition(void)
+{
+ return position;
+}
+
+void
+Camera::setTarget(Vec3 q)
+{
+ position -= target - q;
+ target = q;
+}
+
+Vec3
+Camera::getTarget(void)
+{
+ return target;
+}
+
+float
+Camera::getHeading(void)
+{
+ Vec3 dir = target - position;
+ float a = atan2(dir.y, dir.x)-PI/2.0f;
+ return local_up.z < 0.0f ? a-PI : a;
+}
+
+void
+Camera::turn(float yaw, float pitch)
+{
+ yaw /= 2.0f;
+ pitch /= 2.0f;
+ Quat dir = Quat(target - position);
+ Quat r(cos(yaw), 0.0f, 0.0f, sin(yaw));
+ dir = r*dir*r.K();
+ local_up = Vec3(r*Quat(local_up)*r.K());
+
+ Quat right = dir.wedge(Quat(local_up)).U();
+ r = Quat(cos(pitch), right*sin(pitch));
+ dir = r*dir*r.K();
+ local_up = Vec3(right.wedge(dir).U());
+ if(local_up.z >=0) up.z = 1;
+ else up.z = -1;
+
+ target = position + Vec3(dir);
+}
+
+void
+Camera::orbit(float yaw, float pitch)
+{
+ yaw /= 2.0f;
+ pitch /= 2.0f;
+ Quat dir = Quat(target - position);
+ Quat r(cos(yaw), 0.0f, 0.0f, sin(yaw));
+ dir = r*dir*r.K();
+ local_up = Vec3(r*Quat(local_up)*r.K());
+
+ Quat right = dir.wedge(Quat(local_up)).U();
+ r = Quat(cos(-pitch), right*sin(-pitch));
+ dir = r*dir*r.K();
+ local_up = Vec3(right.wedge(dir).U());
+ if(local_up.z >=0) up.z = 1;
+ else up.z = -1;
+
+ position = target - Vec3(dir);
+}
+
+void
+Camera::dolly(float dist)
+{
+ Vec3 dir = (target - position).normalized()*dist;
+ position += dir;
+ target += dir;
+}
+
+void
+Camera::zoom(float dist)
+{
+ Vec3 dir = target - position;
+ float curdist = dir.norm();
+ if(dist >= curdist)
+ dist = curdist-0.01f;
+ dir = dir.normalized()*dist;
+ position += dir;
+}
+
+void
+Camera::pan(float x, float y)
+{
+ Vec3 dir = (target-position).normalized();
+ Vec3 right = dir.cross(up).normalized();
+// Vec3 local_up = right.cross(dir).normalized();
+ dir = right*x + local_up*y;
+ position += dir;
+ target += dir;
+
+}
+
+float
+Camera::sqDistanceTo(Vec3 q)
+{
+ return (position - q).normsq();
+}
+
+float
+Camera::distanceTo(Vec3 q)
+{
+ return (position - q).norm();
+}
+
+void
+Camera::setFov(float f)
+{
+ fov = f;
+}
+
+float
+Camera::getFov(void)
+{
+ return fov;
+}
+
+void
+Camera::setAspectRatio(float r)
+{
+ aspectRatio = r;
+}
+
+void
+Camera::setNearFar(float n, float f)
+{
+ this->n = n;
+ this->f = f;
+}
+
+Camera::Camera()
+{
+ position = Vec3(0.0f, 6.0f, 0.0f);
+ target = Vec3(0.0f, 0.0f, 0.0f);
+ local_up = up = Vec3(0.0f, 0.0f, 1.0f);
+ fov = 70.0f;
+ aspectRatio = 1.0f;
+ n = 0.1f;
+ f = 100.0f;
+}
+
diff --git a/tools/d3d9/camera.h b/tools/d3d9/camera.h
new file mode 100644
index 0000000..0a47263
--- /dev/null
+++ b/tools/d3d9/camera.h
@@ -0,0 +1,37 @@
+class Camera
+{
+private:
+ Vec3 position;
+ Vec3 target;
+ Vec3 up;
+ Vec3 local_up;
+
+ float fov, aspectRatio;
+ float n, f;
+
+public:
+ Mat4 projMat;
+ Mat4 viewMat;
+
+ void setPosition(Vec3 q);
+ Vec3 getPosition(void);
+ void setTarget(Vec3 q);
+ Vec3 getTarget(void);
+ float getHeading(void);
+
+ void turn(float yaw, float pitch);
+ void orbit(float yaw, float pitch);
+ void dolly(float dist);
+ void zoom(float dist);
+ void pan(float x, float y);
+
+ void setFov(float f);
+ float getFov(void);
+ void setAspectRatio(float r);
+ void setNearFar(float n, float f);
+
+ void look(void);
+ float distanceTo(Vec3 q);
+ float sqDistanceTo(Vec3 q);
+ Camera(void);
+};
diff --git a/tools/d3d9/d3d9.vcxproj b/tools/d3d9/d3d9.vcxproj
new file mode 100644
index 0000000..eadb706
--- /dev/null
+++ b/tools/d3d9/d3d9.vcxproj
@@ -0,0 +1,119 @@
+
+
+
+
+ Debug - null
+ Win32
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {E5D477C8-4CAF-43BF-B7E3-6689503D469F}
+ d3d9
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)
+
+
+ true
+ d3d9.lib;winmm.lib;librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)
+
+
+ true
+ d3d9.lib;winmm.lib;librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;RW_D3D9;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ d3d9.lib;winmm.lib;librw.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/d3d9/d3dInit.cpp b/tools/d3d9/d3dInit.cpp
new file mode 100644
index 0000000..727e1b8
--- /dev/null
+++ b/tools/d3d9/d3dInit.cpp
@@ -0,0 +1,362 @@
+#include "d3dUtility.h"
+#include
+using namespace DirectX;
+
+#include
+#include
+#include "math/math.h"
+#include "camera.h"
+
+IDirect3DDevice9 *Device = 0;
+
+Camera *camera;
+
+namespace rw {
+namespace d3d9 {
+
+int32 nativeRasterOffset;
+
+struct D3d9Raster {
+ IDirect3DTexture9 *texture;
+};
+
+static void*
+createNativeRaster(void *object, int32 offset, int32)
+{
+ D3d9Raster *raster = PLUGINOFFSET(D3d9Raster, object, offset);
+ raster->texture = NULL;
+ return object;
+}
+
+static void*
+destroyNativeRaster(void *object, int32 offset, int32)
+{
+ // TODO:
+ return object;
+}
+
+static void*
+copyNativeRaster(void *dst, void *, int32 offset, int32)
+{
+ D3d9Raster *raster = PLUGINOFFSET(D3d9Raster, dst, offset);
+ raster->texture = NULL;
+ return dst;
+}
+
+void
+registerNativeRaster(void)
+{
+ nativeRasterOffset = Raster::registerPlugin(sizeof(D3d9Raster),
+ 0x12340002,
+ createNativeRaster,
+ destroyNativeRaster,
+ copyNativeRaster);
+}
+
+void
+createTexture(Texture *tex)
+{
+ D3d9Raster *raster = PLUGINOFFSET(D3d9Raster, tex->raster, nativeRasterOffset);
+ int32 w, h;
+ w = tex->raster->width;
+ h = tex->raster->height;
+
+ assert((tex->raster->format & 0xF00) == Raster::C8888);
+
+ IDirect3DTexture9 *texture;
+ Device->CreateTexture(w, h, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
+ D3DLOCKED_RECT lr;
+ texture->LockRect(0, &lr, 0, 0);
+ DWORD *dst = (DWORD*)lr.pBits;
+ uint8 *src = tex->raster->texels;
+ for(int i = 0; i < h; i++){
+ for(int j = 0; j < w; j++){
+ dst[j] = D3DCOLOR_ARGB(src[3], src[0], src[1], src[2]);
+ src += 4;
+ }
+ dst += lr.Pitch/4;
+ }
+ texture->UnlockRect(0);
+ raster->texture = texture;
+}
+
+void
+setTexture(Texture *tex)
+{
+ static DWORD filternomip[] = {
+ 0, D3DTEXF_POINT, D3DTEXF_LINEAR,
+ D3DTEXF_POINT, D3DTEXF_LINEAR,
+ D3DTEXF_POINT, D3DTEXF_LINEAR
+ };
+ static DWORD wrap[] = {
+ 0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
+ D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
+ };
+
+ D3d9Raster *raster = PLUGINOFFSET(D3d9Raster, tex->raster, nativeRasterOffset);
+ if(tex->raster){
+ if(raster->texture == NULL)
+ createTexture(tex);
+ Device->SetTexture(0, raster->texture);
+ Device->SetSamplerState(0, D3DSAMP_MAGFILTER, filternomip[tex->filterAddressing & 0xFF]);
+ Device->SetSamplerState(0, D3DSAMP_MINFILTER, filternomip[tex->filterAddressing & 0xFF]);
+ Device->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap[(tex->filterAddressing >> 8) & 0xF]);
+ Device->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap[(tex->filterAddressing >> 12) & 0xF]);
+ }else
+ Device->SetTexture(0, NULL);
+}
+
+void
+setMaterial(Material *mat)
+{
+ D3DMATERIAL9 mat9;
+ D3DCOLORVALUE black = { 0, 0, 0, 0 };
+ float ambmult = mat->surfaceProps[0]/255.0f;
+ float diffmult = mat->surfaceProps[2]/255.0f;
+ mat9.Ambient.r = mat->color[0]*ambmult;
+ mat9.Ambient.g = mat->color[1]*ambmult;
+ mat9.Ambient.b = mat->color[2]*ambmult;
+ mat9.Ambient.a = mat->color[3]*ambmult;
+ mat9.Diffuse.r = mat->color[0]*diffmult;
+ mat9.Diffuse.g = mat->color[1]*diffmult;
+ mat9.Diffuse.b = mat->color[2]*diffmult;
+ mat9.Diffuse.a = mat->color[3]*diffmult;
+ mat9.Power = 0.0f;
+ mat9.Emissive = black;
+ mat9.Specular = black;
+ Device->SetMaterial(&mat9);
+}
+
+void
+drawAtomic(Atomic *atomic)
+{
+ Geometry *geo = atomic->geometry;
+ if((geo->geoflags & Geometry::NATIVE) == 0)
+ return;
+ InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
+
+ atomic->frame->updateLTM();
+ Device->SetTransform(D3DTS_WORLD, (D3DMATRIX*)atomic->frame->ltm);
+
+ Device->SetStreamSource(0, (IDirect3DVertexBuffer9*)header->vertexStream[0].vertexBuffer,
+ 0, header->vertexStream[0].stride);
+ Device->SetIndices((IDirect3DIndexBuffer9*)header->indexBuffer);
+ Device->SetVertexDeclaration((IDirect3DVertexDeclaration9*)header->vertexDeclaration);
+
+ InstanceData *inst = header->inst;
+ for(uint32 i = 0; i < header->numMeshes; i++){
+ if(inst->material->texture)
+ setTexture(inst->material->texture);
+ else
+ Device->SetTexture(0, NULL);
+ setMaterial(inst->material);
+ Device->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_ARGB(0xFF, 0x40, 0x40, 0x40));
+ Device->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);
+ Device->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
+ if(geo->geoflags & Geometry::PRELIT)
+ Device->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1);
+ Device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)header->primType, inst->baseIndex,
+ 0/*inst->minVert*/, inst->numVertices,
+ inst->startIndex, inst->numPrimitives);
+ inst++;
+ }
+}
+
+}
+}
+
+rw::Clump *clump;
+
+void
+initrw(void)
+{
+ rw::currentTexDictionary = new rw::TexDictionary;
+ rw::Image::setSearchPath("D:\\rockstargames\\ps2\\gta3\\MODELS\\gta3_archive\\txd_extracted\\;D:\\rockstargames\\ps2\\gtavc\\MODELS\\gta3_archive\\txd_extracted\\;D:\\rockstargames\\ps2\\gtasa\\models\\gta3_archive\\txd_extracted\\");
+
+ gta::registerEnvSpecPlugin();
+ rw::registerMatFXPlugin();
+ rw::registerMaterialRightsPlugin();
+ rw::registerAtomicRightsPlugin();
+ rw::registerHAnimPlugin();
+ gta::registerNodeNamePlugin();
+ gta::registerExtraNormalsPlugin();
+ gta::registerBreakableModelPlugin();
+ gta::registerExtraVertColorPlugin();
+ rw::ps2::registerADCPlugin();
+ rw::ps2::registerPDSPlugin();
+ rw::registerSkinPlugin();
+ rw::xbox::registerVertexFormatPlugin();
+ rw::registerNativeDataPlugin();
+ rw::registerMeshPlugin();
+ rw::Atomic::init();
+ rw::d3d9::registerNativeRaster();
+
+ rw::d3d9::device = Device;
+
+ char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\admiral.dff";
+// char *filename = "D:\\rockstargames\\pc\\gtavc\\models\\gta3_archive\\player.dff";
+// char *filename = "C:\\gtasa\\test\\hanger.dff";
+// char *filename = "C:\\Users\\aap\\Desktop\\tmp\\out.dff";
+// char *filename = "out.dff";
+ rw::StreamFile in;
+ if(in.open(filename, "rb") == NULL){
+ MessageBox(0, "couldn't open file\n", 0, 0);
+ printf("couldn't open file\n");
+ }
+ rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL);
+ clump = rw::Clump::streamRead(&in);
+ assert(clump);
+ in.close();
+
+ for(int i = 0; i < clump->numAtomics; i++){
+ rw::Atomic *a = clump->atomicList[i];
+ a->getPipeline()->instance(a);
+ }
+
+// rw::StreamFile out;
+// out.open("out2.dff", "wb");
+// clump->streamWrite(&out);
+// out.close();
+}
+
+bool
+Setup()
+{
+ D3DLIGHT9 light;
+ light.Type = D3DLIGHT_DIRECTIONAL;
+ light.Diffuse = { 0.8f, 0.8f, 0.8f, 1.0f };
+ light.Specular = { 0.0f, 0.0f, 0.0f, 0.0f };
+ light.Ambient = { 0.0f, 0.0f, 0.0f, 0.0f };
+ light.Position = { 0.0f, 0.0f, 0.0f };
+ light.Direction = { 0.0f, 0.0f, -1.0f };
+ light.Range = 0.0f;
+ light.Falloff = 0.0f;
+ light.Attenuation0 = 0.0f;
+ light.Attenuation1 = 0.0f;
+ light.Attenuation2 = 0.0f;
+ light.Theta = 0.0f;
+ light.Phi = 0.0f;
+
+ initrw();
+
+ Device->SetRenderState(D3DRS_LIGHTING, true);
+ Device->SetLight(0, &light);
+ Device->LightEnable(0, 1);
+
+ Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+ Device->SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
+ Device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
+
+ camera = new Camera;
+ camera->setAspectRatio(640.0f/480.0f);
+ camera->setNearFar(0.1f, 250.0f);
+ camera->setTarget(Vec3(0.0f, 0.0f, 0.0f));
+// camera->setPosition(Vec3(0.0f, 5.0f, 0.0f));
+ camera->setPosition(Vec3(0.0f, -5.0f, 0.0f));
+// camera->setPosition(Vec3(0.0f, -1.0f, 3.0f));
+
+ return true;
+}
+
+void
+Cleanup()
+{
+}
+
+bool
+Display(float timeDelta)
+{
+ if(Device == NULL)
+ return true;
+
+ Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
+ 0xff808080, 1.0f, 0);
+ Device->BeginScene();
+
+ camera->look();
+ Device->SetTransform(D3DTS_VIEW, (D3DMATRIX*)camera->viewMat.cr);
+ Device->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)camera->projMat.cr);
+
+ for(rw::int32 i = 0; i < clump->numAtomics; i++){
+ char *name = PLUGINOFFSET(char, clump->atomicList[i]->frame,
+ gta::nodeNameOffset);
+ if(strstr(name, "_dam") || strstr(name, "_vlo"))
+ continue;
+ rw::d3d9::drawAtomic(clump->atomicList[i]);
+ }
+
+ Device->EndScene();
+
+ Device->Present(0, 0, 0, 0);
+ return true;
+}
+
+LRESULT CALLBACK
+d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg){
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+
+ case WM_KEYDOWN:
+ switch(wParam){
+ case 'W':
+ camera->orbit(0.0f, 0.1f);
+ break;
+ case 'S':
+ camera->orbit(0.0f, -0.1f);
+ break;
+ case 'A':
+ camera->orbit(-0.1f, 0.0f);
+ break;
+ case 'D':
+ camera->orbit(0.1f, 0.0f);
+ break;
+ case 'R':
+ camera->zoom(0.1f);
+ break;
+ case 'F':
+ camera->zoom(-0.1f);
+ break;
+ case VK_ESCAPE:
+ DestroyWindow(hwnd);
+ break;
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hwnd);
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+int WINAPI
+WinMain(HINSTANCE hinstance, HINSTANCE prevInstance,
+ PSTR cmdLine, int showCmd)
+{
+/* AllocConsole();
+ freopen("CONIN$", "r", stdin);
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONOUT$", "w", stderr);*/
+
+ if(!d3d::InitD3D(hinstance, 640, 480, true, D3DDEVTYPE_HAL, &Device)){
+ MessageBox(0, "InitD3D() - FAILED", 0, 0);
+ return 0;
+ }
+
+ if(!Setup()){
+ MessageBox(0, "Setup() - FAILED", 0, 0);
+ return 0;
+ }
+
+ d3d::EnterMsgLoop(Display);
+
+ Cleanup();
+
+ Device->Release();
+
+ return 0;
+}
\ No newline at end of file
diff --git a/tools/d3d9/d3dUtility.cpp b/tools/d3d9/d3dUtility.cpp
new file mode 100644
index 0000000..d05ce26
--- /dev/null
+++ b/tools/d3d9/d3dUtility.cpp
@@ -0,0 +1,111 @@
+#include "d3dUtility.h"
+
+bool
+d3d::InitD3D(HINSTANCE hInstance,
+ int width, int height,
+ bool windowed,
+ D3DDEVTYPE deviceType,
+ IDirect3DDevice9 **device)
+{
+ WNDCLASS wc;
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC)d3d::WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(0, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = 0;
+ wc.lpszClassName = "Direct3D9App";
+ if(!RegisterClass(&wc)){
+ MessageBox(0, "RegisterClass() - FAILED", 0, 0);
+ return false;
+ }
+
+ HWND hwnd = 0;
+ hwnd = CreateWindow("Direct3D9App", "Direct3D9App",
+ WS_BORDER | WS_CAPTION | WS_SYSMENU |
+ WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
+ 0, 0, width, height, 0, 0, hInstance, 0);
+ if(!hwnd){
+ MessageBox(0, "CreateWindow() - FAILED", 0, 0);
+ return false;
+ }
+ ShowWindow(hwnd, SW_SHOW);
+ UpdateWindow(hwnd);
+
+ HRESULT hr = 0;
+ IDirect3D9 *d3d9 = 0;
+ d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ if(!d3d9){
+ MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
+ return false;
+ }
+
+ D3DCAPS9 caps;
+ d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
+ int vp = 0;
+ if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
+ vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
+ else
+ vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+
+ D3DPRESENT_PARAMETERS d3dpp;
+ d3dpp.BackBufferWidth = width;
+ d3dpp.BackBufferHeight = height;
+ d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
+ d3dpp.MultiSampleQuality = 0;
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ d3dpp.hDeviceWindow = hwnd;
+ d3dpp.Windowed = windowed;
+ d3dpp.EnableAutoDepthStencil = true;
+ d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
+ d3dpp.Flags = 0;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+
+ hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType, hwnd,
+ vp, &d3dpp, device);
+ if(FAILED(hr)){
+ // try again using a 16-bit depth buffer
+ d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
+
+ hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT, deviceType,
+ hwnd, vp, &d3dpp, device);
+
+ if(FAILED(hr)){
+ d3d9->Release();
+ MessageBox(0, "CreateDevice() - FAILED", 0, 0);
+ return false;
+ }
+ }
+ d3d9->Release();
+ return true;
+}
+
+int
+d3d::EnterMsgLoop(bool (*ptr_display)(float timeDelta))
+{
+ MSG msg;
+ ZeroMemory(&msg, sizeof(MSG));
+
+ static float lastTime = (float)timeGetTime();
+
+ while(msg.message != WM_QUIT){
+ if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }else{
+ float currTime = (float)timeGetTime();
+ float timeDelta = (currTime - lastTime)*0.001f;
+
+ ptr_display(timeDelta);
+
+ lastTime = currTime;
+ }
+ }
+ return msg.wParam;
+}
\ No newline at end of file
diff --git a/tools/d3d9/d3dUtility.h b/tools/d3d9/d3dUtility.h
new file mode 100644
index 0000000..0852b8f
--- /dev/null
+++ b/tools/d3d9/d3dUtility.h
@@ -0,0 +1,31 @@
+#include
+#include
+
+namespace d3d
+{
+bool InitD3D(HINSTANCE hInstance, int width, int height, bool windowed,
+ D3DDEVTYPE deviceType, IDirect3DDevice9 **device);
+
+int EnterMsgLoop(bool (*ptr_display)(float timeDelta));
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+/*
+template void Release(T t)
+{
+ if(t){
+ t->Release();
+ t = 0;
+ }
+}
+
+template void Delete(T t)
+{
+ if(t){
+ delete t;
+ t = 0;
+ }
+}
+*/
+
+}
\ No newline at end of file
diff --git a/tools/d3d9/math.cpp b/tools/d3d9/math.cpp
new file mode 100644
index 0000000..58bfd70
--- /dev/null
+++ b/tools/d3d9/math.cpp
@@ -0,0 +1,1237 @@
+#include "math/math.h"
+
+/*
+ * Vec3
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const Vec3 &v)
+{
+ v.print(of);
+ return of;
+}
+
+
+Vec3::Vec3(void)
+ : x(0.0f), y(0.0f), z(0.0f)
+{
+}
+
+Vec3::Vec3(float x, float y, float z)
+ : x(x), y(y), z(z)
+{
+}
+
+Vec3::Vec3(float *v)
+ : x(v[0]), y(v[1]), z(v[2])
+{
+}
+
+float*
+Vec3::ptr(void)
+{
+ return &x;
+}
+
+Vec3
+Vec3::operator-(void) const
+{
+ return Vec3(-x, -y, -z);
+}
+
+Vec3
+Vec3::operator+(const Vec3 &rhs) const
+{
+ return Vec3(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z);
+}
+
+Vec3
+Vec3::operator-(const Vec3 &rhs) const
+{
+ return Vec3(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z);
+}
+
+Vec3
+Vec3::operator*(float rhs) const
+{
+ return Vec3(this->x*rhs, this->y*rhs, this->z*rhs);
+}
+
+Vec3
+Vec3::operator/(float rhs) const
+{
+ return Vec3(this->x/rhs, this->y/rhs, this->z/rhs);
+}
+
+Vec3&
+Vec3::operator+=(const Vec3 &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+Vec3&
+Vec3::operator-=(const Vec3 &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+Vec3&
+Vec3::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Vec3&
+Vec3::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+bool
+Vec3::operator==(const Vec3 &rhs) const
+{
+ return (this->x == rhs.x) &&
+ (this->y == rhs.y) &&
+ (this->z == rhs.z);
+}
+
+bool
+Vec3::operator!=(const Vec3 &rhs) const
+{
+ return (this->x != rhs.x) ||
+ (this->y != rhs.y) ||
+ (this->z != rhs.z);
+}
+
+float
+Vec3::norm(void) const
+{
+ return sqrt(normsq());
+}
+
+float
+Vec3::normsq(void) const
+{
+ return x*x + y*y + z*z;
+}
+
+Vec3
+Vec3::normalized(void) const
+{
+ return Vec3(*this)/norm();
+}
+
+float
+Vec3::dot(const Vec3 &rhs) const
+{
+ return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z;
+}
+
+Vec3
+Vec3::cross(const Vec3 &rhs) const
+{
+ return Vec3(this->y*rhs.z - this->z*rhs.y,
+ this->z*rhs.x - this->x*rhs.z,
+ this->x*rhs.y - this->y*rhs.x);
+}
+
+void
+Vec3::print(std::ostream &of) const
+{
+ of << "V3(" << x << ", " << y << ", " << z << ")";
+}
+
+/*
+ * Vec4
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const Vec4 &v)
+{
+ v.print(of);
+ return of;
+}
+
+
+Vec4::Vec4(void)
+ : x(0.0f), y(0.0f), z(0.0f), w(0.0f)
+{
+}
+
+Vec4::Vec4(float x, float y, float z, float w)
+ : x(x), y(y), z(z), w(w)
+{
+}
+
+Vec4::Vec4(float *v)
+ : x(v[0]), y(v[1]), z(v[2]), w(v[3])
+{
+}
+
+float*
+Vec4::ptr(void)
+{
+ return &x;
+}
+
+Vec4
+Vec4::operator-(void) const
+{
+ return Vec4(-x, -y, -z, -w);
+}
+
+Vec4
+Vec4::operator+(const Vec4 &rhs) const
+{
+ return Vec4(this->x+rhs.x, this->y+rhs.y, this->z+rhs.z, this->w+rhs.w);
+}
+
+Vec4
+Vec4::operator-(const Vec4 &rhs) const
+{
+ return Vec4(this->x-rhs.x, this->y-rhs.y, this->z-rhs.z, this->w-rhs.w);
+}
+
+Vec4
+Vec4::operator*(float rhs) const
+{
+ return Vec4(this->x*rhs, this->y*rhs, this->z*rhs, this->w*rhs);
+}
+
+Vec4
+Vec4::operator/(float rhs) const
+{
+ return Vec4(this->x/rhs, this->y/rhs, this->z/rhs, this->w/rhs);
+}
+
+Vec4&
+Vec4::operator+=(const Vec4 &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+Vec4&
+Vec4::operator-=(const Vec4 &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+Vec4&
+Vec4::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Vec4&
+Vec4::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+bool
+Vec4::operator==(const Vec4 &rhs) const
+{
+ return (this->x == rhs.x) &&
+ (this->y == rhs.y) &&
+ (this->z == rhs.z) &&
+ (this->w == rhs.w);
+}
+
+bool
+Vec4::operator!=(const Vec4 &rhs) const
+{
+ return (this->x != rhs.x) ||
+ (this->y != rhs.y) ||
+ (this->z != rhs.z) ||
+ (this->w != rhs.w);
+}
+
+float
+Vec4::norm(void) const
+{
+ return sqrt(normsq());
+}
+
+float
+Vec4::normsq(void) const
+{
+ return x*x + y*y + z*z + w*w;
+}
+
+Vec4
+Vec4::normalized(void) const
+{
+ return Vec4(*this)/norm();
+}
+
+float
+Vec4::dot(const Vec4 &rhs) const
+{
+ return this->x*rhs.x + this->y*rhs.y + this->z*rhs.z + this->w*rhs.w;
+}
+
+void
+Vec4::print(std::ostream &of) const
+{
+ of << "V4(" << x << ", " << y << ", " << z << ", " << w << ")";
+}
+
+/*
+ * Quat
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const Quat &v)
+{
+ v.print(of);
+ return of;
+}
+
+
+Quat::Quat(void)
+ : w(0.0f), x(0.0f), y(0.0f), z(0.0f)
+{
+}
+
+Quat::Quat(float w)
+ : w(w), x(0.0f), y(0.0f), z(0.0f)
+{
+}
+
+Quat::Quat(float x, float y, float z)
+ : w(0.0f), x(x), y(y), z(z)
+{
+}
+
+Quat::Quat(float w, float x, float y, float z)
+ : w(w), x(x), y(y), z(z)
+{
+}
+
+float*
+Quat::ptr(void)
+{
+ return &w;
+}
+
+Quat
+Quat::operator-(void) const
+{
+ return Quat(-w, -x, -y, -z);
+}
+
+Quat
+Quat::operator+(const Quat &rhs) const
+{
+ return Quat(this->w+rhs.w, this->x+rhs.x, this->y+rhs.y, this->z+rhs.z);
+}
+
+Quat
+Quat::operator-(const Quat &rhs) const
+{
+ return Quat(this->w-rhs.w, this->x-rhs.x, this->y-rhs.y, this->z-rhs.z);
+}
+
+Quat
+Quat::operator*(const Quat &rhs) const
+{
+ return Quat(
+ this->w*rhs.w - this->x*rhs.x - this->y*rhs.y - this->z*rhs.z,
+ this->w*rhs.x + this->x*rhs.w + this->y*rhs.z - this->z*rhs.y,
+ this->w*rhs.y + this->y*rhs.w + this->z*rhs.x - this->x*rhs.z,
+ this->w*rhs.z + this->z*rhs.w + this->x*rhs.y - this->y*rhs.x);
+}
+
+Quat
+Quat::operator*(float rhs) const
+{
+ return Quat(this->w*rhs, this->x*rhs, this->y*rhs, this->z*rhs);
+}
+
+Quat
+Quat::operator/(float rhs) const
+{
+ return Quat(this->w/rhs, this->x/rhs, this->y/rhs, this->z/rhs);
+}
+
+Quat&
+Quat::operator+=(const Quat &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+Quat&
+Quat::operator-=(const Quat &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+Quat&
+Quat::operator*=(const Quat &rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Quat&
+Quat::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Quat&
+Quat::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+bool
+Quat::operator==(const Quat &rhs) const
+{
+ return (this->w == rhs.w) &&
+ (this->x == rhs.x) &&
+ (this->y == rhs.y) &&
+ (this->z == rhs.z);
+}
+
+bool
+Quat::operator!=(const Quat &rhs) const
+{
+ return (this->w != rhs.w) ||
+ (this->x != rhs.x) ||
+ (this->y != rhs.y) ||
+ (this->z != rhs.z);
+}
+
+Quat
+Quat::inv(void) const
+{
+ return K() / N();
+}
+
+Quat
+Quat::K(void) const
+{
+ return Quat(w, -x, -y, -z);
+}
+
+Quat
+Quat::S(void) const
+{
+ return Quat(w);
+}
+
+Quat
+Quat::V(void) const
+{
+ return Quat(x, y, z);
+}
+
+float
+Quat::T(void) const
+{
+ return sqrt(N());
+}
+
+float
+Quat::N(void) const
+{
+ return w*w + x*x + y*y + z*z;
+}
+
+Quat
+Quat::U(void) const
+{
+ return Quat(*this)/T();
+}
+
+Quat
+Quat::wedge(const Quat &rhs) const
+{
+ return Quat(0.0f,
+ this->y*rhs.z - this->z*rhs.y,
+ this->z*rhs.x - this->x*rhs.z,
+ this->x*rhs.y - this->y*rhs.x);
+}
+
+float
+Quat::inner(const Quat &rhs) const
+{
+ return this->w*rhs.w + this->x*rhs.x + this->y*rhs.y + this->z*rhs.z;
+}
+
+Quat
+Quat::lerp(const Quat &q2, float t) const
+{
+ Quat q1 = *this;
+ float cos = q1.inner(q2);
+ if(cos < 0)
+ q1 = -q1;
+ return (q1*(1.0f - t) + q2*t).U();
+}
+
+Quat
+Quat::slerp(const Quat &q2, float t) const
+{
+ Quat q1 = *this;
+ float cos = q1.inner(q2);
+ if(cos < 0){
+ cos = -cos;
+ q1 = -q1;
+ }
+ float phi = acos(cos);
+ if(phi > 0.00001){
+ float s = sin(phi);
+ q1 = q1*sin((1.0f-t)*phi)/s + q2*sin(t*phi)/s;
+ }
+ return q1;
+}
+
+void
+Quat::print(std::ostream &of) const
+{
+ of << "Q(" << w << ", " << x << ", " << y << ", " << z << ")";
+}
+
+/*
+ * Quat
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const DQuat &v)
+{
+ v.print(of);
+ return of;
+}
+
+
+DQuat::DQuat(void)
+ : q1(), q2()
+{
+}
+
+DQuat::DQuat(const Quat &q1, const Quat &q2)
+ : q1(q1), q2(q2)
+{
+}
+
+DQuat
+DQuat::operator-(void) const
+{
+ return DQuat(-q1, -q2);
+}
+
+DQuat
+DQuat::operator+(const DQuat &rhs) const
+{
+ return DQuat(this->q1+rhs.q1, this->q2+rhs.q2);
+}
+
+DQuat
+DQuat::operator-(const DQuat &rhs) const
+{
+ return DQuat(this->q1-rhs.q1, this->q2-rhs.q2);
+}
+
+DQuat
+DQuat::operator*(const DQuat &rhs) const
+{
+ return DQuat(this->q1*rhs.q1, this->q1*rhs.q2 + this->q2*rhs.q1);
+}
+
+DQuat
+DQuat::operator*(float rhs) const
+{
+ return DQuat(this->q1*rhs, this->q2*rhs);
+}
+
+DQuat
+DQuat::operator/(float rhs) const
+{
+ return DQuat(this->q1/rhs, this->q2/rhs);
+}
+
+DQuat&
+DQuat::operator+=(const DQuat &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+DQuat&
+DQuat::operator-=(const DQuat &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+DQuat&
+DQuat::operator*=(const DQuat &rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+DQuat&
+DQuat::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+DQuat&
+DQuat::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+bool
+DQuat::operator==(const DQuat &rhs) const
+{
+ return (this->q1 == rhs.q1) &&
+ (this->q2 == rhs.q2);
+}
+
+bool
+DQuat::operator!=(const DQuat &rhs) const
+{
+ return (this->q1 != rhs.q1) ||
+ (this->q2 != rhs.q2);
+}
+
+DQuat
+DQuat::K(void) const
+{
+ return DQuat(q1.K(), -q2.K());
+}
+
+void
+DQuat::print(std::ostream &of) const
+{
+ of << "DQ(" << q1 << ", " << q2 << ")";
+}
+
+/*
+ * Mat3
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const Mat3 &v)
+{
+ v.print(of);
+ return of;
+}
+
+Mat3::Mat3(void)
+{
+ for(int i = 0; i < 3*3; i++)
+ cr[i] = 0.0f;
+}
+
+Mat3::Mat3(float f)
+{
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ e[i][j] = (i == j) ? f : 0.0f;
+}
+
+Mat3::Mat3(float *f)
+{
+ for(int i = 0; i < 3*3; i++)
+ cr[i] = f[i];
+}
+
+Mat3::Mat3(float e00, float e10, float e20,
+ float e01, float e11, float e21,
+ float e02, float e12, float e22)
+{
+ e[0][0] = e00; e[1][0] = e10; e[2][0] = e20;
+ e[0][1] = e01; e[1][1] = e11; e[2][1] = e21;
+ e[0][2] = e02; e[1][2] = e12; e[2][2] = e22;
+}
+
+float*
+Mat3::ptr(void)
+{
+ return &e[0][0];
+}
+
+Mat3
+Mat3::rotation(float theta, const Vec3 &v)
+{
+ Mat3 m(1.0f);
+ float c = cos(theta);
+ float s = sin(theta);
+ m.e[0][0] = v.x*v.x*(1-c) + c;
+ m.e[1][0] = v.x*v.y*(1-c) - v.z*s;
+ m.e[2][0] = v.x*v.z*(1-c) + v.y*s;
+
+ m.e[0][1] = v.y*v.x*(1-c) + v.z*s;
+ m.e[1][1] = v.y*v.y*(1-c) + c;
+ m.e[2][1] = v.y*v.z*(1-c) - v.x*s;
+
+ m.e[0][2] = v.z*v.x*(1-c) - v.y*s;
+ m.e[1][2] = v.z*v.y*(1-c) + v.x*s;
+ m.e[2][2] = v.z*v.z*(1-c) + c;
+ return m;
+}
+
+Mat3
+Mat3::scale(const Vec3 &v)
+{
+ Mat3 m(1.0f);
+ m.e[0][0] = v.x;
+ m.e[1][1] = v.y;
+ m.e[2][2] = v.z;
+ return m;
+}
+
+Mat3
+Mat3::transpose(void) const
+{
+ float e[3][3];
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++){
+ e[j][i] = this->e[i][j];
+ e[i][j] = this->e[j][i];
+ }
+ return Mat3(&e[0][0]);
+}
+
+Mat3
+Mat3::operator+(const Mat3 &rhs) const
+{
+ float e[9];
+ for(int i = 0; i < 3*3; i++)
+ e[i] = this->cr[i] + rhs.cr[i];
+ return Mat3(e);
+}
+
+Mat3
+Mat3::operator-(const Mat3 &rhs) const
+{
+ float e[9];
+ for(int i = 0; i < 3*3; i++)
+ e[i] = this->cr[i] - rhs.cr[i];
+ return Mat3(e);
+}
+
+Mat3
+Mat3::operator*(float rhs) const
+{
+ float e[9];
+ for(int i = 0; i < 3*3; i++)
+ e[i] = this->cr[i]*rhs;
+ return Mat3(e);
+}
+
+Mat3
+Mat3::operator/(float rhs) const
+{
+ float e[9];
+ for(int i = 0; i < 3*3; i++)
+ e[i] = this->cr[i]/rhs;
+ return Mat3(e);
+}
+
+Mat3
+Mat3::operator*(const Mat3 &rhs) const
+{
+ float e[3][3];
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ e[i][j] = this->e[0][j]*rhs.e[i][0] +
+ this->e[1][j]*rhs.e[i][1] +
+ this->e[2][j]*rhs.e[i][2];
+ return Mat3(&e[0][0]);
+}
+
+Vec3
+Mat3::operator*(const Vec3 &rhs) const
+{
+ float e[3];
+ for(int i = 0; i < 3; i++)
+ e[i] = this->e[0][i]*rhs.x +
+ this->e[1][i]*rhs.y +
+ this->e[2][i]*rhs.z;
+ return Vec3(e);
+}
+
+Mat3&
+Mat3::operator+=(const Mat3 &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+Mat3&
+Mat3::operator-=(const Mat3 &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+Mat3&
+Mat3::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Mat3&
+Mat3::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+Mat3&
+Mat3::operator*=(const Mat3 &rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+void
+Mat3::print(std::ostream &of) const
+{
+ #define CM << ", " <<
+ of << "M3(" << e[0][0] CM e[1][0] CM e[2][0] << std::endl;
+ of << " " << e[0][1] CM e[1][1] CM e[2][1] << std::endl;
+ of << " " << e[0][2] CM e[1][2] CM e[2][2] << ")";
+ #undef CM
+}
+
+/*
+ * Mat3
+ */
+
+std::ostream&
+operator<<(std::ostream& of, const Mat4 &v)
+{
+ v.print(of);
+ return of;
+}
+
+Mat4::Mat4(void)
+{
+ for(int i = 0; i < 4*4; i++)
+ cr[i] = 0.0f;
+}
+
+Mat4::Mat4(float f)
+{
+ for(int i = 0; i < 4; i++)
+ for(int j = 0; j < 4; j++)
+ e[i][j] = (i == j) ? f : 0.0f;
+}
+
+Mat4::Mat4(float *f)
+{
+ for(int i = 0; i < 4*4; i++)
+ cr[i] = f[i];
+}
+
+Mat4::Mat4(float e00, float e10, float e20, float e30,
+ float e01, float e11, float e21, float e31,
+ float e02, float e12, float e22, float e32,
+ float e03, float e13, float e23, float e33)
+{
+ e[0][0] = e00; e[1][0] = e10; e[2][0] = e20; e[3][0] = e30;
+ e[0][1] = e01; e[1][1] = e11; e[2][1] = e21; e[3][1] = e31;
+ e[0][2] = e02; e[1][2] = e12; e[2][2] = e22; e[3][2] = e32;
+ e[0][3] = e03; e[1][3] = e13; e[2][3] = e23; e[3][3] = e33;
+}
+
+float*
+Mat4::ptr(void)
+{
+ return &e[0][0];
+}
+
+Mat4
+Mat4::perspective(float fov, float aspect, float n, float f)
+{
+ float r = n*tan(fov*3.14159f/360.0f);
+ float t = r/aspect;
+ return frustum(-r, r, -t, t, n, f);
+}
+
+Mat4
+Mat4::frustum(float l, float r, float b, float t,
+ float n, float f)
+{
+ Mat4 m(1.0f);
+ m.e[0][0] = (2.0f*n)/(r-l);
+ m.e[1][1] = (2.0f*n)/(t-b);
+ m.e[2][0] = (r+l)/(r-l);
+ m.e[2][1] = (t+b)/(t-b);
+// TODO:
+// m.e[2][2] = -(f+n)/(f-n);
+// m.e[2][3] = -1.0f;
+// m.e[3][2] = -2.0f*f*n/(f-n);
+ m.e[2][2] = (f+n)/(f-n);
+ m.e[2][3] = 1.0f;
+ m.e[3][2] = -1.0f*f*n/(f-n);
+ m.e[3][3] = 0.0f;
+ return m;
+}
+
+Mat4
+Mat4::ortho(float l, float r, float b, float t,
+ float n, float f)
+{
+ Mat4 m(1.0f);
+ m.e[0][0] = 2.0f/(r-l);
+ m.e[3][0] = -(r+l)/(r-l);
+ m.e[1][1] = 2.0f/(t-b);
+ m.e[3][1] = -(t+b)/(t-b);
+ m.e[2][2] = -2.0f/(f-n);
+ m.e[3][2] = -(f+n)/(f-n);
+ return m;
+}
+
+Mat4
+Mat4::lookat(const Vec3 &pos, const Vec3 &target, const Vec3 &up)
+{
+ Vec3 forward = (target - pos).normalized();
+ Vec3 side = forward.cross(up).normalized();
+ Vec3 nup = side.cross(forward);
+ Mat4 m(1.0f);
+ m.e[0][0] = side.x;
+ m.e[1][0] = side.y;
+ m.e[2][0] = side.z;
+ m.e[0][1] = nup.x;
+ m.e[1][1] = nup.y;
+ m.e[2][1] = nup.z;
+ m.e[0][2] = -forward.x;
+ m.e[1][2] = -forward.y;
+ m.e[2][2] = -forward.z;
+ m = m*Mat4::translation(-pos);
+// TODO:
+ m.e[0][2] *= -1.0f;
+ m.e[1][2] *= -1.0f;
+ m.e[2][2] *= -1.0f;
+ m.e[3][2] *= -1.0f;
+ return m;
+}
+
+Mat4
+Mat4::translation(const Vec3 &v)
+{
+ Mat4 m(1.0f);
+ m.e[3][0] = v.x;
+ m.e[3][1] = v.y;
+ m.e[3][2] = v.z;
+ return m;
+}
+
+Mat4
+Mat4::rotation(float theta, const Vec3 &v)
+{
+ Mat4 m(1.0f);
+ float c = cos(theta);
+ float s = sin(theta);
+ m.e[0][0] = v.x*v.x*(1-c) + c;
+ m.e[1][0] = v.x*v.y*(1-c) - v.z*s;
+ m.e[2][0] = v.x*v.z*(1-c) + v.y*s;
+
+ m.e[0][1] = v.y*v.x*(1-c) + v.z*s;
+ m.e[1][1] = v.y*v.y*(1-c) + c;
+ m.e[2][1] = v.y*v.z*(1-c) - v.x*s;
+
+ m.e[0][2] = v.z*v.x*(1-c) - v.y*s;
+ m.e[1][2] = v.z*v.y*(1-c) + v.x*s;
+ m.e[2][2] = v.z*v.z*(1-c) + c;
+ return m;
+}
+
+Mat4
+Mat4::scale(const Vec3 &v)
+{
+ Mat4 m(1.0f);
+ m.e[0][0] = v.x;
+ m.e[1][1] = v.y;
+ m.e[2][2] = v.z;
+ return m;
+}
+
+Mat4
+Mat4::transpose(void) const
+{
+ float e[4][4];
+ for(int i = 0; i < 4; i++)
+ for(int j = 0; j < 4; j++){
+ e[j][i] = this->e[i][j];
+ e[i][j] = this->e[j][i];
+ }
+ return Mat4(&e[0][0]);
+}
+
+Mat4
+Mat4::operator+(const Mat4 &rhs) const
+{
+ float e[16];
+ for(int i = 0; i < 4*4; i++)
+ e[i] = this->cr[i] + rhs.cr[i];
+ return Mat4(e);
+}
+
+Mat4
+Mat4::operator-(const Mat4 &rhs) const
+{
+ float e[16];
+ for(int i = 0; i < 4*4; i++)
+ e[i] = this->cr[i] - rhs.cr[i];
+ return Mat4(e);
+}
+
+Mat4
+Mat4::operator*(float rhs) const
+{
+ float e[16];
+ for(int i = 0; i < 4*4; i++)
+ e[i] = this->cr[i]*rhs;
+ return Mat4(e);
+}
+
+Mat4
+Mat4::operator/(float rhs) const
+{
+ float e[16];
+ for(int i = 0; i < 4*4; i++)
+ e[i] = this->cr[i]/rhs;
+ return Mat4(e);
+}
+
+Mat4
+Mat4::operator*(const Mat4 &rhs) const
+{
+ float e[4][4];
+ for(int i = 0; i < 4; i++)
+ for(int j = 0; j < 4; j++)
+ e[i][j] = this->e[0][j]*rhs.e[i][0] +
+ this->e[1][j]*rhs.e[i][1] +
+ this->e[2][j]*rhs.e[i][2] +
+ this->e[3][j]*rhs.e[i][3];
+ return Mat4(&e[0][0]);
+}
+
+Vec4
+Mat4::operator*(const Vec4 &rhs) const
+{
+ float e[4];
+ for(int i = 0; i < 4; i++)
+ e[i] = this->e[0][i]*rhs.x +
+ this->e[1][i]*rhs.y +
+ this->e[2][i]*rhs.z +
+ this->e[3][i]*rhs.w;
+ return Vec4(e);
+}
+
+Mat4&
+Mat4::operator+=(const Mat4 &rhs)
+{
+ *this = *this + rhs;
+ return *this;
+}
+
+Mat4&
+Mat4::operator-=(const Mat4 &rhs)
+{
+ *this = *this - rhs;
+ return *this;
+}
+
+Mat4&
+Mat4::operator*=(float rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+Mat4&
+Mat4::operator/=(float rhs)
+{
+ *this = *this / rhs;
+ return *this;
+}
+
+Mat4&
+Mat4::operator*=(const Mat4 &rhs)
+{
+ *this = *this * rhs;
+ return *this;
+}
+
+void
+Mat4::print(std::ostream &of) const
+{
+ #define CM << ", " <<
+ of << "M4(" << e[0][0] CM e[1][0] CM e[2][0] CM e[3][0] << std::endl;
+ of << " " << e[0][1] CM e[1][1] CM e[2][1] CM e[3][1] << std::endl;
+ of << " " << e[0][2] CM e[1][2] CM e[2][2] CM e[3][2] << std::endl;
+ of << " " << e[0][3] CM e[1][3] CM e[2][3] CM e[3][3] << ")";
+ #undef CM
+}
+
+
+
+
+
+Vec3::Vec3(const Vec4 &v)
+ : x(v.x), y(v.y), z(v.z)
+{
+}
+
+Vec3::Vec3(const Quat &q)
+ : x(q.x), y(q.y), z(q.z)
+{
+}
+
+Vec4::Vec4(const Vec3 &v, float w)
+ : x(v.x), y(v.y), z(v.z), w(w)
+{
+}
+
+Vec4::Vec4(const Quat &q)
+ : x(q.x), y(q.y), z(q.z), w(q.w)
+{
+}
+
+Quat::Quat(const Vec3 &v)
+ : w(0), x(v.x), y(v.y), z(v.z)
+{
+}
+
+Quat::Quat(float w, const Vec3 &v)
+ : w(w), x(v.x), y(v.y), z(v.z)
+{
+}
+
+Quat::Quat(const Vec4 &v)
+ : w(v.w), x(v.x), y(v.y), z(v.z)
+{
+}
+
+Quat::Quat(const Mat3 &m)
+{
+ float trace, s, q[4];
+ int i, j, k;
+
+ int nxt[3] = {1, 2, 0};
+
+ trace = m.e[0][0] + m.e[1][1] + m.e[2][2];
+ if(trace > 0.0f){
+ s = sqrt(trace + 1.0f);
+ this->w = s / 2.0f;
+ s = 0.5f / s;
+ this->x = (m.e[2][1] - m.e[1][2]) * s;
+ this->y = (m.e[0][2] - m.e[2][0]) * s;
+ this->z = (m.e[1][0] - m.e[0][1]) * s;
+ }else{
+ i = 0;
+ if(m.e[1][1] > m.e[0][0]) i = 1;
+ if(m.e[2][2] > m.e[i][i]) i = 2;
+ j = nxt[i];
+ k = nxt[j];
+ s = sqrt((m.e[i][i] - m.e[j][j] - m.e[k][k]) + 1.0);
+ q[i] = s*0.5f;
+ if(q[i] != 0.0f) s = 0.5f / s;
+ q[3] = (m.e[k][j] - m.e[j][k]) * s;
+ q[j] = (m.e[j][i] + m.e[i][j]) * s;
+ q[k] = (m.e[k][i] + m.e[i][k]) * s;
+ this->w = q[3];
+ this->x = q[0];
+ this->y = q[1];
+ this->z = q[2];
+ }
+}
+
+Mat3::Mat3(const Mat4 &m)
+{
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ this->e[i][j] = m.e[i][j];
+}
+
+Mat4::Mat4(const Mat3 &m)
+{
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ this->e[i][j] = m.e[i][j];
+ this->e[0][3] = 0.0f;
+ this->e[1][3] = 0.0f;
+ this->e[2][3] = 0.0f;
+ this->e[3][3] = 1.0f;
+ this->e[3][2] = 0.0f;
+ this->e[3][1] = 0.0f;
+ this->e[3][0] = 0.0f;
+}
+
+Mat3
+Mat3::rotation(const Quat &v)
+{
+ Mat3 m(1.0f);
+ m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z;
+ m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z;
+ m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z;
+ m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y;
+ m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z;
+ m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x;
+ m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y;
+ m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z;
+ m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z;
+ return m;
+}
+
+Mat4
+Mat4::rotation(const Quat &q)
+{
+ Mat4 m(1.0f);
+ m.e[0][0] = q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z;
+ m.e[1][0] = 2*q.x*q.y - 2*q.w*q.z;
+ m.e[2][0] = 2*q.w*q.y + 2*q.x*q.z;
+ m.e[0][1] = 2*q.w*q.z + 2*q.x*q.y;
+ m.e[1][1] = q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z;
+ m.e[2][1] = 2*q.y*q.z - 2*q.w*q.x;
+ m.e[0][2] = 2*q.x*q.z - 2*q.w*q.y;
+ m.e[1][2] = 2*q.w*q.x + 2*q.y*q.z;
+ m.e[2][2] = q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z;
+ return m;
+}
+
+Mat4
+Mat4::transrot(const DQuat &q)
+{
+ const Quat &q1 = q.q1;
+ const Quat &q2 = q.q2;
+ Mat4 m(1.0f);
+ m.e[0][0] = q1.w*q1.w + q1.x*q1.x - q1.y*q1.y - q1.z*q1.z;
+ m.e[1][0] = 2*q1.x*q1.y - 2*q1.w*q1.z;
+ m.e[2][0] = 2*q1.w*q1.y + 2*q1.x*q1.z;
+ m.e[0][1] = 2*q1.w*q1.z + 2*q1.x*q1.y;
+ m.e[1][1] = q1.w*q1.w - q1.x*q1.x + q1.y*q1.y - q1.z*q1.z;
+ m.e[2][1] = 2*q1.y*q1.z - 2*q1.w*q1.x;
+ m.e[0][2] = 2*q1.x*q1.z - 2*q1.w*q1.y;
+ m.e[1][2] = 2*q1.w*q1.x + 2*q1.y*q1.z;
+ m.e[2][2] = q1.w*q1.w - q1.x*q1.x - q1.y*q1.y + q1.z*q1.z;
+ m.e[3][0] = 2*(q1.w*q2.x - q2.w*q1.x + q1.y*q2.z - q1.z*q2.y);
+ m.e[3][1] = 2*(q1.w*q2.y - q2.w*q1.y + q1.z*q2.x - q1.x*q2.z);
+ m.e[3][2] = 2*(q1.w*q2.z - q2.w*q1.z + q1.x*q2.y - q1.y*q2.x);
+ return m;
+}
+
diff --git a/tools/d3d9/math/conversion.h b/tools/d3d9/math/conversion.h
new file mode 100644
index 0000000..01e7897
--- /dev/null
+++ b/tools/d3d9/math/conversion.h
@@ -0,0 +1,93 @@
+#ifndef MATH_CONVERSION_H
+#define MATH_CONVERSION_H
+
+Vec3::Vec3(const Vec4 &v)
+ : x(v.x), y(v.y), z(v.z)
+{
+}
+
+Vec3::Vec3(const Quat &q)
+ : x(q.x), y(q.y), z(q.z)
+{
+}
+
+Vec4::Vec4(const Vec3 &v, float w)
+ : x(v.x), y(v.y), z(v.z), w(w)
+{
+}
+
+Vec4::Vec4(const Quat &q)
+ : x(q.x), y(q.y), z(q.z), w(q.w)
+{
+}
+
+Quat::Quat(const Vec3 &v)
+ : x(v.x), y(v.y), z(v.z)
+{
+}
+
+Quat::Quat(float w, const Vec3 &v)
+ : w(w), x(v.x), y(v.y), z(v.z)
+{
+}
+
+Quat::Quat(const Vec4 &v)
+ : w(v.w), x(v.x), y(v.y), z(v.z)
+{
+}
+
+Mat3::Mat3(const Mat4 &m)
+{
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ this->e[i][j] = m.e[i][j];
+}
+
+Mat4::Mat4(const Mat3 &m)
+{
+ for(int i = 0; i < 3; i++)
+ for(int j = 0; j < 3; j++)
+ this->e[i][j] = m.e[i][j];
+ this->e[0][3] = 0.0f;
+ this->e[1][3] = 0.0f;
+ this->e[2][3] = 0.0f;
+ this->e[3][3] = 1.0f;
+ this->e[3][2] = 0.0f;
+ this->e[3][1] = 0.0f;
+ this->e[3][0] = 0.0f;
+}
+
+Mat4
+Mat4::rotation(const Quat &v)
+{
+ Mat4 m(1.0f);
+ m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z;
+ m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z;
+ m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z;
+ m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y;
+ m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z;
+ m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x;
+ m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y;
+ m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z;
+ m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z;
+ return m;
+}
+
+Mat3
+Mat3::rotation(const Quat &v)
+{
+ Mat3 m(1.0f);
+ m.e[0][0] = v.w*v.w + v.x*v.x - v.y*v.y - v.z*v.z;
+ m.e[1][0] = 2*v.x*v.y - 2*v.w*v.z;
+ m.e[2][0] = 2*v.w*v.y + 2*v.x*v.z;
+ m.e[0][1] = 2*v.w*v.z + 2*v.x*v.y;
+ m.e[1][1] = v.w*v.w - v.x*v.x + v.y*v.y - v.z*v.z;
+ m.e[2][1] = 2*v.y*v.z - 2*v.w*v.x;
+ m.e[0][2] = 2*v.x*v.z - 2*v.w*v.y;
+ m.e[1][2] = 2*v.w*v.x + 2*v.y*v.z;
+ m.e[2][2] = v.w*v.w - v.x*v.x - v.y*v.y + v.z*v.z;
+ return m;
+}
+
+#endif
+
diff --git a/tools/d3d9/math/dquat.h b/tools/d3d9/math/dquat.h
new file mode 100644
index 0000000..2690cea
--- /dev/null
+++ b/tools/d3d9/math/dquat.h
@@ -0,0 +1,45 @@
+#ifndef MATH_DQUAT_H
+#define MATH_DQUAT_H
+
+#include
+#include
+
+class Vec3;
+class Vec4;
+
+class DQuat {
+public:
+ Quat q1, q2;
+
+ DQuat(void);
+ DQuat(const Quat &q1, const Quat &q2);
+ DQuat operator-(void) const;
+ DQuat operator+(const DQuat &rhs) const;
+ DQuat operator-(const DQuat &rhs) const;
+ DQuat operator*(const DQuat &rhs) const;
+ DQuat operator*(float rhs) const;
+ DQuat operator/(float rhs) const;
+ DQuat &operator+=(const DQuat &rhs);
+ DQuat &operator-=(const DQuat &rhs);
+ DQuat &operator*=(const DQuat &rhs);
+ DQuat &operator*=(float rhs);
+ DQuat &operator/=(float rhs);
+ bool operator==(const DQuat &rhs) const;
+ bool operator!=(const DQuat &rhs) const;
+
+// DQuat inv(void) const;
+ DQuat K(void) const; /* conjugate */
+// DQuat S(void) const; /* scalar */
+// DQuat V(void) const; /* vector */
+// float T(void) const; /* tensor */
+// float N(void) const; /* norm = tensor^2 */
+// DQuat U(void) const; /* versor */
+// DQuat wedge(const Quat &rhs) const;
+// float inner(const Quat &rhs) const;
+// DQuat slerp(const Quat &rhs, float t) const;
+
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/d3d9/math/mat3.h b/tools/d3d9/math/mat3.h
new file mode 100644
index 0000000..e1c6034
--- /dev/null
+++ b/tools/d3d9/math/mat3.h
@@ -0,0 +1,43 @@
+#ifndef MATH_MATRIX3_H
+#define MATH_MATRIX3_H
+
+#include
+#include
+
+class Mat4;
+
+class Mat3 {
+public:
+ union {
+ float e[3][3];
+ float cr[9];
+ };
+
+ Mat3(void);
+ Mat3(float f);
+ Mat3(float *f);
+ Mat3(float e00, float e10, float e20,
+ float e01, float e11, float e21,
+ float e02, float e12, float e22);
+ Mat3(const Mat4 &m);
+ float *ptr(void);
+ static Mat3 rotation(float theta, const Vec3 &v);
+ static Mat3 rotation(const Quat &v);
+ static Mat3 scale(const Vec3 &v);
+ Mat3 transpose(void) const;
+ Mat3 operator+(const Mat3 &rhs) const;
+ Mat3 operator-(const Mat3 &rhs) const;
+ Mat3 operator*(float rhs) const;
+ Mat3 operator/(float rhs) const;
+ Mat3 operator*(const Mat3 &rhs) const;
+ Vec3 operator*(const Vec3 &rhs) const;
+ Mat3 &operator+=(const Mat3 &rhs);
+ Mat3 &operator-=(const Mat3 &rhs);
+ Mat3 &operator*=(float rhs);
+ Mat3 &operator/=(float rhs);
+ Mat3 &operator*=(const Mat3 &rhs);
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/d3d9/math/mat4.h b/tools/d3d9/math/mat4.h
new file mode 100644
index 0000000..1bac359
--- /dev/null
+++ b/tools/d3d9/math/mat4.h
@@ -0,0 +1,52 @@
+#ifndef MATH_MATRIX4_H
+#define MATH_MATRIX4_H
+
+#include
+#include
+
+class Mat3;
+
+class Mat4 {
+public:
+ union {
+ float e[4][4];
+ float cr[16];
+ };
+
+ Mat4(void);
+ Mat4(float f);
+ Mat4(float *f);
+ Mat4(float e00, float e10, float e20, float e30,
+ float e01, float e11, float e21, float e31,
+ float e02, float e12, float e22, float e32,
+ float e03, float e13, float e23, float e33);
+ Mat4(const Mat3 &m);
+ float *ptr(void);
+ static Mat4 perspective(float fov, float aspect, float n, float f);
+ static Mat4 frustum(float l, float r, float b, float t,
+ float n, float f);
+ static Mat4 ortho(float l, float r, float b, float t,
+ float n, float f);
+ static Mat4 lookat(const Vec3 &pos, const Vec3 &target, const Vec3 &up);
+ static Mat4 translation(const Vec3 &v);
+ static Mat4 rotation(float theta, const Vec3 &v);
+ static Mat4 rotation(const Quat &q);
+ static Mat4 transrot(const DQuat &q);
+ static Mat4 scale(const Vec3 &v);
+ Mat4 transpose(void) const;
+ Mat4 operator+(const Mat4 &rhs) const;
+ Mat4 operator-(const Mat4 &rhs) const;
+ Mat4 operator*(float rhs) const;
+ Mat4 operator/(float rhs) const;
+ Mat4 operator*(const Mat4 &rhs) const;
+ Vec4 operator*(const Vec4 &rhs) const;
+ Mat4 &operator+=(const Mat4 &rhs);
+ Mat4 &operator-=(const Mat4 &rhs);
+ Mat4 &operator*=(float rhs);
+ Mat4 &operator/=(float rhs);
+ Mat4 &operator*=(const Mat4 &rhs);
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/d3d9/math/math.h b/tools/d3d9/math/math.h
new file mode 100644
index 0000000..0c04fa3
--- /dev/null
+++ b/tools/d3d9/math/math.h
@@ -0,0 +1,21 @@
+#ifndef MATH_H
+#define MATH_H
+
+#include "vec3.h"
+#include "vec4.h"
+#include "quat.h"
+#include "dquat.h"
+#include "mat3.h"
+#include "mat4.h"
+
+std::ostream &operator<<(std::ostream& of, const Vec3 &v);
+std::ostream &operator<<(std::ostream& of, const Vec4 &v);
+std::ostream &operator<<(std::ostream& of, const Quat &v);
+std::ostream &operator<<(std::ostream& of, const DQuat &v);
+std::ostream &operator<<(std::ostream& of, const Mat3 &v);
+std::ostream &operator<<(std::ostream& of, const Mat4 &v);
+
+#define PI 3.14159265359f
+
+
+#endif
diff --git a/tools/d3d9/math/quat.h b/tools/d3d9/math/quat.h
new file mode 100644
index 0000000..7da753a
--- /dev/null
+++ b/tools/d3d9/math/quat.h
@@ -0,0 +1,54 @@
+#ifndef MATH_QUAT_H
+#define MATH_QUAT_H
+
+#include
+#include
+
+class Vec3;
+class Vec4;
+class Mat3;
+
+/* Hamilton style */
+
+class Quat {
+public:
+ float w, x, y, z;
+
+ Quat(void);
+ Quat(float w);
+ Quat(float x, float y, float z);
+ Quat(float w, float x, float y, float z);
+ Quat(float w, const Vec3 &v);
+ Quat(const Vec3 &v);
+ Quat(const Vec4 &v);
+ Quat(const Mat3 &m);
+ float *ptr(void);
+ Quat operator-(void) const;
+ Quat operator+(const Quat &rhs) const;
+ Quat operator-(const Quat &rhs) const;
+ Quat operator*(const Quat &rhs) const;
+ Quat operator*(float rhs) const;
+ Quat operator/(float rhs) const;
+ Quat &operator+=(const Quat &rhs);
+ Quat &operator-=(const Quat &rhs);
+ Quat &operator*=(const Quat &rhs);
+ Quat &operator*=(float rhs);
+ Quat &operator/=(float rhs);
+ bool operator==(const Quat &rhs) const;
+ bool operator!=(const Quat &rhs) const;
+ Quat inv(void) const;
+ Quat K(void) const; /* conjugate */
+ Quat S(void) const; /* scalar */
+ Quat V(void) const; /* vector */
+ float T(void) const; /* tensor */
+ float N(void) const; /* norm = tensor^2 */
+ Quat U(void) const; /* versor */
+ Quat wedge(const Quat &rhs) const;
+ float inner(const Quat &rhs) const;
+ Quat lerp(const Quat &rhs, float t) const;
+ Quat slerp(const Quat &rhs, float t) const;
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/d3d9/math/vec3.h b/tools/d3d9/math/vec3.h
new file mode 100644
index 0000000..5b21593
--- /dev/null
+++ b/tools/d3d9/math/vec3.h
@@ -0,0 +1,40 @@
+#ifndef MATH_VECTOR3_H
+#define MATH_VECTOR3_H
+
+#include
+#include
+
+class Vec4;
+class Quat;
+
+class Vec3 {
+public:
+ float x, y, z;
+
+ Vec3(void);
+ Vec3(float x, float y, float z);
+ Vec3(float *v);
+ Vec3(const Vec4 &v);
+ Vec3(const Quat &q);
+ float *ptr(void);
+ Vec3 operator-(void) const;
+ Vec3 operator+(const Vec3 &rhs) const;
+ Vec3 operator-(const Vec3 &rhs) const;
+ Vec3 operator*(float rhs) const;
+ Vec3 operator/(float rhs) const;
+ Vec3 &operator+=(const Vec3 &rhs);
+ Vec3 &operator-=(const Vec3 &rhs);
+ Vec3 &operator*=(float rhs);
+ Vec3 &operator/=(float rhs);
+ bool operator==(const Vec3 &rhs) const;
+ bool operator!=(const Vec3 &rhs) const;
+ float norm(void) const;
+ float normsq(void) const;
+ Vec3 normalized(void) const;
+ float dot(const Vec3 &rhs) const;
+ Vec3 cross(const Vec3 &rhs) const;
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/d3d9/math/vec4.h b/tools/d3d9/math/vec4.h
new file mode 100644
index 0000000..90920f7
--- /dev/null
+++ b/tools/d3d9/math/vec4.h
@@ -0,0 +1,39 @@
+#ifndef MATH_VECTOR4_H
+#define MATH_VECTOR4_H
+
+#include
+#include
+
+class Vec3;
+class Quat;
+
+class Vec4 {
+public:
+ float x, y, z, w;
+
+ Vec4(void);
+ Vec4(float x, float y, float z, float w);
+ Vec4(float *v);
+ Vec4(const Vec3 &v, float w = 0.0f);
+ Vec4(const Quat &w);
+ float *ptr(void);
+ Vec4 operator-(void) const;
+ Vec4 operator+(const Vec4 &rhs) const;
+ Vec4 operator-(const Vec4 &rhs) const;
+ Vec4 operator*(float rhs) const;
+ Vec4 operator/(float rhs) const;
+ Vec4 &operator+=(const Vec4 &rhs);
+ Vec4 &operator-=(const Vec4 &rhs);
+ Vec4 &operator*=(float rhs);
+ Vec4 &operator/=(float rhs);
+ bool operator==(const Vec4 &rhs) const;
+ bool operator!=(const Vec4 &rhs) const;
+ float norm(void) const;
+ float normsq(void) const;
+ Vec4 normalized(void) const;
+ float dot(const Vec4 &rhs) const;
+ void print(std::ostream &of) const;
+};
+
+#endif
+
diff --git a/tools/dffwrite.cpp b/tools/dffwrite/dffwrite.cpp
similarity index 93%
rename from tools/dffwrite.cpp
rename to tools/dffwrite/dffwrite.cpp
index 2c45bd9..5f54bfd 100644
--- a/tools/dffwrite.cpp
+++ b/tools/dffwrite/dffwrite.cpp
@@ -4,8 +4,8 @@
#include
#include
-#include "../rw.h"
-#include "../src/gtaplg.h"
+#include
+#include
using namespace std;
@@ -15,6 +15,7 @@ main(int argc, char *argv[])
// rw::version = 0x31000;
// rw::build = 0;
+// rw::version = 0x32000;
// rw::version = 0x33002;
// rw::version = 0x30200;
@@ -75,9 +76,9 @@ main(int argc, char *argv[])
// ofstream out(argv[2], ios::binary);
// rw::StreamFile out;
// out.open(argv[2], "wb");
- data = new rw::uint8[256*1024];
+ data = new rw::uint8[1024*1024];
rw::StreamMemory out;
- out.open(data, 0, 256*1024);
+ out.open(data, 0, 1024*1024);
c->streamWrite(&out);
cf = fopen(argv[2], "wb");
diff --git a/tools/dffwrite/dffwrite.vcxproj b/tools/dffwrite/dffwrite.vcxproj
new file mode 100644
index 0000000..c9ec792
--- /dev/null
+++ b/tools/dffwrite/dffwrite.vcxproj
@@ -0,0 +1,112 @@
+
+
+
+
+ Debug - null
+ Win32
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}
+ dffwrite
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/dumprwtree.cpp b/tools/dumprwtree/dumprwtree.cpp
similarity index 99%
rename from tools/dumprwtree.cpp
rename to tools/dumprwtree/dumprwtree.cpp
index 04e58ec..f5ee4ae 100644
--- a/tools/dumprwtree.cpp
+++ b/tools/dumprwtree/dumprwtree.cpp
@@ -4,7 +4,7 @@
#include
#include
-#include "../rw.h"
+#include
using namespace std;
using namespace rw;
diff --git a/tools/dumprwtree/dumprwtree.vcxproj b/tools/dumprwtree/dumprwtree.vcxproj
new file mode 100644
index 0000000..cf3dc60
--- /dev/null
+++ b/tools/dumprwtree/dumprwtree.vcxproj
@@ -0,0 +1,109 @@
+
+
+
+
+ Debug - null
+ Win32
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}
+ dumprwtree
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)\
+
+
+
+ Level3
+ Disabled
+ true
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/insttest.cpp b/tools/insttest/insttest.cpp
old mode 100755
new mode 100644
similarity index 87%
rename from tools/insttest.cpp
rename to tools/insttest/insttest.cpp
index f922b33..880b8b9
--- a/tools/insttest.cpp
+++ b/tools/insttest/insttest.cpp
@@ -4,8 +4,8 @@
#include
#include
-#include "../rw.h"
-#include "../src/gtaplg.h"
+#include
+#include
using namespace std;
using namespace rw;
@@ -31,13 +31,14 @@ main(int argc, char *argv[])
rw::Atomic::init();
// rw::platform = rw::PLATFORM_PS2;
- rw::platform = rw::PLATFORM_OGL;
+// rw::platform = rw::PLATFORM_OGL;
+ rw::platform = rw::PLATFORM_XBOX;
int uninstance = 0;
int arg = 1;
if(argc < 2){
- printf("usage: %s [-u] ps2.dff\n", argv[0]);
+ printf("usage: %s [-u] in.dff\n", argv[0]);
return 0;
}
@@ -45,7 +46,7 @@ main(int argc, char *argv[])
uninstance++;
arg++;
if(argc < 3){
- printf("usage: %s [-u] ps2.dff\n", argv[0]);
+ printf("usage: %s [-u] in.dff\n", argv[0]);
return 0;
}
}
@@ -85,9 +86,9 @@ main(int argc, char *argv[])
p->instance(a);
}
- data = new rw::uint8[512*1024];
+ data = new rw::uint8[1024*1024];
rw::StreamMemory out;
- out.open(data, 0, 512*1024);
+ out.open(data, 0, 1024*1024);
c->streamWrite(&out);
FILE *cf = fopen("out.dff", "wb");
diff --git a/tools/insttest/insttest.vcxproj b/tools/insttest/insttest.vcxproj
new file mode 100644
index 0000000..11826d3
--- /dev/null
+++ b/tools/insttest/insttest.vcxproj
@@ -0,0 +1,112 @@
+
+
+
+
+ Debug - null
+ Win32
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {2592ED29-F258-4949-AB45-7B873BF697F7}
+ insttest
+
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ true
+ v120
+ MultiByte
+
+
+ Application
+ false
+ v120
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)
+ $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(SolutionDir)$(Configuration)
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ Disabled
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
+
+
+ true
+ true
+ true
+ librw.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
\ No newline at end of file