mirror of https://github.com/aap/librw.git
415 lines
11 KiB
C++
415 lines
11 KiB
C++
#include "d3dUtility.h"
|
|
#include <DirectXMath.h>
|
|
using namespace DirectX;
|
|
|
|
#include <rw.h>
|
|
#include <src/gtaplg.h>
|
|
#include "math/math.h"
|
|
#include "camera.h"
|
|
|
|
IDirect3DDevice9 *Device = 0;
|
|
|
|
Camera *camera;
|
|
|
|
namespace rw {
|
|
|
|
namespace d3d {
|
|
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
namespace d3d9 {
|
|
using namespace d3d;
|
|
|
|
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->numVertices,
|
|
inst->startIndex, inst->numPrimitives);
|
|
inst++;
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace d3d8 {
|
|
using namespace d3d;
|
|
|
|
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);
|
|
|
|
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->SetFVF(inst->vertexShader);
|
|
Device->SetStreamSource(0, (IDirect3DVertexBuffer9*)inst->vertexBuffer, 0, inst->stride);
|
|
Device->SetIndices((IDirect3DIndexBuffer9*)inst->indexBuffer);
|
|
uint32 numPrim = inst->primType == D3DPT_TRIANGLESTRIP ? inst->numIndices-2 : inst->numIndices/3;
|
|
Device->DrawIndexedPrimitive((D3DPRIMITIVETYPE)inst->primType, inst->baseIndex,
|
|
0, inst->numVertices, 0, numPrim);
|
|
inst++;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
rw::Clump *clump;
|
|
void (*renderCB)(rw::Atomic*) = NULL;
|
|
|
|
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::d3d::registerNativeRaster();
|
|
|
|
rw::platform = rw::PLATFORM_D3D9;
|
|
rw::d3d::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 = "out2.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);
|
|
}
|
|
if(rw::platform == rw::PLATFORM_D3D8)
|
|
renderCB = rw::d3d8::drawAtomic;
|
|
else if(rw::platform == rw::PLATFORM_D3D9)
|
|
renderCB = rw::d3d9::drawAtomic;
|
|
|
|
// 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;
|
|
renderCB(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;
|
|
} |