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