#include "impl.h" #include using namespace TglImpl; struct ViewportAppData { ViewportAppData(IDirect3DRM2* pRenderer); ~ViewportAppData(); IDirect3DRMFrame2* m_pLightFrame; IDirect3DRMFrame2* m_pCamera; IDirect3DRMFrame2* m_pLastRenderedFrame; float m_backgroundColorRed; float m_backgroundColorGreen; float m_backgroundColorBlue; }; DECOMP_SIZE_ASSERT(ViewportAppData, 0x18); // FUNCTION: LEGO1 0x100a10b0 // FUNCTION: BETA10 0x10168920 ViewportAppData::ViewportAppData(IDirect3DRM2* pRenderer) { Result result = ResultVal(pRenderer->CreateFrame(NULL, &m_pLightFrame)); assert(Succeeded(result)); m_pCamera = NULL; m_pLastRenderedFrame = NULL; m_backgroundColorRed = 0.0f; m_backgroundColorGreen = 0.0f; m_backgroundColorBlue = 0.0f; } // FUNCTION: LEGO1 0x100a10e0 // FUNCTION: BETA10 0x101689bd ViewportAppData::~ViewportAppData() { int refCount; IDirect3DRMFrameArray* pChildFrames; IDirect3DRMFrame* pChildFrame = NULL; Result result = ResultVal(m_pLightFrame->GetChildren(&pChildFrames)); assert(Succeeded(result)); for (int i = 0; i < (int) pChildFrames->GetSize(); i++) { result = ResultVal(pChildFrames->GetElement(i, &pChildFrame)); assert(Succeeded(result)); result = ResultVal(m_pLightFrame->DeleteChild(pChildFrame)); assert(Succeeded(result)); refCount = pChildFrame->Release(); // GetElement() does AddRef() assert(refCount >= 1); } refCount = pChildFrames->Release(); assert(refCount == 0); refCount = m_pLightFrame->Release(); assert(refCount == 0); } // Forward declare to satisfy order check void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg); // FUNCTION: LEGO1 0x100a1160 // FUNCTION: BETA10 0x10168ba5 Result ViewImpl::ViewportCreateAppData( IDirect3DRM2* pDevice, IDirect3DRMViewport* pViewport, IDirect3DRMFrame2* pCamera ) { ViewportAppData* pViewportAppData = new ViewportAppData(pDevice); assert(pViewportAppData); pViewportAppData->m_pCamera = pCamera; assert(!pViewport->GetAppData()); Result result = ResultVal(pViewport->SetAppData(reinterpret_cast(pViewportAppData))); assert(Succeeded(result)); assert(reinterpret_cast(pViewport->GetAppData()) == pViewportAppData); if (Succeeded(result)) { result = ResultVal(pViewport->AddDestroyCallback(ViewportDestroyCallback, pViewportAppData)); assert(Succeeded(result)); } if (!Succeeded(result)) { delete pViewportAppData; pViewport->SetAppData(0); } return result; } // FUNCTION: BETA10 0x1016bd80 inline Result ViewRestoreFrameAfterRender( IDirect3DRMFrame* pFrame, IDirect3DRMFrame* pCamera, IDirect3DRMFrame* pLightFrame ) { Result result = Success; if (pFrame) { // remove camera and light frame from frame that was rendered // this doesn't destroy the camera as it is still the camera of the viewport... result = ResultVal(pFrame->DeleteChild(pCamera)); assert(Succeeded(result)); assert((pCamera->AddRef(), pCamera->Release()) > 0); result = ResultVal(pFrame->DeleteChild(pLightFrame)); assert(Succeeded(result)); // decrease frame's ref count (it was increased in ViewPrepareFrameForRender()) pFrame->Release(); } return result; } // FIXME: from LEGO1/tgl/d3drm/view.cpp // FUNCTION: LEGO1 0x100a1240 // FUNCTION: BETA10 0x10168dc9 void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg) { ViewportAppData* pViewportAppData = reinterpret_cast(pArg); assert(static_cast(pObject)); assert(pViewportAppData); Result result = ViewRestoreFrameAfterRender( pViewportAppData->m_pLastRenderedFrame, pViewportAppData->m_pCamera, pViewportAppData->m_pLightFrame ); assert(Succeeded(result)); delete pViewportAppData; } // FUNCTION: LEGO1 0x100a1290 // FUNCTION: BETA10 0x10168eab Result ViewportPickImpl( IDirect3DRMViewport* pViewport, int x, int y, const GroupImpl** ppGroupsToPickFrom, int groupsToPickFromCount, const Group**& rppPickedGroups, int& rPickedGroupCount ) { // Left unimplemented in shipped game. return Error; } inline ViewportAppData* ViewportGetData(IDirect3DRMViewport* pViewport) { return reinterpret_cast(pViewport->GetAppData()); } // FUNCTION: BETA10 0x10170ab0 inline IDirect3DRMFrame* ViewportGetLightFrame(IDirect3DRMViewport* pViewport) { assert(pViewport->GetAppData()); return reinterpret_cast(pViewport->GetAppData())->m_pLightFrame; } // FUNCTION: LEGO1 0x100a2d80 // FUNCTION: BETA10 0x1016e640 void* ViewImpl::ImplementationDataPtr() { return reinterpret_cast(&m_data); } // FUNCTION: BETA10 0x10170a40 inline Result ViewAddLight(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame* pLight) { IDirect3DRMFrame* pLightFrame = ViewportGetLightFrame(pViewport); assert(pLightFrame); return ResultVal(pLightFrame->AddChild(const_cast(pLight))); } // FUNCTION: BETA10 0x101709a0 inline Result ViewImpl::Add(const LightImpl& rLight) { assert(m_data); assert(rLight.ImplementationData()); return ViewAddLight(m_data, rLight.ImplementationData()); } // FUNCTION: LEGO1 0x100a2d90 // FUNCTION: BETA10 0x1016e690 Result ViewImpl::Add(const Light* pLight) { assert(m_data); assert(pLight); return Add(*static_cast(pLight)); } // FUNCTION: BETA10 0x10170bb0 inline Result ViewRemoveLight(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame* pLight) { IDirect3DRMFrame* pLightFrame = ViewportGetLightFrame(pViewport); assert(pLightFrame); return ResultVal(pLightFrame->DeleteChild(const_cast(pLight))); } // FUNCTION: BETA10 0x10170b10 inline Result ViewImpl::Remove(const LightImpl& rLight) { assert(m_data); assert(rLight.ImplementationData()); return ViewRemoveLight(m_data, rLight.ImplementationData()); } // FUNCTION: LEGO1 0x100a2dc0 // FUNCTION: BETA10 0x1016e710 Result ViewImpl::Remove(const Light* pLight) { assert(m_data); assert(pLight); return Remove(*static_cast(pLight)); } // FUNCTION: BETA10 0x10170cc0 inline Result ViewSetCamera(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame2* pCamera) { ViewportAppData* pViewportAppData; Result result; pViewportAppData = reinterpret_cast(pViewport->GetAppData()); assert(pViewportAppData); result = ViewRestoreFrameAfterRender( pViewportAppData->m_pLastRenderedFrame, pViewportAppData->m_pCamera, pViewportAppData->m_pLightFrame ); assert(Succeeded(result)); pViewportAppData->m_pCamera = const_cast(pCamera); pViewportAppData->m_pLastRenderedFrame = 0; return ResultVal(pViewport->SetCamera(const_cast(pCamera))); } // FUNCTION: BETA10 0x10170c20 inline Result ViewImpl::SetCamera(const CameraImpl& rCamera) { assert(m_data); assert(rCamera.ImplementationData()); return ViewSetCamera(m_data, rCamera.ImplementationData()); } // FUNCTION: LEGO1 0x100a2df0 // FUNCTION: BETA10 0x1016e790 Result ViewImpl::SetCamera(const Camera* pCamera) { assert(m_data); assert(pCamera); return SetCamera(*static_cast(pCamera)); } // FUNCTION: BETA10 0x1016e870 inline Result ViewSetProjection(IDirect3DRMViewport* pViewport, ProjectionType type) { D3DRMPROJECTIONTYPE projectionType = Translate(type); return ResultVal(pViewport->SetProjection(projectionType)); } // FUNCTION: LEGO1 0x100a2e70 // FUNCTION: BETA10 0x1016e810 Result ViewImpl::SetProjection(ProjectionType type) { assert(m_data); return ViewSetProjection(m_data, type); } // FUNCTION: BETA10 0x1016e920 inline Result ViewSetFrustrum( IDirect3DRMViewport* pViewport, float frontClippingDistance, float backClippingDistance, float degrees ) { float field = frontClippingDistance * tan(DegreesToRadians(degrees / 2)); Result result; result = ResultVal(pViewport->SetFront(frontClippingDistance)); if (Succeeded(result)) { result = ResultVal(pViewport->SetBack(backClippingDistance)); } if (Succeeded(result)) { result = ResultVal(pViewport->SetField(field)); } return result; } // FUNCTION: LEGO1 0x100a2eb0 // FUNCTION: BETA10 0x1016e8b0 Result ViewImpl::SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) { assert(m_data); return ViewSetFrustrum(m_data, frontClippingDistance, backClippingDistance, degrees); } // FUNCTION: BETA10 0x1016ea70 inline Result ViewSetBackgroundColor(IDirect3DRMViewport* pViewport, float r, float g, float b) { Result result = Success; ViewportAppData* pViewportAppData = reinterpret_cast(pViewport->GetAppData()); assert(pViewportAppData); pViewportAppData->m_backgroundColorRed = r; pViewportAppData->m_backgroundColorGreen = g; pViewportAppData->m_backgroundColorBlue = b; if (pViewportAppData->m_pLastRenderedFrame) { result = ResultVal(pViewportAppData->m_pLastRenderedFrame->SetSceneBackgroundRGB(r, g, b)); assert(Succeeded(result)); } return result; } // FUNCTION: LEGO1 0x100a2f30 // FUNCTION: BETA10 0x1016ea00 Result ViewImpl::SetBackgroundColor(float r, float g, float b) { assert(m_data); return ViewSetBackgroundColor(m_data, r, g, b); } // FUNCTION: BETA10 0x1016ebd0 inline Result ViewGetBackgroundColor(IDirect3DRMViewport* pViewport, float* r, float* g, float* b) { ViewportAppData* pViewportAppData = reinterpret_cast(pViewport->GetAppData()); assert(pViewportAppData); *r = pViewportAppData->m_backgroundColorRed; *g = pViewportAppData->m_backgroundColorGreen; *b = pViewportAppData->m_backgroundColorBlue; return Success; } // FUNCTION: LEGO1 0x100a2f80 // FUNCTION: BETA10 0x1016eb60 Result ViewImpl::GetBackgroundColor(float* r, float* g, float* b) { assert(m_data); return ViewGetBackgroundColor(m_data, r, g, b); } // FUNCTION: BETA10 0x1016ecb0 inline Result ViewClear(IDirect3DRMViewport* pViewport) { return ResultVal(pViewport->Clear()); } // FUNCTION: LEGO1 0x100a2fb0 // FUNCTION: BETA10 0x1016ec50 Result ViewImpl::Clear() { assert(m_data); return ViewClear(m_data); } // FUNCTION: BETA10 0x10170fb0 inline Result ViewPrepareFrameForRender( IDirect3DRMFrame* pFrame, IDirect3DRMFrame* pCamera, IDirect3DRMFrame* pLightFrame, float backgroundRed, float backgroundGreen, float backgroundBlue ) { Result result = Success; if (pFrame) { // set background color result = ResultVal(pFrame->SetSceneBackgroundRGB(backgroundRed, backgroundGreen, backgroundBlue)); assert(Succeeded(result)); // add camera to frame to be rendered result = ResultVal(pFrame->AddChild(pCamera)); assert(Succeeded(result)); // add light frame to frame to be rendered result = ResultVal(pFrame->AddChild(pLightFrame)); assert(Succeeded(result)); // increase ref count of frame to ensure it does not get deleted underneath us pFrame->AddRef(); } return result; } // FUNCTION: BETA10 0x10170e30 inline Result ViewRender(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame2* pGroup) { ViewportAppData* pViewportAppData; Result result; pViewportAppData = reinterpret_cast(pViewport->GetAppData()); assert(pViewportAppData); if (pViewportAppData->m_pLastRenderedFrame != pGroup) { result = ViewRestoreFrameAfterRender( pViewportAppData->m_pLastRenderedFrame, pViewportAppData->m_pCamera, pViewportAppData->m_pLightFrame ); assert(Succeeded(result)); pViewportAppData->m_pLastRenderedFrame = const_cast(pGroup); result = ViewPrepareFrameForRender( pViewportAppData->m_pLastRenderedFrame, pViewportAppData->m_pCamera, pViewportAppData->m_pLightFrame, pViewportAppData->m_backgroundColorRed, pViewportAppData->m_backgroundColorGreen, pViewportAppData->m_backgroundColorBlue ); } assert(Succeeded(result)); result = ResultVal(pViewport->Render(const_cast(pGroup))); assert(Succeeded(result)); return result; } // FUNCTION: BETA10 0x10170d90 inline Result ViewImpl::Render(const GroupImpl& rScene) { assert(m_data); assert(rScene.ImplementationData()); return ViewRender(m_data, rScene.ImplementationData()); } // FUNCTION: LEGO1 0x100a2fd0 // FUNCTION: BETA10 0x1016ece0 Result ViewImpl::Render(const Group* pGroup) { assert(m_data); assert(pGroup); return Render(*static_cast(pGroup)); } // FUNCTION: BETA10 0x1016edd0 inline Result ViewForceUpdate( IDirect3DRMViewport* pViewport, unsigned long x, unsigned long y, unsigned long width, unsigned long height ) { return ResultVal(pViewport->ForceUpdate(x, y, x + width - 1, y + height - 1)); } // FUNCTION: LEGO1 0x100a3080 // FUNCTION: BETA10 0x1016ed60 Result ViewImpl::ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) { assert(m_data); return ViewForceUpdate(m_data, x, y, width, height); } // FUNCTION: BETA10 0x101710f0 inline Result ViewImpl::Pick( unsigned long x, unsigned long y, const GroupImpl** ppGroupsToPickFrom, int groupsToPickFromCount, const Group**& rppPickedGroups, int& rPickedGroupCount ) { assert(m_data); return ViewportPickImpl( m_data, x, y, ppGroupsToPickFrom, groupsToPickFromCount, rppPickedGroups, rPickedGroupCount ); } // FUNCTION: LEGO1 0x100a30c0 // FUNCTION: BETA10 0x1016ee10 Result ViewImpl::Pick( unsigned long x, unsigned long y, const Group** ppGroupsToPickFrom, int groupsToPickFromCount, const Group**& rppPickedGroups, int& rPickedGroupCount ) { assert(m_data); return Pick( x, y, reinterpret_cast(ppGroupsToPickFrom), groupsToPickFromCount, rppPickedGroups, rPickedGroupCount ); } // FUNCTION: BETA10 0x1016eff0 inline Result ViewTransformWorldToScreen(IDirect3DRMViewport* pViewport, const float world[3], float screen[4]) { D3DRMVECTOR4D d3dRMScreen; D3DVECTOR d3dRMWorld; D3DVECTOR* pD3DRMWorld = Translate(world, d3dRMWorld); Result result; result = ResultVal(pViewport->Transform(&d3dRMScreen, pD3DRMWorld)); if (Succeeded(result)) { screen[0] = d3dRMScreen.x; screen[1] = d3dRMScreen.y; screen[2] = d3dRMScreen.z; screen[3] = d3dRMScreen.w; } return result; } // FUNCTION: LEGO1 0x100a30f0 // FUNCTION: BETA10 0x1016ef90 Result ViewImpl::TransformWorldToScreen(const float world[3], float screen[4]) { assert(m_data); return ViewTransformWorldToScreen(m_data, world, screen); } // FUNCTION: BETA10 0x1016f0d0 inline Result ViewTransformScreenToWorld(IDirect3DRMViewport* pViewport, const float screen[4], float world[3]) { D3DVECTOR d3dRMWorld; D3DRMVECTOR4D d3dScreen; d3dScreen.x = screen[0]; d3dScreen.y = screen[1]; d3dScreen.z = screen[2]; d3dScreen.w = screen[3]; Result result; result = ResultVal(pViewport->InverseTransform(&d3dRMWorld, &d3dScreen)); if (Succeeded(result)) { world[0] = d3dRMWorld.x; world[1] = d3dRMWorld.y; world[2] = d3dRMWorld.z; } return result; } // FUNCTION: LEGO1 0x100a3160 // FUNCTION: BETA10 0x1016f070 Result ViewImpl::TransformScreenToWorld(const float screen[4], float world[3]) { assert(m_data); return ViewTransformScreenToWorld(m_data, screen, world); }