mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-23 08:24:16 +00:00

* ImplementationData methods and typedefs * RendererImpl::CreateView * RendererImpl::CreateMeshBuilder * DeepClone * CreateCamera and CreateTexture * CreateDevice * Disable static var annotation
601 lines
15 KiB
C++
601 lines
15 KiB
C++
#include "impl.h"
|
|
|
|
#include <assert.h>
|
|
|
|
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<LPD3DRM_APPDATA>(pViewportAppData)));
|
|
assert(Succeeded(result));
|
|
assert(reinterpret_cast<ViewportAppData*>(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<ViewportAppData*>(pArg);
|
|
assert(static_cast<ViewImpl::ViewDataType>(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<ViewportAppData*>(pViewport->GetAppData());
|
|
}
|
|
|
|
// FUNCTION: BETA10 0x10170ab0
|
|
inline IDirect3DRMFrame* ViewportGetLightFrame(IDirect3DRMViewport* pViewport)
|
|
{
|
|
assert(pViewport->GetAppData());
|
|
return reinterpret_cast<ViewportAppData*>(pViewport->GetAppData())->m_pLightFrame;
|
|
}
|
|
|
|
// FUNCTION: LEGO1 0x100a2d80
|
|
// FUNCTION: BETA10 0x1016e640
|
|
void* ViewImpl::ImplementationDataPtr()
|
|
{
|
|
return reinterpret_cast<void*>(&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<IDirect3DRMFrame*>(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<const LightImpl*>(pLight));
|
|
}
|
|
|
|
// FUNCTION: BETA10 0x10170bb0
|
|
inline Result ViewRemoveLight(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame* pLight)
|
|
{
|
|
IDirect3DRMFrame* pLightFrame = ViewportGetLightFrame(pViewport);
|
|
|
|
assert(pLightFrame);
|
|
return ResultVal(pLightFrame->DeleteChild(const_cast<IDirect3DRMFrame*>(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<const LightImpl*>(pLight));
|
|
}
|
|
|
|
// FUNCTION: BETA10 0x10170cc0
|
|
inline Result ViewSetCamera(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame2* pCamera)
|
|
{
|
|
ViewportAppData* pViewportAppData;
|
|
Result result;
|
|
|
|
pViewportAppData = reinterpret_cast<ViewportAppData*>(pViewport->GetAppData());
|
|
assert(pViewportAppData);
|
|
|
|
result = ViewRestoreFrameAfterRender(
|
|
pViewportAppData->m_pLastRenderedFrame,
|
|
pViewportAppData->m_pCamera,
|
|
pViewportAppData->m_pLightFrame
|
|
);
|
|
assert(Succeeded(result));
|
|
pViewportAppData->m_pCamera = const_cast<IDirect3DRMFrame2*>(pCamera);
|
|
pViewportAppData->m_pLastRenderedFrame = 0;
|
|
|
|
return ResultVal(pViewport->SetCamera(const_cast<IDirect3DRMFrame2*>(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<const CameraImpl*>(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<ViewportAppData*>(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<ViewportAppData*>(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<ViewportAppData*>(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<IDirect3DRMFrame2*>(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<IDirect3DRMFrame2*>(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<const GroupImpl*>(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<const GroupImpl**>(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);
|
|
}
|