From 5bfa13c5cce4b07fba121ef23a0785776d97a2bf Mon Sep 17 00:00:00 2001 From: shenlei Date: Wed, 23 Sep 2026 20:15:54 +0900 Subject: [PATCH] =?UTF-8?q?2V2-e.1:=203D=20draw-command=20channel=20?= =?UTF-8?q?=E2=80=94=20recording=20D3D8=20device,=20StateManager,=20GrpBas?= =?UTF-8?q?e,=20camera?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EterLib/StateManager.cpp and GrpBase.cpp ported verbatim. CGraphicDevice::Create builds a platform IDirect3DDevice8 that keeps the device state and records every Draw* call as a Render3DDraw (vertices decoded by FVF, strips/fans expanded, textures, world/view/proj, blend/depth/light state). The 40250 camera (__UpdateCamera, SetCenterPosition, ...) and the Process order (__UpdateCamera -> OnCameraUpdate -> OnUIUpdate -> Begin/SetInterfaceRenderState/OnUIRender/End) are in place; CScreen Begin/End, CPythonGraphic render states and CCullingManager::Process matrix updates are verbatim. port.login_flow asserts a textured, lit character draw under the RH perspective with every vertex on screen; offline and live pass. Co-Authored-By: Claude Opus 5.5 --- audit/history.jsonl | 1 + audit/port-map/EterLib/GrpBase.cpp.json | 296 +++++++ audit/port-map/EterLib/StateManager.cpp.json | 332 ++++++++ docs/PORT-PLAN.md | 2 +- extension/src/platform/EterLib/CpuBuffer.h | 18 + .../src/platform/EterLib/CullingManager.cpp | 11 +- extension/src/platform/EterLib/GrpBase.cpp | 378 --------- extension/src/platform/EterLib/GrpDevice.cpp | 274 ++++++- .../src/platform/EterLib/GrpImageTexture.cpp | 40 + extension/src/platform/EterLib/GrpScreen.cpp | 59 +- extension/src/platform/EterLib/GrpTexture.cpp | 2 +- .../src/platform/EterLib/RecordingDevice.cpp | 385 +++++++++ .../src/platform/EterLib/RecordingDevice.h | 7 + .../src/platform/EterLib/RenderCommands3D.h | 55 ++ .../src/platform/EterLib/StateManager.cpp | 292 ------- .../src/platform/EterLib/UIRenderCommands.h | 4 + .../platform/EterPythonLib/PythonGraphic.cpp | 77 +- .../UserInterface/PythonApplication.cpp | 96 ++- .../UserInterface/PythonApplicationCamera.cpp | 408 ++++++++++ .../platform/pending/GameLib/MapManager.cpp | 9 + .../pending/UserInterface/PythonPlayer.cpp | 48 +- extension/src/port/EterLib/GrpBase.cpp | 512 ++++++++++++ extension/src/port/EterLib/StateManager.cpp | 769 ++++++++++++++++++ extension/src/port/common/D3D8Types.h | 116 ++- extension/src/port/common/D3DXMath.cpp | 141 ++++ extension/src/port/common/D3DXMath.h | 30 + extension/tests/port_login_flow_test.cpp | 31 + 27 files changed, 3616 insertions(+), 777 deletions(-) create mode 100644 audit/port-map/EterLib/GrpBase.cpp.json create mode 100644 audit/port-map/EterLib/StateManager.cpp.json delete mode 100644 extension/src/platform/EterLib/GrpBase.cpp create mode 100644 extension/src/platform/EterLib/RecordingDevice.cpp create mode 100644 extension/src/platform/EterLib/RecordingDevice.h create mode 100644 extension/src/platform/EterLib/RenderCommands3D.h delete mode 100644 extension/src/platform/EterLib/StateManager.cpp create mode 100644 extension/src/platform/UserInterface/PythonApplicationCamera.cpp create mode 100644 extension/src/port/EterLib/GrpBase.cpp create mode 100644 extension/src/port/EterLib/StateManager.cpp diff --git a/audit/history.jsonl b/audit/history.jsonl index 721b1f8d..76266b33 100644 --- a/audit/history.jsonl +++ b/audit/history.jsonl @@ -517,3 +517,4 @@ {"time": "2026-09-23T09:39:22Z", "event": "port_round", "unit": "PORT-PLAN 2V2-c: chrmgr/chr modules + race registration chain", "ported": ["UserInterface/PythonCharacterManagerModule.cpp", "UserInterface/PythonCharacterModule.cpp", "GameLib/RaceData.cpp", "GameLib/RaceDataFile.cpp", "GameLib/RaceManager.cpp", "GameLib/RaceMotionData.cpp", "GameLib/GameType.cpp", "EterLib/AttributeData.cpp", "EterLib/AttributeInstance.cpp", "EterLib/TextFileLoader.cpp", "EterLib/Util.cpp (lines 1-141, 297-end)", "EterLib/Camera.cpp", "UserInterface/CameraProcedure.cpp"], "adapted": ["EterLib/Util.cpp code page / font face stays with the platform font backend", "CRaceManager created in PythonBoot in CPythonApplication member order", "D3DXVec2CCW / D3DXMatrixfDeterminant / D3DXMatrixLookAtRH"], "divergent": [], "needs_live": ["intermittent (about 1 in 11 live runs) unhandled header 7 in the Loading phase, suspected packet-size desync; the test now prints g_iLastPacket and fails; 8 later runs clean"], "tests": ["port.login_flow: pass (chr/chrmgr not stubs, race 0 MODE_GENERAL/NAME_WAIT registered, no unhandled packet header)", "port.login_live: 8/8 pass against 192.168.21.203", "script/port_gate.sh macos: PASS"], "todo": ["2V2-d gr2 loader + CGraphicThing adapter, InstanceBase/ActorInstance stand-ins", "2V2-e render", "Loading-phase header 7 desync"]} {"time": "2026-09-23T10:56:00Z", "event": "port_round", "unit": "PORT-PLAN 2V2-d.1: ActorInstance/InstanceBase closure, main character instance", "ported": ["GameLib/ActorInstance.cpp", "GameLib/ActorInstanceAttach.cpp", "GameLib/ActorInstanceBattle.cpp", "GameLib/ActorInstanceBlend.cpp", "GameLib/ActorInstanceCollisionDetection.cpp", "GameLib/ActorInstanceEvent.cpp", "GameLib/ActorInstanceFly.cpp", "GameLib/ActorInstanceMotion.cpp", "GameLib/ActorInstanceMotionEvent.cpp", "GameLib/ActorInstancePosition.cpp", "GameLib/ActorInstanceRender.cpp", "GameLib/ActorInstanceRotation.cpp", "GameLib/ActorInstanceSync.cpp", "GameLib/ActorInstanceWeaponTrace.cpp", "UserInterface/InstanceBase.cpp", "UserInterface/InstanceBaseBattle.cpp", "UserInterface/InstanceBaseEffect.cpp", "UserInterface/InstanceBaseEvent.cpp", "UserInterface/InstanceBaseMotion.cpp", "UserInterface/InstanceBaseTransform.cpp", "GameLib/GameUtil.cpp", "GameLib/FlyTarget.cpp", "GameLib/PhysicsObject.cpp", "GameLib/GameEventManager.cpp", "GameLib/WeaponTrace.cpp", "GameLib/MapUtil.cpp", "EterLib/lineintersect_utils.cpp"], "adapted": ["Packet.h TPlayerSkill::tNextRead LONG (32-bit time_t on the wire) + static_assert 1531", "MapUtil.cpp include", "CGameEventManager / CPythonSystem created in PythonBoot in CPythonApplication member order", "D3D8Types.h full D3DTA/D3DTEXTUREOP/D3DCMPFUNC/D3DBLEND/D3DCULL"], "divergent": [], "needs_live": [], "tests": ["port.login_flow: pass (main instance exists, race 0, no AdditionalInfo error, SKILL_LEVEL in Loading)", "port.login_live: 8/8 pass against 192.168.21.203, no unhandled packet", "script/port_gate.sh macos: PASS"], "todo": ["2V2-d.2 gr2/mdatr resource factories + CGraphicThing/CGrannyModel/CGrannyMotion/CGraphicThingInstance on libgr2", "2V2-e render"]} {"time": "2026-09-23T10:36:40Z", "event": "port_round", "unit": "PORT-PLAN 2V2-d.2: Granny runtime on libgr2 + EterGrnLib, main character model animates", "ported": ["EterGrnLib/LODController.cpp", "EterGrnLib/Material.cpp", "EterGrnLib/Mesh.cpp", "EterGrnLib/Model.cpp", "EterGrnLib/ModelInstance.cpp", "EterGrnLib/ModelInstanceCollisionDetection.cpp", "EterGrnLib/ModelInstanceModel.cpp", "EterGrnLib/ModelInstanceMotion.cpp", "EterGrnLib/ModelInstanceRender.cpp", "EterGrnLib/ModelInstanceUpdate.cpp", "EterGrnLib/Motion.cpp", "EterGrnLib/Thing.cpp", "EterGrnLib/ThingInstance.cpp", "EterGrnLib/Util.cpp", "EterLib/GrpObjectInstance.cpp", "EterLib/GrpCollisionObject.cpp", "EterLib/CollisionData.cpp"], "adapted": ["platform/EterGrnLib/GrannyRuntime.cpp: Granny SDK 2.11 API on libgr2 (file sections, type-definition vertex conversion incl. half floats, material texture by Usage, mesh/bone bindings, deformer, control clock/loop/ease, weighted SRT sampling, composite matrices)", "shim/sdk/granny.h declared from the SDK 2.11 header", "CPU vertex/index buffers (platform/EterLib/CpuBuffer.h)", "Resource.cpp gr2 factory", "CPythonApplication::UpdateGame/RenderGame/GetMousePosition through singletons (no app object); CPythonGraphic in GameSingletons; host cursor", "libgr2: skeleton/mesh/anim/fileinfo accessors", "D3D8Types texture-stage enums, D3DXVec4Transform"], "divergent": [], "needs_live": [], "tests": ["port.login_flow: pass (PART_MAIN model has meshes, material 0 diffuse image loaded, WAIT motion changes bone matrices between frames)", "port.login_live: pass against 192.168.21.203", "script/port_gate.sh macos: PASS"], "todo": ["2V2-e Godot render adapter: recognizable standing character offline + live", "mdatr factory with CAttributeData resource"]} +{"time": "2026-09-23T11:09:12Z", "event": "port_round", "unit": "PORT-PLAN 2V2-e.1: 3D draw-command channel (recording D3D8 device, StateManager, GrpBase, camera)", "ported": ["EterLib/StateManager.cpp", "EterLib/GrpBase.cpp"], "adapted": ["platform/EterLib/RecordingDevice.cpp: IDirect3DDevice8 that records every Draw* as Render3DDraw (RenderCommands3D.h)", "CGraphicDevice::Create on the recording device, CPU default IB/PDT VBs", "D3DXMath PerspectiveFovRH/OrthoRH/OrthoOffCenterRH + ID3DXMatrixStack", "PythonApplicationCamera.cpp: __UpdateCamera and camera API verbatim, members in a file-static struct", "Process: __UpdateCamera, OnCameraUpdate, Begin/SetInterfaceRenderState/OnUIRender/End", "CScreen Begin/End/Set*Operation, CPythonGraphic Set{Game,Interface}RenderState/PushState/PopState/GetOrthoDepth, CCullingManager::Process view/proj (no frustum culling yet)", "pending CPythonPlayer main-actor functions (no event handler), CMapManager::IsMapReady"], "divergent": [], "needs_live": [], "tests": ["port.login_flow: pass (textured lit triangle draw, RH perspective, all vertices on screen)", "port.login_live: pass against 192.168.21.203", "script/port_gate.sh macos: PASS"], "todo": ["2V2-e.2 Godot consumer of Render3DDraws + offline screenshot", "2V2-e.3 live smoke", "SphereLib frustum culling", "PythonPlayerEventHandler"]} diff --git a/audit/port-map/EterLib/GrpBase.cpp.json b/audit/port-map/EterLib/GrpBase.cpp.json new file mode 100644 index 00000000..8e624aa5 --- /dev/null +++ b/audit/port-map/EterLib/GrpBase.cpp.json @@ -0,0 +1,296 @@ +{ + "reference": "EterLib/GrpBase.cpp", + "reference_sha256": "c0e9ca5417117c5ac4b03436a1e64c9318265c203872b8fd949452cea8d0afa2", + "priority": "P4", + "contracts": [], + "functions": { + "PixelPositionToD3DXVECTOR3": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:PixelPositionToD3DXVECTOR3" + ] + }, + "D3DXVECTOR3ToPixelPosition": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:D3DXVECTOR3ToPixelPosition" + ] + }, + "CGraphicBase::IsLowTextureMemory": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::IsLowTextureMemory" + ] + }, + "CGraphicBase::IsHighTextureMemory": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::IsHighTextureMemory" + ] + }, + "CGraphicBase::IsFastTNL": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::IsFastTNL" + ] + }, + "CGraphicBase::IsTLVertexClipping": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::IsTLVertexClipping" + ] + }, + "CGraphicBase::GetBackBufferSize": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetBackBufferSize" + ] + }, + "CGraphicBase::SetDefaultIndexBuffer": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetDefaultIndexBuffer" + ] + }, + "CGraphicBase::SetPDTStream": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetPDTStream" + ] + }, + "CGraphicBase::GetAvailableTextureMemory": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetAvailableTextureMemory" + ] + }, + "CGraphicBase::GetViewMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetViewMatrix" + ] + }, + "CGraphicBase::GetIdentityMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetIdentityMatrix" + ] + }, + "CGraphicBase::SetEyeCamera": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetEyeCamera" + ] + }, + "CGraphicBase::SetSimpleCamera": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetSimpleCamera" + ] + }, + "CGraphicBase::SetAroundCamera": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetAroundCamera" + ] + }, + "CGraphicBase::SetPositionCamera": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetPositionCamera" + ] + }, + "CGraphicBase::SetOrtho2D": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetOrtho2D" + ] + }, + "CGraphicBase::SetOrtho3D": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetOrtho3D" + ] + }, + "CGraphicBase::SetPerspective": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetPerspective" + ] + }, + "CGraphicBase::UpdateProjMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::UpdateProjMatrix" + ] + }, + "CGraphicBase::UpdateViewMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::UpdateViewMatrix" + ] + }, + "CGraphicBase::UpdatePipeLineMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::UpdatePipeLineMatrix" + ] + }, + "CGraphicBase::SetViewport": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetViewport" + ] + }, + "CGraphicBase::GetTargetPosition": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetTargetPosition" + ] + }, + "CGraphicBase::GetCameraPosition": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetCameraPosition" + ] + }, + "CGraphicBase::GetMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetMatrix" + ] + }, + "CGraphicBase::GetMatrixPointer": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetMatrixPointer" + ] + }, + "CGraphicBase::GetSphereMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetSphereMatrix" + ] + }, + "CGraphicBase::GetFOV": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetFOV" + ] + }, + "CGraphicBase::PushMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::PushMatrix" + ] + }, + "CGraphicBase::Scale": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::Scale" + ] + }, + "CGraphicBase::Rotate": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::Rotate" + ] + }, + "CGraphicBase::RotateLocal": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::RotateLocal" + ] + }, + "CGraphicBase::MultMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::MultMatrix" + ] + }, + "CGraphicBase::MultMatrixLocal": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::MultMatrixLocal" + ] + }, + "CGraphicBase::RotateYawPitchRollLocal": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::RotateYawPitchRollLocal" + ] + }, + "CGraphicBase::Translate": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::Translate" + ] + }, + "CGraphicBase::LoadMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::LoadMatrix" + ] + }, + "CGraphicBase::PopMatrix": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::PopMatrix" + ] + }, + "CGraphicBase::GetColor": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetColor" + ] + }, + "CGraphicBase::InitScreenEffect": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::InitScreenEffect" + ] + }, + "CGraphicBase::SetScreenEffectWaving": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetScreenEffectWaving" + ] + }, + "CGraphicBase::SetScreenEffectFlashing": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::SetScreenEffectFlashing" + ] + }, + "CGraphicBase::GetFaceCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetFaceCount" + ] + }, + "CGraphicBase::ResetFaceCount": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::ResetFaceCount" + ] + }, + "CGraphicBase::GetLastResult": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::GetLastResult" + ] + }, + "CGraphicBase::CGraphicBase": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::CGraphicBase" + ] + }, + "CGraphicBase::~CGraphicBase": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/GrpBase.cpp:CGraphicBase::~CGraphicBase" + ] + } + } +} diff --git a/audit/port-map/EterLib/StateManager.cpp.json b/audit/port-map/EterLib/StateManager.cpp.json new file mode 100644 index 00000000..3370891d --- /dev/null +++ b/audit/port-map/EterLib/StateManager.cpp.json @@ -0,0 +1,332 @@ +{ + "reference": "EterLib/StateManager.cpp", + "reference_sha256": "97c47e6dc6c3c4d9f4a867dfe41f4ea0586d0db74d91e55c0cf03f28092dd00d", + "priority": "P4", + "contracts": [], + "functions": { + "CStateManager::SetLight": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetLight" + ] + }, + "CStateManager::GetLight": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetLight" + ] + }, + "CStateManager::BeginScene": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::BeginScene" + ] + }, + "CStateManager::EndScene": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::EndScene" + ] + }, + "CStateManager::CStateManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::CStateManager" + ] + }, + "CStateManager::~CStateManager": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::~CStateManager" + ] + }, + "CStateManager::SetDevice": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetDevice" + ] + }, + "CStateManager::SetBestFiltering": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetBestFiltering" + ] + }, + "CStateManager::Restore": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::Restore" + ] + }, + "CStateManager::SetDefaultState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetDefaultState" + ] + }, + "CStateManager::SaveMaterial": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveMaterial" + ] + }, + "CStateManager::RestoreMaterial": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreMaterial" + ] + }, + "CStateManager::SetMaterial": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetMaterial" + ] + }, + "CStateManager::GetMaterial": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetMaterial" + ] + }, + "CStateManager::GetRenderState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetRenderState" + ] + }, + "CStateManager::SaveRenderState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveRenderState" + ] + }, + "CStateManager::RestoreRenderState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreRenderState" + ] + }, + "CStateManager::SetRenderState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetRenderState" + ] + }, + "CStateManager::SaveTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveTexture" + ] + }, + "CStateManager::RestoreTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreTexture" + ] + }, + "CStateManager::SetTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetTexture" + ] + }, + "CStateManager::GetTexture": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetTexture" + ] + }, + "CStateManager::SaveTextureStageState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveTextureStageState" + ] + }, + "CStateManager::RestoreTextureStageState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreTextureStageState" + ] + }, + "CStateManager::SetTextureStageState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetTextureStageState" + ] + }, + "CStateManager::GetTextureStageState": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetTextureStageState" + ] + }, + "CStateManager::SaveVertexShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveVertexShader" + ] + }, + "CStateManager::RestoreVertexShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreVertexShader" + ] + }, + "CStateManager::SetVertexShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetVertexShader" + ] + }, + "CStateManager::GetVertexShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetVertexShader" + ] + }, + "CStateManager::SavePixelShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SavePixelShader" + ] + }, + "CStateManager::RestorePixelShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestorePixelShader" + ] + }, + "CStateManager::SetPixelShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetPixelShader" + ] + }, + "CStateManager::GetPixelShader": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetPixelShader" + ] + }, + "CStateManager::SaveTransform": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveTransform" + ] + }, + "CStateManager::RestoreTransform": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreTransform" + ] + }, + "CStateManager::SetTransform": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetTransform" + ] + }, + "CStateManager::GetTransform": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::GetTransform" + ] + }, + "CStateManager::SaveVertexShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveVertexShaderConstant" + ] + }, + "CStateManager::RestoreVertexShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreVertexShaderConstant" + ] + }, + "CStateManager::SetVertexShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetVertexShaderConstant" + ] + }, + "CStateManager::SavePixelShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SavePixelShaderConstant" + ] + }, + "CStateManager::RestorePixelShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestorePixelShaderConstant" + ] + }, + "CStateManager::SetPixelShaderConstant": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetPixelShaderConstant" + ] + }, + "CStateManager::SaveStreamSource": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveStreamSource" + ] + }, + "CStateManager::RestoreStreamSource": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreStreamSource" + ] + }, + "CStateManager::SetStreamSource": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetStreamSource" + ] + }, + "CStateManager::SaveIndices": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SaveIndices" + ] + }, + "CStateManager::RestoreIndices": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::RestoreIndices" + ] + }, + "CStateManager::SetIndices": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::SetIndices" + ] + }, + "CStateManager::DrawPrimitive": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::DrawPrimitive" + ] + }, + "CStateManager::DrawPrimitiveUP": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::DrawPrimitiveUP" + ] + }, + "CStateManager::DrawIndexedPrimitive": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::DrawIndexedPrimitive" + ] + }, + "CStateManager::DrawIndexedPrimitiveUP": { + "status": "PORTED", + "impl": [ + "extension/src/port/EterLib/StateManager.cpp:CStateManager::DrawIndexedPrimitiveUP" + ] + } + } +} diff --git a/docs/PORT-PLAN.md b/docs/PORT-PLAN.md index 7b0f13b9..7bd38dac 100644 --- a/docs/PORT-PLAN.md +++ b/docs/PORT-PLAN.md @@ -423,7 +423,7 @@ extension/third_party/cpython-2.7.18/ # 静态库(2P 批次 | 2V2-b | `PythonNetworkStreamPhaseGame*.cpp` 分派闭包:`SetGamePhase`/`GamePhase`,PHASE_GAME 后的 Entergame 包洪流(`GC_TIME`/`GC_CHANNEL`/`GC_CHARACTER_ADD`/`GC_CHAR_ADDITIONAL_INFO`/`GC_CHARACTER_UPDATE`/技能/物品/快捷栏…)读流不断 | 完成:`PythonNetworkStreamPhaseGame`/`PhaseGameActor`/`PhaseGameItem`/`Command`、`NetworkActorManager` 原样移植并在运行时分派(port-map 标 PORTED);`GC_CHAT` 需要的 `PythonChat.cpp`/`PythonChatModule.cpp` 一并原样移植,`GameplayModules.cpp` 的 `chat` 桩删除,`initChat()` 按 40250 顺序在 `initnet()` 前调用。未移植单元的单例在 `PythonBoot` 的 `GameSingletons` 里按 `CPythonApplication` 成员顺序创建(calloc 存储:替身构造函数不初始化标量);替身由 `platform_stub.py pending
<符号...> [--ctor]` 按链接缺失符号生成到 `platform/pending//`,返回 `const char*` 的替身返回 `""`(`RecvGuild` 里 `strcmp(…, CPythonPlayer::GetName())`)。`port.login_flow` 假服按 `CInputLogin::Entergame` 顺序发:Loading 阶段 `CHARACTER_ADD`+`CHAR_ADDITIONAL_INFO`+`CHARACTER_UPDATE`、`NPC_POSITION` → `PHASE_GAME` → `LAND_LIST`、`TIME`、`CHANNEL`、问候 `CHAT` → `PING`,客户端回 `PONG`,公告进 `CPythonChat`,`TraceError` 观察钩子(`EterBase/TraceErrorObserver.h`)断言无 `Unknown packet header`。`port.login_live` 2026-09-23 对 192.168.21.203 读 10 s 真实游戏阶段:连接保持、GameWindow 显示、无未知包;剩下的 SYSERR 只有 `CreateInstance` 失败(2V2-d 的 `SetRace` 占位) | | 2V2-c | `PythonCharacterManager` + `chrmgr`/`chr` 模块:`playerSettingModule` 的种族/动作/特效注册走真实实现 | 完成:`PythonCharacterManagerModule.cpp`/`PythonCharacterModule.cpp` 原样移植,`GameplayModules.cpp` 的 `chr`/`chrmgr` 桩删除,`initchr()`/`initchrmgr()` 按 40250 顺序在 `initChat()` 前调用;注册链需要的 `RaceData`/`RaceDataFile`/`RaceManager`/`RaceMotionData`、`GameType`、`AttributeData`/`AttributeInstance`、`TextFileLoader`、`Util.cpp`(代码页/字体部分留在 platform 字体后端,port-map 标 ADAPTED/N_A)、`Camera`/`CameraProcedure` 原样移植(port-map 标 PORTED),`CRaceManager` 按 `CPythonApplication` 成员顺序在 `PythonBoot` 创建;`D3DXMath` 补 `D3DXVec2CCW`/`D3DXMatrixfDeterminant`/`D3DXMatrixLookAtRH`。`port.login_flow` 断言 `chr`/`chrmgr` 不是桩、种族 0 的 `MODE_GENERAL`/`NAME_WAIT` 动作已注册、Syserr 无“처리되지 않은 패킷 헤더”;`port.login_live` 2026-09-23 对 192.168.21.203 连跑 8 次通过、`script/port_gate.sh macos` PASS,怪物种族实例随真实 `SetRace` 创建。偶发(约 1/11)Loading 阶段报头 7 未处理(疑包长失步),测试现打印 `g_iLastPacket` 并判失败,未再复现 | | 2V2-d | `InstanceBase` + `ActorInstance` + `CGraphicThingInstance` adapter:`GC_CHARACTER_ADD` 创建主角实例(msm 模型 + 待机动作) | 完成。d.1:`ActorInstance*.cpp`(Attach/Battle/Blend/CollisionDetection/Event/Fly/Motion/MotionEvent/Position/Render/Rotation/Sync/WeaponTrace)、`InstanceBase*.cpp`(Battle/Effect/Event/Motion/Transform)、`GameUtil`、`FlyTarget`、`PhysicsObject`、`GameEventManager`、`WeaponTrace`、`MapUtil`、`lineintersect_utils` 原样移植,`pending/GameLib/{ActorInstance,FlyTarget,PhysicsObject,MapUtil}.cpp`、`pending/UserInterface/InstanceBase.cpp` 替身删除,`ActorInstance.cpp`/`InstanceBase.cpp` 随主角创建进入运行时(port-map 标 PORTED);`CGameEventManager` 与 `CPythonSystem`(最后一个成员)按 `CPythonApplication` 成员顺序在 `PythonBoot` 创建;`D3D8Types.h` 补全 `D3DTA`/`D3DTEXTUREOP`/`D3DCMPFUNC`/`D3DBLEND`/`D3DCULL`。假服 `CHARACTER_ADD` 的 `bType` 改为 `CHAR_TYPE_PC`(6,原 0 使 `RecvCharacterAppendPacket` 不记主角、`CHAR_ADDITIONAL_INFO` 报错)。2V2-c 的偶发 Loading 头 7 根因:`TPlayerSkill::tNextRead` 是 `time_t`,40250 用 `_USE_32BIT_TIME_T`,LP64 下 `TPacketGCSkillLevelNew` 变成 2551 字节(线上 1531),`CInputDB::PlayerLoad` 在 `PointsPacket` 后发的 `SKILL_LEVEL`(76)读多吞掉后续包;`Packet.h` 改 `LONG` 并 `static_assert` 1531,假服 Loading 阶段补发 `SKILL_LEVEL` 回归。`port.login_flow` 断言主角实例存在且种族 0、无 `TPacketGCCharacterAdditionalInfo` 报错;`port.login_live` 2026-09-23 对 192.168.21.203 连跑 8 次通过,剩余 SYSERR 只有 gr2 `NOT SUPPORT FILE`。d.2:Granny SDK 2.11 运行时在 libgr2 上实现(`platform/EterGrnLib/GrannyRuntime.cpp`,`shim/sdk/granny.h` 按 SDK 头声明所用类型与函数:文件/段、按类型定义的顶点转换含 half、材质贴图按 Usage 查找、网格绑定、变形器、控制器时钟/循环/缓入缓出、加权 SRT 采样与复合矩阵),`EterGrnLib/*.cpp`(LODController/Material/Mesh/Model/ModelInstance*/Motion/Thing/ThingInstance/Util)与 `EterLib/{GrpObjectInstance,GrpCollisionObject,CollisionData}.cpp` 原样移植,对应 platform 骨架与 pending 替身删除(port-map 标 PORTED);`Resource.cpp` 注册 gr2 工厂(mdatr 等 `CAttributeData` 资源化时再注册);VB/IB 为 CPU 缓冲(`platform/EterLib/CpuBuffer.h`),渲染 adapter 属 2V2-e。`app.UpdateGame`/`RenderGame`(40250 `PythonApplication.cpp:321/168`)接入,成员经单例访问(平台没有 `CPythonApplication` 对象),`CPythonGraphic`(含 `CCullingManager`)按成员顺序进 `GameSingletons`;`GetMousePosition` 读 host 光标。`port.login_flow` 断言主角 PART_MAIN 模型有网格、材质漫反射贴图已加载、WAIT 动作使骨骼矩阵逐帧变化;离线与 `port.login_live`(192.168.21.203)2026-09-23 通过 | - | 2V2-e | Godot 显示主角(渲染 adapter),离线 + 真服 smoke:进游戏看到可辨认的静止角色 | TODO | + | 2V2-e | Godot 显示主角(渲染 adapter),离线 + 真服 smoke:进游戏看到可辨认的静止角色 | 进行中。e.1 完成:3D 绘制命令通道。`EterLib/StateManager.cpp`、`EterLib/GrpBase.cpp` 原样移植(platform 骨架删除,port-map 标 PORTED);`CGraphicDevice::Create` 建平台 `IDirect3DDevice8`(`platform/EterLib/RecordingDevice.cpp`:记住 transform/渲染状态/贴图阶段/材质/灯光/FVF/流/索引,按 FVF 解码顶点、展开 strip/fan,每次 Draw* 记成一条 `Render3DDraw`,`RenderCommands3D.h`),默认 IB/PDT VB 为 CPU 缓冲;`D3DXMath` 补 `PerspectiveFovRH`/`OrthoRH`/`OrthoOffCenterRH` 与 `ID3DXMatrixStack`。相机:`PythonApplicationCamera.cpp` 原样移植 `__UpdateCamera`/`SetCamera`/`SetCenterPosition`/`GetCenterPosition` 等(成员放文件内静态结构,平台没有 `CPythonApplication` 对象),`Process` 按 40250 顺序调 `__UpdateCamera`→`OnCameraUpdate`→`OnUIUpdate`→`Begin`/`SetInterfaceRenderState`/`OnUIRender`/`End`;`CScreen::Begin/End/Set*Operation`、`CPythonGraphic::Set{Game,Interface}RenderState/PushState/PopState/GetOrthoDepth`、`CCullingManager::Process` 的 view/proj 更新(视锥剔除等 SphereLib)原样;`pending` 补 `CPythonPlayer::NEW_GetMainActorPosition/NEW_GetMainActorPtr/NEW_FindActorPtr/SetMainCharacterIndex`(事件处理器留待 `PythonPlayerEventHandler`)、`CMapManager::IsMapReady`。`port.login_flow` 断言某帧有贴图、带法线/UV 的三角形绘制,投影为 `SetPerspective` 的 RH 透视(_34=-1),且顶点全部落在屏幕内(相机对准主角);离线与 `port.login_live`(192.168.21.203)2026-09-23 通过。下一步 e.2 Godot 消费端 | 4. **2V3 — 本地移动**:加入 `PythonPlayer`、`PythonPlayerInput*`、`PythonPlayerEventHandler`、 `InstanceBaseMovement`、`ActorInstance{Motion,Event,Position,Rotation,CollisionDetection}` 的实际依赖闭包。验收为输入经过新路径 改变位置/朝向、发送与 40250 相同的移动封包,并在离线边界测试和真服 smoke 中通过。接通时删除对应 legacy 玩法逻辑。 diff --git a/extension/src/platform/EterLib/CpuBuffer.h b/extension/src/platform/EterLib/CpuBuffer.h index 113697c1..767a5f24 100644 --- a/extension/src/platform/EterLib/CpuBuffer.h +++ b/extension/src/platform/EterLib/CpuBuffer.h @@ -11,12 +11,30 @@ struct MtCpuVertexBuffer : IDirect3DVertexBuffer8 { std::vector bytes; DWORD fvf = 0; + + HRESULT Lock(UINT offset, UINT size, BYTE** data, DWORD) override + { + if (size_t(offset) + size > bytes.size()) + return E_FAIL; + *data = bytes.data() + offset; + return S_OK; + } + HRESULT Unlock() override { return S_OK; } }; struct MtCpuIndexBuffer : IDirect3DIndexBuffer8 { std::vector bytes; D3DFORMAT format = D3DFMT_INDEX16; + + HRESULT Lock(UINT offset, UINT size, BYTE** data, DWORD) override + { + if (size_t(offset) + size > bytes.size()) + return E_FAIL; + *data = bytes.data() + offset; + return S_OK; + } + HRESULT Unlock() override { return S_OK; } }; // D3DXGetFVFVertexSize. diff --git a/extension/src/platform/EterLib/CullingManager.cpp b/extension/src/platform/EterLib/CullingManager.cpp index 9a611abe..532a7b8d 100644 --- a/extension/src/platform/EterLib/CullingManager.cpp +++ b/extension/src/platform/EterLib/CullingManager.cpp @@ -40,9 +40,16 @@ auto CCullingManager::Update() -> void MT_PLATFORM_STUB(); } -auto CCullingManager::Process() -> void +// 40250 CullingManager.cpp:105. RenderGame calls it after SetPerspective; it hands the camera's view and +// the projection to CStateManager for the scene. +// PORT: BuildViewFrustum and m_Factory->FrustumTest follow in 40250; the sphere-pack culling (SphereLib) +// is not ported, so every registered object stays visible. +void CCullingManager::Process() { - MT_PLATFORM_STUB(); + //DWORD time = ELTimer_GetMSec(); + //Frustum f; + UpdateViewMatrix(); + UpdateProjMatrix(); } auto CCullingManager::FindRange(const Vector3d &, float) -> void diff --git a/extension/src/platform/EterLib/GrpBase.cpp b/extension/src/platform/EterLib/GrpBase.cpp deleted file mode 100644 index 39f48275..00000000 --- a/extension/src/platform/EterLib/GrpBase.cpp +++ /dev/null @@ -1,378 +0,0 @@ -// Platform skeleton for EterLib/GrpBase.h (40250 EterLib/GrpBase.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterLib/StdAfx.h" -#include "EterLib/GrpBase.h" - -#include "../PlatformStub.h" -#include -#include "UIRenderCommands.h" - -auto CGraphicBase::GetAvailableTextureMemory() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::GetViewMatrix() -> const D3DXMATRIX & -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::GetIdentityMatrix() -> const D3DXMATRIX & -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -CGraphicBase::CGraphicBase() -{ - MT_PLATFORM_STUB(); -} - -CGraphicBase::~CGraphicBase() -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetSimpleCamera(float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetEyeCamera(float, float, float, float, float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetAroundCamera(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetPositionCamera(float, float, float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::MoveCamera(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetTargetPosition(float *, float *, float *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetCameraPosition(float *, float *, float *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetOrtho2D(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetOrtho3D(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetPerspective(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetFOV() -> float -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::PushMatrix() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::MultMatrix(const D3DXMATRIX *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::MultMatrixLocal(const D3DXMATRIX *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::Translate(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::Rotate(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::RotateLocal(float, float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::RotateYawPitchRollLocal(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::Scale(float, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::PopMatrix() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::LoadMatrix(const D3DXMATRIX &) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetMatrix(D3DXMATRIX *) const -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetMatrixPointer() const -> const D3DXMATRIX * -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::GetSphereMatrix(D3DXMATRIX *, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::InitScreenEffect() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetScreenEffectWaving(float, int) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetScreenEffectFlashing(float, const D3DXCOLOR &) -> void -{ - MT_PLATFORM_STUB(); -} - -// 40250 GrpBase.cpp:458: the bytes B, G, R, A of a little-endian D3DCOLOR. -auto CGraphicBase::GetColor(float r, float g, float b, float a) -> DWORD -{ - BYTE argb[4] = - { - (BYTE) (255.0f * b), - (BYTE) (255.0f * g), - (BYTE) (255.0f * r), - (BYTE) (255.0f * a) - }; - - DWORD color; - std::memcpy(&color, argb, sizeof(color)); - return color; -} - -auto CGraphicBase::GetFaceCount() -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::ResetFaceCount() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetLastResult() -> HRESULT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::UpdateProjMatrix() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::UpdateViewMatrix() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetViewport(DWORD, DWORD, DWORD, DWORD, float, float) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::GetBackBufferSize(UINT *width, UINT *height) -> void -{ - UIRenderGetSize(width, height); -} - -auto CGraphicBase::IsTLVertexClipping() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::IsFastTNL() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::IsLowTextureMemory() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::IsHighTextureMemory() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::SetDefaultIndexBuffer(UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CGraphicBase::SetPDTStream(SPDTVertexRaw *, UINT) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CGraphicBase::SetPDTStream(SPDTVertex *, UINT) -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -decltype(CGraphicBase::ms_matIdentity) CGraphicBase::ms_matIdentity{}; - -decltype(CGraphicBase::ms_matView) CGraphicBase::ms_matView{}; - -decltype(CGraphicBase::ms_matProj) CGraphicBase::ms_matProj{}; - -decltype(CGraphicBase::ms_matInverseView) CGraphicBase::ms_matInverseView{}; - -decltype(CGraphicBase::ms_matInverseViewYAxis) CGraphicBase::ms_matInverseViewYAxis{}; - -decltype(CGraphicBase::ms_matWorld) CGraphicBase::ms_matWorld{}; - -decltype(CGraphicBase::ms_matWorldView) CGraphicBase::ms_matWorldView{}; - -auto CGraphicBase::UpdatePipeLineMatrix() -> void -{ - MT_PLATFORM_STUB(); -} - -decltype(CGraphicBase::ms_lpSphereMesh) CGraphicBase::ms_lpSphereMesh{}; - -decltype(CGraphicBase::ms_lpCylinderMesh) CGraphicBase::ms_lpCylinderMesh{}; - -decltype(CGraphicBase::ms_hLastResult) CGraphicBase::ms_hLastResult{}; - -decltype(CGraphicBase::ms_iWidth) CGraphicBase::ms_iWidth{}; - -decltype(CGraphicBase::ms_iHeight) CGraphicBase::ms_iHeight{}; - -decltype(CGraphicBase::ms_iD3DAdapterInfo) CGraphicBase::ms_iD3DAdapterInfo{}; - -decltype(CGraphicBase::ms_iD3DDevInfo) CGraphicBase::ms_iD3DDevInfo{}; - -decltype(CGraphicBase::ms_iD3DModeInfo) CGraphicBase::ms_iD3DModeInfo{}; - -decltype(CGraphicBase::ms_kD3DDetector) CGraphicBase::ms_kD3DDetector{}; - -decltype(CGraphicBase::ms_hWnd) CGraphicBase::ms_hWnd{}; - -decltype(CGraphicBase::ms_hDC) CGraphicBase::ms_hDC{}; - -decltype(CGraphicBase::ms_lpd3d) CGraphicBase::ms_lpd3d{}; - -decltype(CGraphicBase::ms_lpd3dDevice) CGraphicBase::ms_lpd3dDevice{}; - -decltype(CGraphicBase::ms_lpd3dMatStack) CGraphicBase::ms_lpd3dMatStack{}; - -decltype(CGraphicBase::ms_Viewport) CGraphicBase::ms_Viewport{}; - -decltype(CGraphicBase::ms_faceCount) CGraphicBase::ms_faceCount{}; - -decltype(CGraphicBase::ms_d3dCaps) CGraphicBase::ms_d3dCaps{}; - -decltype(CGraphicBase::ms_d3dPresentParameter) CGraphicBase::ms_d3dPresentParameter{}; - -decltype(CGraphicBase::ms_dwD3DBehavior) CGraphicBase::ms_dwD3DBehavior{}; - -decltype(CGraphicBase::ms_ptVS) CGraphicBase::ms_ptVS{}; - -decltype(CGraphicBase::ms_pntVS) CGraphicBase::ms_pntVS{}; - -decltype(CGraphicBase::ms_pnt2VS) CGraphicBase::ms_pnt2VS{}; - -decltype(CGraphicBase::ms_matScreen0) CGraphicBase::ms_matScreen0{}; - -decltype(CGraphicBase::ms_matScreen1) CGraphicBase::ms_matScreen1{}; - -decltype(CGraphicBase::ms_matScreen2) CGraphicBase::ms_matScreen2{}; - -decltype(CGraphicBase::ms_vtPickRayOrig) CGraphicBase::ms_vtPickRayOrig{}; - -decltype(CGraphicBase::ms_vtPickRayDir) CGraphicBase::ms_vtPickRayDir{}; - -decltype(CGraphicBase::ms_fFieldOfView) CGraphicBase::ms_fFieldOfView{}; - -decltype(CGraphicBase::ms_fAspect) CGraphicBase::ms_fAspect{}; - -decltype(CGraphicBase::ms_fNearY) CGraphicBase::ms_fNearY{}; - -decltype(CGraphicBase::ms_fFarY) CGraphicBase::ms_fFarY{}; - -decltype(CGraphicBase::ms_dwWavingEndTime) CGraphicBase::ms_dwWavingEndTime{}; - -decltype(CGraphicBase::ms_iWavingPower) CGraphicBase::ms_iWavingPower{}; - -decltype(CGraphicBase::ms_dwFlashingEndTime) CGraphicBase::ms_dwFlashingEndTime{}; - -decltype(CGraphicBase::ms_FlashingColor) CGraphicBase::ms_FlashingColor{}; - -decltype(CGraphicBase::ms_Ray) CGraphicBase::ms_Ray{}; - -decltype(CGraphicBase::ms_bSupportDXT) CGraphicBase::ms_bSupportDXT{}; - -decltype(CGraphicBase::ms_isLowTextureMemory) CGraphicBase::ms_isLowTextureMemory{}; - -decltype(CGraphicBase::ms_isHighTextureMemory) CGraphicBase::ms_isHighTextureMemory{}; - -decltype(CGraphicBase::ms_alpd3dPDTVB) CGraphicBase::ms_alpd3dPDTVB{}; - -decltype(CGraphicBase::ms_alpd3dDefIB) CGraphicBase::ms_alpd3dDefIB{}; - -auto PixelPositionToD3DXVECTOR3(const D3DXVECTOR3 &, D3DXVECTOR3 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto D3DXVECTOR3ToPixelPosition(const D3DXVECTOR3 &, D3DXVECTOR3 *) -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/EterLib/GrpDevice.cpp b/extension/src/platform/EterLib/GrpDevice.cpp index e7e46fd0..b79c2d5b 100644 --- a/extension/src/platform/EterLib/GrpDevice.cpp +++ b/extension/src/platform/EterLib/GrpDevice.cpp @@ -1,34 +1,143 @@ -// Platform skeleton for EterLib/GrpDevice.h (40250 EterLib/GrpDevice.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. +// 40250 EterLib/GrpDevice.cpp over the platform's recording device (RecordingDevice.h): there is no +// Direct3D object, adapter detection or window; Create makes the device, CStateManager, the matrix +// stack and the default buffers as 40250 does. The remaining MT_PLATFORM_STUB() bodies (device reset, +// web-browser mode, driver warnings) have no platform counterpart yet. #include "EterLib/StdAfx.h" #include "EterLib/GrpDevice.h" +#include "EterLib/StateManager.h" +#include "EterBase/Stl.h" + +#include "CpuBuffer.h" +#include "RecordingDevice.h" + +#include #include "../PlatformStub.h" +bool GRAPHICS_CAPS_CAN_NOT_DRAW_LINE = false; +bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW = false; +bool GRAPHICS_CAPS_HALF_SIZE_IMAGE = false; +bool GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER = false; +bool GRAPHICS_CAPS_SOFTWARE_TILING = false; + CGraphicDevice::CGraphicDevice() +: m_uBackBufferCount(0) { - MT_PLATFORM_STUB(); + __Initialize(); } CGraphicDevice::~CGraphicDevice() { - MT_PLATFORM_STUB(); + Destroy(); } -auto CGraphicDevice::InitBackBufferCount(UINT) -> void +void CGraphicDevice::InitBackBufferCount(UINT uBackBufferCount) { - MT_PLATFORM_STUB(); + m_uBackBufferCount=uBackBufferCount; } -auto CGraphicDevice::Destroy() -> void +void CGraphicDevice::Destroy() { - MT_PLATFORM_STUB(); + __DestroyPDTVertexBufferList(); + __DestroyDefaultIndexBufferList(); + + // PORT: no DC, vertex shader objects or D3DX meshes; the stream "shaders" are FVF codes. + ms_ptVS = 0; + ms_pntVS = 0; + ms_pnt2VS = 0; + + safe_release(ms_lpd3dMatStack); + safe_release(ms_lpd3dDevice); + + if (m_pStateManager) + { + delete m_pStateManager; + m_pStateManager = NULL; + } + + __Initialize(); } -auto CGraphicDevice::Create(HWND, int, int, bool, int, int) -> int +int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int /*iBit*/, int iReflashRate) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + int iRet = CREATE_OK; + + Destroy(); + + ms_iWidth = iHres; + ms_iHeight = iVres; + + // PORT: in place of Direct3DCreate8, the display-mode detection and CreateDevice: the recording + // device renders through Godot, which supports DXT and has no refresh-rate or T&L failures. + ms_hWnd = hWnd; + ms_lpd3dDevice = MtCreateRecordingDevice(iHres, iVres); + ms_dwD3DBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING; + ms_d3dPresentParameter.BackBufferWidth = iHres; + ms_d3dPresentParameter.BackBufferHeight = iVres; + ms_d3dPresentParameter.Windowed = Windowed; + + if (FAILED((ms_hLastResult = ms_lpd3dDevice->GetDeviceCaps(&ms_d3dCaps)))) + { + Tracenf("IDirect3DDevice.GetDeviceCaps - ERROR %d", ms_hLastResult); + return CREATE_GET_DEVICE_CAPS2; + } + + ms_lpd3dDevice->GetViewport(&ms_Viewport); + + m_pStateManager = new CStateManager(ms_lpd3dDevice); + + D3DXCreateMatrixStack(0, &ms_lpd3dMatStack); + ms_lpd3dMatStack->LoadIdentity(); + + ms_ptVS = CreatePTStreamVertexShader(); + ms_pntVS = CreatePNTStreamVertexShader(); + ms_pnt2VS = CreatePNT2StreamVertexShader(); + + D3DXMatrixIdentity(&ms_matIdentity); + D3DXMatrixIdentity(&ms_matView); + D3DXMatrixIdentity(&ms_matProj); + D3DXMatrixIdentity(&ms_matInverseView); + D3DXMatrixIdentity(&ms_matInverseViewYAxis); + D3DXMatrixIdentity(&ms_matScreen0); + D3DXMatrixIdentity(&ms_matScreen1); + D3DXMatrixIdentity(&ms_matScreen2); + + ms_matScreen0._11 = 1; + ms_matScreen0._22 = -1; + + ms_matScreen1._41 = 1; + ms_matScreen1._42 = 1; + + ms_matScreen2._11 = (float) iHres / 2; + ms_matScreen2._22 = (float) iVres / 2; + + // PORT: no D3DXCreateSphere/D3DXCreateCylinder (debug collision rendering) and no Clear. + + if (!__CreateDefaultIndexBufferList()) + return false; + + if (!__CreatePDTVertexBufferList()) + return false; + + DWORD dwTexMemSize = GetAvailableTextureMemory(); + + if (dwTexMemSize < 64 * 1024 * 1024) + ms_isLowTextureMemory = true; + else + ms_isLowTextureMemory = false; + + if (dwTexMemSize > 100 * 1024 * 1024) + ms_isHighTextureMemory = true; + else + ms_isHighTextureMemory = false; + + if (ms_d3dCaps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER) + GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER=false; + else + GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER=true; + + // PORT: the SIS/3dfx driver checks have no adapter identifier to test. + return (iRet); } auto CGraphicDevice::GetDeviceState() -> EDeviceState @@ -69,9 +178,23 @@ auto CGraphicDevice::RegisterWarningString(UINT, const char *) -> void MT_PLATFORM_STUB(); } -auto CGraphicDevice::__Initialize() -> void +void CGraphicDevice::__Initialize() { - MT_PLATFORM_STUB(); + ms_iD3DAdapterInfo=D3DADAPTER_DEFAULT; + ms_iD3DDevInfo=D3DADAPTER_DEFAULT; + ms_iD3DModeInfo=D3DADAPTER_DEFAULT; + + ms_lpd3d = NULL; + ms_lpd3dDevice = NULL; + ms_lpd3dMatStack = NULL; + + ms_dwWavingEndTime = 0; + ms_dwFlashingEndTime = 0; + + m_pStateManager = NULL; + + __InitializeDefaultIndexBufferList(); + __InitializePDTVertexBufferList(); } auto CGraphicDevice::__IsInDriverBlackList(D3D_CAdapterInfo &) -> bool @@ -85,60 +208,133 @@ auto CGraphicDevice::__WarningMessage(HWND, UINT) -> void MT_PLATFORM_STUB(); } -auto CGraphicDevice::__InitializeDefaultIndexBufferList() -> void +void CGraphicDevice::__InitializeDefaultIndexBufferList() { - MT_PLATFORM_STUB(); + for (UINT i=0; i void +void CGraphicDevice::__DestroyDefaultIndexBufferList() { - MT_PLATFORM_STUB(); + for (UINT i=0; i bool +bool CGraphicDevice::__CreateDefaultIndexBufferList() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + static const WORD c_awLineIndices[2] = { 0, 1, }; + static const WORD c_awLineTriIndices[6] = { 0, 1, 0, 2, 1, 2, }; + static const WORD c_awLineRectIndices[8] = { 0, 1, 0, 2, 1, 3, 2, 3,}; + static const WORD c_awLineCubeIndices[24] = { + 0, 1, 0, 2, 1, 3, 2, 3, + 0, 4, 1, 5, 2, 6, 3, 7, + 4, 5, 4, 6, 5, 7, 6, 7, + }; + static const WORD c_awFillTriIndices[3]= { 0, 1, 2, }; + static const WORD c_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, }; + static const WORD c_awFillCubeIndices[36] = { + 0, 1, 2, 1, 3, 2, + 2, 0, 6, 0, 4, 6, + 0, 1, 4, 1, 5, 4, + 1, 3, 5, 3, 7, 5, + 3, 2, 7, 2, 6, 7, + 4, 5, 6, 5, 7, 6, + }; + + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE, 2, c_awLineIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_TRI, 6, c_awLineTriIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_RECT, 8, c_awLineRectIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_CUBE, 24, c_awLineCubeIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_TRI, 3, c_awFillTriIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_RECT, 6, c_awFillRectIndices)) + return false; + if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_CUBE, 36, c_awFillCubeIndices)) + return false; + + return true; } -auto CGraphicDevice::__CreateDefaultIndexBuffer(UINT, UINT, const WORD *) -> bool +bool CGraphicDevice::__CreateDefaultIndexBuffer(UINT eDefIB, UINT uIdxCount, const WORD* c_awIndices) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(ms_alpd3dDefIB[eDefIB]==NULL); + + // PORT: a CPU buffer in place of CreateIndexBuffer (CpuBuffer.h). + MtCpuIndexBuffer* pIB = new MtCpuIndexBuffer; + pIB->bytes.resize(sizeof(WORD)*uIdxCount); + pIB->format = D3DFMT_INDEX16; + ms_alpd3dDefIB[eDefIB] = pIB; + + WORD* dstIndices; + if (FAILED( + ms_alpd3dDefIB[eDefIB]->Lock(0, 0, (BYTE**)&dstIndices, 0) + )) return false; + + memcpy(dstIndices, c_awIndices, sizeof(WORD)*uIdxCount); + + ms_alpd3dDefIB[eDefIB]->Unlock(); + + return true; } -auto CGraphicDevice::__InitializePDTVertexBufferList() -> void +void CGraphicDevice::__InitializePDTVertexBufferList() { - MT_PLATFORM_STUB(); + for (UINT i=0; i void +void CGraphicDevice::__DestroyPDTVertexBufferList() { - MT_PLATFORM_STUB(); + for (UINT i=0; i bool +bool CGraphicDevice::__CreatePDTVertexBufferList() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + for (UINT i=0; ibytes.resize(sizeof(TPDTVertex)*PDT_VERTEX_NUM); + pVB->fvf = D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1; + ms_alpd3dPDTVB[i] = pVB; + } + return true; } -auto CGraphicDevice::CreatePTStreamVertexShader() -> DWORD +// PORT: the stream vertex shaders are declarations for the fixed-function pipeline; the recording +// device decodes vertices by FVF, so each returns the FVF matching its declaration. PT keeps its +// texture coordinates in stream 1, which the device does not record: stream 0 is position only. +DWORD CGraphicDevice::CreatePTStreamVertexShader() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(ms_lpd3dDevice != NULL); + return D3DFVF_XYZ; } -auto CGraphicDevice::CreatePNTStreamVertexShader() -> DWORD +DWORD CGraphicDevice::CreatePNTStreamVertexShader() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(ms_lpd3dDevice != NULL); + return D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1; } -auto CGraphicDevice::CreatePNT2StreamVertexShader() -> DWORD +DWORD CGraphicDevice::CreatePNT2StreamVertexShader() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(ms_lpd3dDevice != NULL); + return D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2; } auto CGraphicDevice::CreateDoublePNTStreamVertexShader() -> DWORD diff --git a/extension/src/platform/EterLib/GrpImageTexture.cpp b/extension/src/platform/EterLib/GrpImageTexture.cpp index 60e84534..953fcdfe 100644 --- a/extension/src/platform/EterLib/GrpImageTexture.cpp +++ b/extension/src/platform/EterLib/GrpImageTexture.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace { unsigned little16(const unsigned char* data) { return data[0] | (unsigned(data[1]) << 8); } @@ -100,6 +101,25 @@ MemoryTexture* live_memory_texture(const IDirect3DTexture8* texture) if (entry.second == texture) return entry.second; return nullptr; } + +// PORT: the IDirect3DTexture8 behind a file texture (CreateFromMemoryFile). The canvas and the 3D +// renderer decode the file themselves; the handle only carries the pack path so a texture bound +// through STATEMANAGER.SetTexture(stage, GetD3DTexture()) can be named. +struct FileTexture : IDirect3DTexture8 +{ + std::string name; +}; + +std::set g_file_textures; // guarded by g_memory_mutex + +IDirect3DTexture8* new_file_texture(const std::string& name) +{ + auto* file = new FileTexture(); + file->name = name; + std::lock_guard lock(g_memory_mutex); + g_file_textures.insert(file); + return file; +} } void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture) @@ -108,9 +128,22 @@ void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture) if (MemoryTexture* memory = live_memory_texture(texture)) { g_memory.erase(memory->id); delete memory; + } else if (g_file_textures.erase(static_cast(texture))) { + delete static_cast(texture); } } +std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle) +{ + if (!handle) return {}; + const auto* texture = static_cast(handle); + std::lock_guard lock(g_memory_mutex); + if (const MemoryTexture* memory = live_memory_texture(texture)) + return "mem:" + std::to_string(memory->id) + "@" + std::to_string(memory->revision); + const auto* file = static_cast(texture); + return g_file_textures.count(file) ? file->name : std::string(); +} + bool UIRenderMemoryTexture(const std::string& name, UIMemoryTexture* out) { if (name.compare(0, 4, "mem:") != 0 || !out) return false; @@ -195,6 +228,11 @@ auto CGraphicImageTexture::CreateFromTexturePointer(const CGraphicTexture *sourc // 40250 shares the source's D3D texture; the canvas names textures by pack path instead. if (const auto* image = dynamic_cast(source)) m_stFileName = image->m_stFileName; + // PORT: 40250 AddRefs the source's texture; this handle is not reference counted, so the copy gets + // its own named handle. + DestroyDeviceObjects(); + if (!m_bEmpty && !m_stFileName.empty()) + m_lpd3dTexture = new_file_texture(m_stFileName); } auto CGraphicImageTexture::CreateFromDiskFile(const char *, D3DFORMAT, DWORD) -> bool @@ -223,6 +261,8 @@ auto CGraphicImageTexture::CreateFromMemoryFile(UINT size, const void *bytes, D3 if (!width || !height || width > 16384 || height > 16384) return false; m_width = static_cast(width); m_height = static_cast(height); m_bEmpty = false; + DestroyDeviceObjects(); + m_lpd3dTexture = new_file_texture(m_stFileName); return true; } diff --git a/extension/src/platform/EterLib/GrpScreen.cpp b/extension/src/platform/EterLib/GrpScreen.cpp index ec79cc41..b3596e04 100644 --- a/extension/src/platform/EterLib/GrpScreen.cpp +++ b/extension/src/platform/EterLib/GrpScreen.cpp @@ -2,19 +2,19 @@ // Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. #include "EterLib/StdAfx.h" #include "EterLib/GrpScreen.h" +#include "EterLib/StateManager.h" #include "../PlatformStub.h" #include "UIRenderCommands.h" #include +// 40250 GrpScreen.cpp:838 CScreen::CScreen() { - MT_PLATFORM_STUB(); } CScreen::~CScreen() { - MT_PLATFORM_STUB(); } auto CScreen::ClearDepthBuffer() -> void @@ -27,15 +27,26 @@ auto CScreen::Clear() -> void MT_PLATFORM_STUB(); } -auto CScreen::Begin() -> bool +// 40250 GrpScreen.cpp:691. CPythonApplication::Process brackets the frame's render with Begin/End; only +// inside the scene does CStateManager hand transforms to the recording device. +bool CScreen::Begin() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + assert(ms_lpd3dDevice != NULL); + ResetFaceCount(); + + if (!STATEMANAGER.BeginScene()) + { + Tracenf("BeginScene FAILED\n"); + return false; + } + + return true; } -auto CScreen::End() -> void +// 40250 GrpScreen.cpp:705 +void CScreen::End() { - MT_PLATFORM_STUB(); + STATEMANAGER.EndScene(); } auto CScreen::Show(HWND) -> void @@ -158,19 +169,41 @@ auto CScreen::RenderCylinder(const D3DXMATRIX *, float, float, float, float, flo MT_PLATFORM_STUB(); } -auto CScreen::SetColorOperation() -> void +// 40250 GrpScreen.cpp +void CScreen::SetColorOperation() { - MT_PLATFORM_STUB(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } -auto CScreen::SetDiffuseOperation() -> void +// 40250 GrpScreen.cpp +void CScreen::SetDiffuseOperation() { - MT_PLATFORM_STUB(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } -auto CScreen::SetBlendOperation() -> void +// 40250 GrpScreen.cpp +void CScreen::SetBlendOperation() { - MT_PLATFORM_STUB(); + STATEMANAGER.SetTexture(0, NULL); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } auto CScreen::SetOneColorOperation(D3DXCOLOR &) -> void diff --git a/extension/src/platform/EterLib/GrpTexture.cpp b/extension/src/platform/EterLib/GrpTexture.cpp index af1184d9..746d304e 100644 --- a/extension/src/platform/EterLib/GrpTexture.cpp +++ b/extension/src/platform/EterLib/GrpTexture.cpp @@ -31,7 +31,7 @@ auto CGraphicTexture::GetD3DTexture() const -> LPDIRECT3DTEXTURE8 return m_lpd3dTexture; } -// PORT: safe_release(m_lpd3dTexture); the only textures this platform creates are memory textures. +// PORT: safe_release(m_lpd3dTexture); the platform textures are memory textures and file-texture handles. auto CGraphicTexture::DestroyDeviceObjects() -> void { if (m_lpd3dTexture) diff --git a/extension/src/platform/EterLib/RecordingDevice.cpp b/extension/src/platform/EterLib/RecordingDevice.cpp new file mode 100644 index 00000000..b22f40a2 --- /dev/null +++ b/extension/src/platform/EterLib/RecordingDevice.cpp @@ -0,0 +1,385 @@ +#include "RecordingDevice.h" +#include "RenderCommands3D.h" +#include "UIRenderCommands.h" +#include "CpuBuffer.h" + +#include +#include + +namespace { +std::mutex g_draws_mutex; +std::vector g_draws; + +struct VertexLayout { + unsigned stride = 0; + bool rhw = false; + int normal = -1, diffuse = -1, uv0 = -1, uv1 = -1; +}; + +// The element offsets of a fixed-function FVF (D3DXGetFVFVertexSize's order). +VertexLayout fvf_layout(DWORD fvf) +{ + VertexLayout layout; + unsigned offset = 0; + switch (fvf & D3DFVF_POSITION_MASK) + { + case D3DFVF_XYZ: offset = 12; break; + case D3DFVF_XYZRHW: offset = 16; layout.rhw = true; break; + case D3DFVF_XYZB1: offset = 16; break; + case D3DFVF_XYZB2: offset = 20; break; + case D3DFVF_XYZB3: offset = 24; break; + case D3DFVF_XYZB4: offset = 28; break; + case D3DFVF_XYZB5: offset = 32; break; + } + if (fvf & D3DFVF_NORMAL) { layout.normal = offset; offset += 12; } + if (fvf & D3DFVF_PSIZE) offset += 4; + if (fvf & D3DFVF_DIFFUSE) { layout.diffuse = offset; offset += 4; } + if (fvf & D3DFVF_SPECULAR) offset += 4; + const unsigned texCount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + for (unsigned i = 0; i < texCount; ++i) + { + static const unsigned coordSize[4] = { 8, 12, 16, 4 }; + if (i == 0) layout.uv0 = offset; + if (i == 1) layout.uv1 = offset; + offset += coordSize[(fvf >> (16 + i * 2)) & 3]; + } + layout.stride = offset; + return layout; +} + +void copy_color(float out[4], const D3DCOLORVALUE& c) +{ + out[0] = c.r; out[1] = c.g; out[2] = c.b; out[3] = c.a; +} + +class RecordingDevice final : public IDirect3DDevice8 +{ +public: + RecordingDevice(int width, int height) : m_width(width), m_height(height) + { + static const float identity[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; + for (auto& matrix : m_transforms) + std::memcpy(matrix, identity, sizeof(identity)); + std::memset(&m_material, 0, sizeof(m_material)); + m_material.Diffuse = { 1, 1, 1, 1 }; + std::memset(m_lights, 0, sizeof(m_lights)); + } + + ULONG AddRef() override { return ++m_refs; } + ULONG Release() override + { + const ULONG refs = --m_refs; + if (!refs) + delete this; + return refs; + } + + // PORT: a D3D8 HAL on a T&L card (D3DDEVCAPS_HWTRANSFORMANDLIGHT), 8 lights, 4 texture stages. + HRESULT GetDeviceCaps(D3DCAPS8* caps) override + { + std::memset(caps, 0, sizeof(*caps)); + caps->DevCaps = D3DDEVCAPS_HWTRANSFORMANDLIGHT; + caps->MaxActiveLights = 8; + caps->MaxTextureBlendStages = 4; + caps->MaxSimultaneousTextures = 4; + caps->MaxTextureWidth = caps->MaxTextureHeight = 4096; + caps->MaxAnisotropy = 16; + caps->MaxPrimitiveCount = 0xFFFFF; + caps->MaxVertexIndex = 0xFFFFF; + caps->MaxStreams = 8; + caps->MaxStreamStride = 255; + caps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_MIRROR; + return S_OK; + } + HRESULT GetViewport(D3DVIEWPORT8* viewport) override + { + *viewport = { 0, 0, DWORD(m_width), DWORD(m_height), 0.0f, 1.0f }; + return S_OK; + } + // PORT: CPU memory has no texture budget; report the 64MB of a mid-range 2004 card. + UINT GetAvailableTextureMem() override { return 64u << 20; } + HRESULT BeginScene() override { return S_OK; } + HRESULT EndScene() override { return S_OK; } + + HRESULT SetTransform(D3DTRANSFORMSTATETYPE state, const D3DMATRIX* matrix) override + { + if (unsigned(state) < kTransforms && matrix) + std::memcpy(m_transforms[state], matrix, sizeof(float) * 16); + return S_OK; + } + HRESULT GetTransform(D3DTRANSFORMSTATETYPE state, D3DMATRIX* matrix) override + { + if (unsigned(state) < kTransforms) + std::memcpy(matrix, m_transforms[state], sizeof(float) * 16); + return S_OK; + } + HRESULT SetMaterial(const D3DMATERIAL8* material) override { m_material = *material; return S_OK; } + HRESULT SetLight(DWORD index, const D3DLIGHT8* light) override + { + if (index < 8) + m_lights[index] = *light; + return S_OK; + } + HRESULT SetRenderState(D3DRENDERSTATETYPE state, DWORD value) override + { + if (unsigned(state) < kRenderStates) + m_renderStates[state] = value; + return S_OK; + } + HRESULT SetTexture(DWORD stage, IDirect3DBaseTexture8* texture) override + { + if (stage < kStages) + m_textures[stage] = texture; + return S_OK; + } + HRESULT SetTextureStageState(DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) override + { + if (stage < kStages && unsigned(type) < kStageStates) + m_stageStates[stage][type] = value; + return S_OK; + } + // PORT: fixed function only; CGraphicDevice's stream "shaders" are the FVFs they describe. + HRESULT SetVertexShader(DWORD handle) override { m_fvf = handle; return S_OK; } + HRESULT SetPixelShader(DWORD) override { return S_OK; } + HRESULT SetVertexShaderConstant(DWORD, const void*, DWORD) override { return S_OK; } + HRESULT SetPixelShaderConstant(DWORD, const void*, DWORD) override { return S_OK; } + HRESULT SetStreamSource(UINT stream, IDirect3DVertexBuffer8* buffer, UINT stride) override + { + if (stream == 0) + { + m_stream = static_cast(buffer); + m_streamStride = stride; + } + return S_OK; + } + HRESULT SetIndices(IDirect3DIndexBuffer8* indices, UINT baseVertex) override + { + m_indices = static_cast(indices); + m_baseVertex = baseVertex; + return S_OK; + } + + HRESULT DrawPrimitive(D3DPRIMITIVETYPE type, UINT startVertex, UINT primitiveCount) override + { + if (!m_stream) + return E_FAIL; + const UINT count = index_count(type, primitiveCount); + std::vector indices(count); + for (UINT i = 0; i < count; ++i) + indices[i] = startVertex + i; + record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices); + return S_OK; + } + HRESULT DrawIndexedPrimitive(D3DPRIMITIVETYPE type, UINT, UINT, UINT startIndex, UINT primitiveCount) override + { + if (!m_stream || !m_indices) + return E_FAIL; + std::vector indices; + if (!read_indices(m_indices->bytes.data(), m_indices->bytes.size(), m_indices->format, startIndex, + index_count(type, primitiveCount), m_baseVertex, &indices)) + return E_FAIL; + record(type, primitiveCount, m_stream->bytes.data(), m_stream->bytes.size(), m_streamStride, indices); + return S_OK; + } + HRESULT DrawPrimitiveUP(D3DPRIMITIVETYPE type, UINT primitiveCount, const void* vertices, UINT stride) override + { + const UINT count = index_count(type, primitiveCount); + std::vector indices(count); + for (UINT i = 0; i < count; ++i) + indices[i] = i; + record(type, primitiveCount, static_cast(vertices), size_t(count) * stride, stride, indices); + return S_OK; + } + HRESULT DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE type, UINT minVertex, UINT numVertices, UINT primitiveCount, + const void* indexData, D3DFORMAT indexFormat, const void* vertices, UINT stride) override + { + const UINT count = index_count(type, primitiveCount); + const size_t indexSize = indexFormat == D3DFMT_INDEX32 ? 4 : 2; + std::vector indices; + if (!read_indices(static_cast(indexData), count * indexSize, indexFormat, 0, count, 0, &indices)) + return E_FAIL; + record(type, primitiveCount, static_cast(vertices), size_t(minVertex + numVertices) * stride, stride, indices); + return S_OK; + } + +private: + static constexpr unsigned kTransforms = 512; // D3DTS_WORLDMATRIX(0..255) = 256..511 + static constexpr unsigned kRenderStates = 256; + static constexpr unsigned kStages = 8; + static constexpr unsigned kStageStates = 32; + + static UINT index_count(D3DPRIMITIVETYPE type, UINT primitives) + { + switch (type) + { + case D3DPT_POINTLIST: return primitives; + case D3DPT_LINELIST: return primitives * 2; + case D3DPT_LINESTRIP: return primitives + 1; + case D3DPT_TRIANGLELIST: return primitives * 3; + case D3DPT_TRIANGLESTRIP: case D3DPT_TRIANGLEFAN: return primitives + 2; + default: return 0; + } + } + + static bool read_indices(const uint8_t* bytes, size_t size, D3DFORMAT format, UINT start, UINT count, UINT base, + std::vector* out) + { + const size_t indexSize = format == D3DFMT_INDEX32 ? 4 : 2; + if ((size_t(start) + count) * indexSize > size) + return false; + out->resize(count); + for (UINT i = 0; i < count; ++i) + { + const uint8_t* p = bytes + (size_t(start) + i) * indexSize; + std::uint32_t index = indexSize == 4 ? (p[0] | (p[1] << 8) | (p[2] << 16) | (std::uint32_t(p[3]) << 24)) : (p[0] | (p[1] << 8)); + (*out)[i] = index + base; + } + return true; + } + + void record(D3DPRIMITIVETYPE type, UINT primitives, const uint8_t* vertices, size_t vertexBytes, UINT stride, + const std::vector& indices) + { + if (type == D3DPT_POINTLIST || indices.empty() || !vertices) + return; + VertexLayout layout = fvf_layout(m_fvf); + if (!stride) + stride = layout.stride; + if (!stride || stride < (layout.rhw ? 16u : 12u)) + return; + // Elements past the stream's stride live in another stream (CreatePTStreamVertexShader). + if (layout.normal + 12 > int(stride)) layout.normal = -1; + if (layout.diffuse + 4 > int(stride)) layout.diffuse = -1; + if (layout.uv0 + 8 > int(stride)) layout.uv0 = -1; + if (layout.uv1 + 8 > int(stride)) layout.uv1 = -1; + + Render3DDraw draw; + std::memcpy(draw.world, m_transforms[256], sizeof(draw.world)); // D3DTS_WORLD + std::memcpy(draw.view, m_transforms[D3DTS_VIEW], sizeof(draw.view)); + std::memcpy(draw.proj, m_transforms[D3DTS_PROJECTION], sizeof(draw.proj)); + draw.texture0 = UIRenderTextureNameFromHandle(m_textures[0]); + draw.texture1 = UIRenderTextureNameFromHandle(m_textures[1]); + draw.pretransformed = layout.rhw; + draw.lines = type == D3DPT_LINELIST || type == D3DPT_LINESTRIP; + + // Rebase: copy only the vertices the indices reference. + std::uint32_t lo = indices[0], hi = indices[0]; + for (std::uint32_t index : indices) + { + lo = std::min(lo, index); + hi = std::max(hi, index); + } + if ((size_t(hi) + 1) * stride > vertexBytes) + return; + const size_t count = size_t(hi - lo) + 1; + draw.positions.resize(count * 3); + if (layout.rhw) draw.rhw.resize(count); + if (layout.normal >= 0) draw.normals.resize(count * 3); + if (layout.uv0 >= 0) draw.uv0.resize(count * 2); + if (layout.uv1 >= 0) draw.uv1.resize(count * 2); + if (layout.diffuse >= 0) draw.diffuse.resize(count); + for (size_t i = 0; i < count; ++i) + { + const uint8_t* v = vertices + (lo + i) * stride; + std::memcpy(&draw.positions[i * 3], v, 12); + if (layout.rhw) std::memcpy(&draw.rhw[i], v + 12, 4); + if (layout.normal >= 0) std::memcpy(&draw.normals[i * 3], v + layout.normal, 12); + if (layout.uv0 >= 0) std::memcpy(&draw.uv0[i * 2], v + layout.uv0, 8); + if (layout.uv1 >= 0) std::memcpy(&draw.uv1[i * 2], v + layout.uv1, 8); + if (layout.diffuse >= 0) std::memcpy(&draw.diffuse[i], v + layout.diffuse, 4); + } + + // Strips and fans become lists; D3D flips the winding of every odd strip triangle. + switch (type) + { + case D3DPT_TRIANGLESTRIP: + for (UINT i = 0; i < primitives; ++i) + { + const std::uint32_t a = indices[i] - lo, b = indices[i + 1] - lo, c = indices[i + 2] - lo; + if (i & 1) draw.indices.insert(draw.indices.end(), { b, a, c }); + else draw.indices.insert(draw.indices.end(), { a, b, c }); + } + break; + case D3DPT_TRIANGLEFAN: + for (UINT i = 0; i < primitives; ++i) + draw.indices.insert(draw.indices.end(), { indices[0] - lo, indices[i + 1] - lo, indices[i + 2] - lo }); + break; + case D3DPT_LINESTRIP: + for (UINT i = 0; i < primitives; ++i) + draw.indices.insert(draw.indices.end(), { indices[i] - lo, indices[i + 1] - lo }); + break; + default: + for (std::uint32_t index : indices) + draw.indices.push_back(index - lo); + break; + } + + draw.alpha_blend = m_renderStates[D3DRS_ALPHABLENDENABLE]; + draw.src_blend = m_renderStates[D3DRS_SRCBLEND]; + draw.dest_blend = m_renderStates[D3DRS_DESTBLEND]; + draw.alpha_test = m_renderStates[D3DRS_ALPHATESTENABLE]; + draw.alpha_ref = m_renderStates[D3DRS_ALPHAREF]; + draw.alpha_func = m_renderStates[D3DRS_ALPHAFUNC]; + draw.cull_mode = m_renderStates[D3DRS_CULLMODE]; + draw.z_enable = m_renderStates[D3DRS_ZENABLE]; + draw.z_write = m_renderStates[D3DRS_ZWRITEENABLE]; + draw.z_func = m_renderStates[D3DRS_ZFUNC]; + draw.lighting = m_renderStates[D3DRS_LIGHTING]; + draw.texture_factor = m_renderStates[D3DRS_TEXTUREFACTOR]; + draw.fog_enable = m_renderStates[D3DRS_FOGENABLE]; + draw.ambient = m_renderStates[D3DRS_AMBIENT]; + for (int stage = 0; stage < 2; ++stage) + { + draw.color_op[stage] = m_stageStates[stage][D3DTSS_COLOROP]; + draw.color_arg1[stage] = m_stageStates[stage][D3DTSS_COLORARG1]; + draw.color_arg2[stage] = m_stageStates[stage][D3DTSS_COLORARG2]; + draw.alpha_op[stage] = m_stageStates[stage][D3DTSS_ALPHAOP]; + draw.alpha_arg1[stage] = m_stageStates[stage][D3DTSS_ALPHAARG1]; + draw.alpha_arg2[stage] = m_stageStates[stage][D3DTSS_ALPHAARG2]; + } + copy_color(draw.material_diffuse, m_material.Diffuse); + copy_color(draw.material_ambient, m_material.Ambient); + copy_color(draw.material_emissive, m_material.Emissive); + if (m_lights[0].Type == D3DLIGHT_DIRECTIONAL) + { + draw.light0 = true; + draw.light0_direction[0] = m_lights[0].Direction.x; + draw.light0_direction[1] = m_lights[0].Direction.y; + draw.light0_direction[2] = m_lights[0].Direction.z; + copy_color(draw.light0_diffuse, m_lights[0].Diffuse); + copy_color(draw.light0_ambient, m_lights[0].Ambient); + } + Render3DAdd(std::move(draw)); + } + + ULONG m_refs = 1; + int m_width, m_height; + float m_transforms[kTransforms][16]; + DWORD m_renderStates[kRenderStates] = {}; + DWORD m_stageStates[kStages][kStageStates] = {}; + IDirect3DBaseTexture8* m_textures[kStages] = {}; + D3DMATERIAL8 m_material; + D3DLIGHT8 m_lights[8]; + DWORD m_fvf = 0; + MtCpuVertexBuffer* m_stream = nullptr; + UINT m_streamStride = 0; + MtCpuIndexBuffer* m_indices = nullptr; + UINT m_baseVertex = 0; +}; +} + +IDirect3DDevice8* MtCreateRecordingDevice(int width, int height) { return new RecordingDevice(width, height); } + +void Render3DBeginFrame() +{ + std::lock_guard lock(g_draws_mutex); + g_draws.clear(); +} + +void Render3DAdd(Render3DDraw draw) +{ + std::lock_guard lock(g_draws_mutex); + g_draws.push_back(std::move(draw)); +} + +const std::vector& Render3DDraws() { return g_draws; } diff --git a/extension/src/platform/EterLib/RecordingDevice.h b/extension/src/platform/EterLib/RecordingDevice.h new file mode 100644 index 00000000..67cd8790 --- /dev/null +++ b/extension/src/platform/EterLib/RecordingDevice.h @@ -0,0 +1,7 @@ +#pragma once +// The platform's IDirect3DDevice8: CGraphicDevice::Create hands it to CStateManager, which keeps +// 40250's state caching; the device remembers the state it is given and turns every draw call into a +// Render3DDraw (RenderCommands3D.h) for the Godot renderer. +#include "EterLib/StdAfx.h" + +IDirect3DDevice8* MtCreateRecordingDevice(int width, int height); diff --git a/extension/src/platform/EterLib/RenderCommands3D.h b/extension/src/platform/EterLib/RenderCommands3D.h new file mode 100644 index 00000000..8b740e44 --- /dev/null +++ b/extension/src/platform/EterLib/RenderCommands3D.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include +#include + +// The 3D draw calls the ported game render (CPythonApplication::RenderGame) issues through +// CStateManager, recorded by the platform's IDirect3DDevice8 (RecordingDevice.cpp) and consumed by +// Godot. Like UIRenderCommands.h this header stays free of D3D and godot-cpp types. +// +// Matrices are D3D8's row-vector layout (translation in elements 12..14), exactly as 40250 set them. +struct Render3DDraw { + float world[16]; + float view[16]; + float proj[16]; + + // Stage 0/1 textures, named like UIRenderTextureName: the pack path of a file texture or + // "mem:@"; empty when the stage has no texture. + std::string texture0; + std::string texture1; + + // The referenced vertices, rebased so indices start at 0. normals/uv0/uv1/diffuse are empty when + // the vertex format has no such element. pretransformed: D3DFVF_XYZRHW (screen-space x, y, z, rhw + // in positions + rhw). + bool pretransformed = false; + std::vector positions; // x, y, z + std::vector rhw; + std::vector normals; // x, y, z + std::vector uv0; // u, v + std::vector uv1; // u, v + std::vector diffuse; // 0xAARRGGBB + std::vector indices; // triangle list (strips and fans are expanded), or line list + bool lines = false; + + // D3DRS_* / D3DTSS_* values in effect for the draw. + std::uint32_t alpha_blend = 0, src_blend = 0, dest_blend = 0; + std::uint32_t alpha_test = 0, alpha_ref = 0, alpha_func = 0; + std::uint32_t cull_mode = 0, z_enable = 0, z_write = 0, z_func = 0; + std::uint32_t lighting = 0, texture_factor = 0, fog_enable = 0; + std::uint32_t color_op[2] = {}, color_arg1[2] = {}, color_arg2[2] = {}; + std::uint32_t alpha_op[2] = {}, alpha_arg1[2] = {}, alpha_arg2[2] = {}; + // D3DMATERIAL8 diffuse/ambient/emissive (r, g, b, a) and light 0 when enabled. + float material_diffuse[4] = {1, 1, 1, 1}; + float material_ambient[4] = {}; + float material_emissive[4] = {}; + bool light0 = false; + float light0_direction[3] = {}; + float light0_diffuse[4] = {}; + float light0_ambient[4] = {}; + std::uint32_t ambient = 0; // D3DRS_AMBIENT +}; + +void Render3DBeginFrame(); +void Render3DAdd(Render3DDraw draw); +const std::vector& Render3DDraws(); diff --git a/extension/src/platform/EterLib/StateManager.cpp b/extension/src/platform/EterLib/StateManager.cpp deleted file mode 100644 index 86744262..00000000 --- a/extension/src/platform/EterLib/StateManager.cpp +++ /dev/null @@ -1,292 +0,0 @@ -// Platform skeleton for EterLib/StateManager.h (40250 EterLib/StateManager.cpp), generated by platform_stub.py. -// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation. -#include "EterLib/StdAfx.h" -#include "EterLib/StateManager.h" - -#include "../PlatformStub.h" - -CStateManager::CStateManager(LPDIRECT3DDEVICE8) -{ - MT_PLATFORM_STUB(); -} - -CStateManager::~CStateManager() -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetDefaultState() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::Restore() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::BeginScene() -> bool -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::EndScene() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveMaterial() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveMaterial(const D3DMATERIAL8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreMaterial() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetMaterial(const D3DMATERIAL8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetMaterial(D3DMATERIAL8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetLight(DWORD, const D3DLIGHT8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetLight(DWORD, D3DLIGHT8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveRenderState(D3DRENDERSTATETYPE, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreRenderState(D3DRENDERSTATETYPE) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetRenderState(D3DRENDERSTATETYPE, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetRenderState(D3DRENDERSTATETYPE, DWORD *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveTexture(DWORD, LPDIRECT3DBASETEXTURE8) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreTexture(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetTexture(DWORD, LPDIRECT3DBASETEXTURE8) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetTexture(DWORD, LPDIRECT3DBASETEXTURE8 *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetTextureStageState(DWORD, D3DTEXTURESTAGESTATETYPE, DWORD *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetBestFiltering(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveVertexShader(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreVertexShader() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetVertexShader(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetVertexShader(DWORD *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SavePixelShader(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestorePixelShader() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetPixelShader(DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetPixelShader(DWORD *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveTransform(D3DTRANSFORMSTATETYPE, const D3DMATRIX *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreTransform(D3DTRANSFORMSTATETYPE) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetTransform(D3DTRANSFORMSTATETYPE, const D3DMATRIX *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::GetTransform(D3DTRANSFORMSTATETYPE, D3DMATRIX *) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveVertexShaderConstant(DWORD, const void *, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreVertexShaderConstant(DWORD, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetVertexShaderConstant(DWORD, const void *, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SavePixelShaderConstant(DWORD, const void *, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestorePixelShaderConstant(DWORD, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetPixelShaderConstant(DWORD, const void *, DWORD) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveStreamSource(UINT, LPDIRECT3DVERTEXBUFFER8, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreStreamSource(UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetStreamSource(UINT, LPDIRECT3DVERTEXBUFFER8, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SaveIndices(LPDIRECT3DINDEXBUFFER8, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::RestoreIndices() -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::SetIndices(LPDIRECT3DINDEXBUFFER8, UINT) -> void -{ - MT_PLATFORM_STUB(); -} - -auto CStateManager::DrawPrimitive(D3DPRIMITIVETYPE, UINT, UINT) -> HRESULT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::DrawPrimitiveUP(D3DPRIMITIVETYPE, UINT, const void *, UINT) -> HRESULT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::DrawIndexedPrimitive(D3DPRIMITIVETYPE, UINT, UINT, UINT, UINT) -> HRESULT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE, UINT, UINT, UINT, const void *, D3DFORMAT, const void *, UINT) -> HRESULT -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::GetRenderState(D3DRENDERSTATETYPE) -> DWORD -{ - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); -} - -auto CStateManager::SetDevice(LPDIRECT3DDEVICE8) -> void -{ - MT_PLATFORM_STUB(); -} diff --git a/extension/src/platform/EterLib/UIRenderCommands.h b/extension/src/platform/EterLib/UIRenderCommands.h index ca7cb572..351da11e 100644 --- a/extension/src/platform/EterLib/UIRenderCommands.h +++ b/extension/src/platform/EterLib/UIRenderCommands.h @@ -44,7 +44,11 @@ struct UIMemoryTexture { }; bool UIRenderMemoryTexture(const std::string& name, UIMemoryTexture* out); struct IDirect3DTexture8; +struct IDirect3DBaseTexture8; +// Frees the platform texture behind a CGraphicTexture: a memory texture or a file texture's handle. void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture); +// The name (as UIRenderTextureName) of the texture a D3D handle belongs to; "" for null or unknown. +std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle); // A textured quad from 40250's TPDTVertex[4] (TL, TR, BL, BR) positions and texture coordinates. // PORT: D3D8 puts pixel centres on integers, which is why 40250 subtracts 0.5 from every vertex; the diff --git a/extension/src/platform/EterPythonLib/PythonGraphic.cpp b/extension/src/platform/EterPythonLib/PythonGraphic.cpp index 5345c614..d7297fb5 100644 --- a/extension/src/platform/EterPythonLib/PythonGraphic.cpp +++ b/extension/src/platform/EterPythonLib/PythonGraphic.cpp @@ -8,6 +8,7 @@ // RenderCoolTimeBox:CSlotWindow::OnRender 画技能冷却扇形用的,没有渲染设备时什么都不做。 #include "EterPythonLib/StdAfx.h" #include "EterPythonLib/PythonGraphic.h" +#include "EterLib/StateManager.h" #include "../PlatformStub.h" #include "../EterLib/UIRenderCommands.h" @@ -37,13 +38,81 @@ void CPythonGraphic::RenderDownButton(float, float, float, float) { MT_PLATFORM_ bool CPythonGraphic::SaveScreenShot(const char*) { MT_PLATFORM_STUB(); return false; } void CPythonGraphic::SetCursorPosition(int, int) { MT_PLATFORM_STUB(); } DWORD CPythonGraphic::GetAvailableMemory() { MT_PLATFORM_STUB(); return 0; } -void CPythonGraphic::SetGameRenderState() { MT_PLATFORM_STUB(); } -void CPythonGraphic::SetInterfaceRenderState() { MT_PLATFORM_STUB(); } -void CPythonGraphic::PushState() { MT_PLATFORM_STUB(); } -void CPythonGraphic::PopState() { MT_PLATFORM_STUB(); } void CPythonGraphic::SetGamma(float) { MT_PLATFORM_STUB(); } void CPythonGraphic::RenderCoolTimeBox(float fxCenter, float fyCenter, float fRadius, float fTime) { MT_PLATFORM_STUB(); } + +// 40250 PythonGraphic.cpp:17 +float CPythonGraphic::GetOrthoDepth() +{ + return m_fOrthoDepth; +} + +// 40250 PythonGraphic.cpp:22 +void CPythonGraphic::SetInterfaceRenderState() +{ + STATEMANAGER.SetTransform(D3DTS_PROJECTION, &ms_matIdentity); + STATEMANAGER.SetTransform(D3DTS_VIEW, &ms_matIdentity); + STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_NONE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_NONE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE); + + STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + CPythonGraphic::Instance().SetBlendOperation(); + CPythonGraphic::Instance().SetOrtho2D(ms_iWidth, ms_iHeight, GetOrthoDepth()); + + STATEMANAGER.SetRenderState(D3DRS_LIGHTING, FALSE); +} + +// 40250 PythonGraphic.cpp:42 +void CPythonGraphic::SetGameRenderState() +{ + STATEMANAGER.SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + STATEMANAGER.SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + STATEMANAGER.SetRenderState(D3DRS_LIGHTING, TRUE); +} + +// 40250 PythonGraphic.cpp:387 +void CPythonGraphic::PushState() +{ + TState curState; + + curState.matProj = ms_matProj; + curState.matView = ms_matView; + //STATEMANAGER.SaveTransform(D3DTS_WORLD, &m_SaveWorldMatrix); + + m_stateStack.push(curState); + //CCamera::Instance().PushParams(); +} + +// 40250 PythonGraphic.cpp:399 +void CPythonGraphic::PopState() +{ + if (m_stateStack.empty()) + { + assert(!"PythonGraphic::PopState StateStack is EMPTY"); + return; + } + + TState & rState = m_stateStack.top(); + + //STATEMANAGER.RestoreTransform(D3DTS_WORLD); + ms_matProj = rState.matProj; + ms_matView = rState.matView; + + UpdatePipeLineMatrix(); + + m_stateStack.pop(); + //CCamera::Instance().PopParams(); +} diff --git a/extension/src/platform/UserInterface/PythonApplication.cpp b/extension/src/platform/UserInterface/PythonApplication.cpp index 83a693e4..13c89f0e 100644 --- a/extension/src/platform/UserInterface/PythonApplication.cpp +++ b/extension/src/platform/UserInterface/PythonApplication.cpp @@ -10,6 +10,8 @@ #include "EterLib/NetDevice.h" #include "../PlatformStub.h" #include "../EterLib/UIRenderCommands.h" +#include "../EterLib/RenderCommands3D.h" +#include "EterLib/GrpDevice.h" #include "../ScriptLib/PythonBoot.h" // 2V0-d link surface; 2V0-f adds the application lifecycle (Create/Loop/Process/Exit) that @@ -53,17 +55,12 @@ void CPythonApplication::SetMinFog(float) { MT_PLATFORM_STUB(); } // this returns it. PORT: no member to hold it; the timer only advances in Process(), so reading it // here gives the same value. float CPythonApplication::GetGlobalTime() { return CTimer::Instance().GetCurrentSecond(); } -// Camera (2V3). -void CPythonApplication::SetEventCamera(const SCameraSetting&) { MT_PLATFORM_STUB(); } -void CPythonApplication::SetDefaultCamera() { MT_PLATFORM_STUB(); } -// In 40250 this stores m_v3CenterPosition for the game view (introselect.py sets it on the character list). -void CPythonApplication::SetCenterPosition(float, float, float) { MT_PLATFORM_STUB(); } void CPythonApplication::SetFrameSkip(bool) { MT_PLATFORM_STUB(); } // PORT: 40250 creates the Win32 window, the D3D8 device, cursors, sound, keyboard, the net device, -// fonts and the IME here. The Godot window and its canvas are the device on this platform and they -// already exist when the host starts the script, so the window size is the canvas size -// (PythonBoot::SetUISize) rather than the width/height passed from metin2.cfg. What remains of -// Create belongs to the subsystems that are not ported yet (sound 2V4, net 2V1, game render 2V3). +// fonts and the IME here. The Godot window and its canvas already exist when the host starts the +// script, so the window size is the canvas size (PythonBoot::SetUISize) rather than the width/height +// passed from metin2.cfg, and the graphic device is the recording device (RecordingDevice.h) at that +// size. Cursors, sound, keyboard, fonts and the IME are not created here yet. bool CPythonApplication::Create(PyObject*, const char*, int, int, int) { unsigned width = 0, height = 0; @@ -76,6 +73,38 @@ bool CPythonApplication::Create(PyObject*, const char*, int, int, int) return false; } + // In 40250 m_grpDevice is a member created here (PythonApplication.cpp:909). + static CGraphicDevice s_grpDevice; + int iRet = s_grpDevice.Create(NULL, width, height, true, 32, 0); + + switch (iRet) + { + case CGraphicDevice::CREATE_OK: + break; + + case CGraphicDevice::CREATE_REFRESHRATE: + break; + + case CGraphicDevice::CREATE_GET_DEVICE_CAPS: + PyErr_SetString(PyExc_RuntimeError, "GetDevCaps failed"); + TraceError("CreateDevice: GetDevCaps failed"); + return false; + + case CGraphicDevice::CREATE_GET_DEVICE_CAPS2: + PyErr_SetString(PyExc_RuntimeError, "GetDevCaps2 failed"); + TraceError("CreateDevice: GetDevCaps2 failed"); + return false; + + default: + // PORT: the recording device returns only the cases above; the rest is 40250's fallback. + if (iRet & CGraphicDevice::CREATE_OK) + break; + + TraceError("CreateDevice: Unknown Error!"); + PyErr_SetString(PyExc_RuntimeError, "UNKNOWN_ERROR"); + return false; + } + // In 40250 m_netDevice is a member created here (PythonApplication.cpp:1242). static CNetworkDevice s_netDevice; if (!s_netDevice.Create()) @@ -205,15 +234,43 @@ bool CPythonApplication::Process() // transfer is not ported yet (GuildMarkDownloader.cpp/GuildMarkUploader.cpp). CAccountConnector::Instance().Process(); + //!@# Alt+Tab 중 SetTransfor 에서 튕김 현상 해결을 위해 - [levites] + //if (m_isActivateWnd) + __UpdateCamera(); + CResourceManager::Instance().Update(); + OnCameraUpdate(); OnUIUpdate(); + // PORT: the render block without the lost-device restore, ClearDepthBuffer, Show and the render-time + // statistics (Godot clears and presents the frame). The frame's UI and 3D command lists restart here. + CCullingManager::Instance().Update(); UIRenderBeginFrame(); - OnUIRender(); + Render3DBeginFrame(); + CPythonGraphic& rkGraphic = CPythonGraphic::Instance(); + if (rkGraphic.Begin()) + { + rkGraphic.SetInterfaceRenderState(); + + OnUIRender(); + + rkGraphic.End(); + } return true; } +// 40250 PythonApplicationEvent.cpp:5 +void CPythonApplication::OnCameraUpdate() +{ + if ( CPythonBackground::Instance().IsMapReady() ) + { + CCamera* pkCameraMgr = CCameraManager::Instance().GetCurrentCamera(); + if (pkCameraMgr) + pkCameraMgr->Update(); + } +} + // 40250 PythonApplicationEvent.cpp:15-25 void CPythonApplication::OnUIUpdate() { @@ -233,30 +290,11 @@ bool CPythonApplication::GetLiarCursorOn() { MT_PLATFORM_STUB(); return false; } void CPythonApplication::SetCursorMode(int) { MT_PLATFORM_STUB(); } void CPythonApplication::SetMouseHandler(PyObject*) { MT_PLATFORM_STUB(); } void CPythonApplication::SetGlobalCenterPosition(LONG, LONG) { MT_PLATFORM_STUB(); } -void CPythonApplication::SetCamera(float, float, float, float) { MT_PLATFORM_STUB(); } -void CPythonApplication::GetCamera(float* distance, float* pitch, float* rotation, float* height) { - MT_PLATFORM_STUB(); - if (distance) *distance = 0; - if (pitch) *pitch = 0; - if (rotation) *rotation = 0; - if (height) *height = 0; -} -void CPythonApplication::RotateCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::PitchCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::ZoomCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::MovieRotateCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::MoviePitchCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::MovieZoomCamera(int) { MT_PLATFORM_STUB(); } -void CPythonApplication::MovieResetCamera() { MT_PLATFORM_STUB(); } -float CPythonApplication::GetRotation() { MT_PLATFORM_STUB(); return 0; } -float CPythonApplication::GetPitch() { MT_PLATFORM_STUB(); return 0; } void CPythonApplication::SetFPS(int) { MT_PLATFORM_STUB(); } time_t CPythonApplication::GetServerTime() { MT_PLATFORM_STUB(); return 0; } time_t CPythonApplication::GetServerTimeStamp() { MT_PLATFORM_STUB(); return 0; } void CPythonApplication::SetConnectData(const char*, int) { MT_PLATFORM_STUB(); } void CPythonApplication::GetConnectData(std::string& ip, int& port) { MT_PLATFORM_STUB(); ip.clear(); port = 0; } -void CPythonApplication::EnableSpecialCameraMode() { MT_PLATFORM_STUB(); } -void CPythonApplication::SetCameraSpeed(int) { MT_PLATFORM_STUB(); } void CPythonApplication::SaveCameraSetting(const char*) { MT_PLATFORM_STUB(); } bool CPythonApplication::LoadCameraSetting(const char*) { MT_PLATFORM_STUB(); return false; } void CPythonApplication::SetForceSightRange(int) { MT_PLATFORM_STUB(); } diff --git a/extension/src/platform/UserInterface/PythonApplicationCamera.cpp b/extension/src/platform/UserInterface/PythonApplicationCamera.cpp new file mode 100644 index 00000000..3933efe0 --- /dev/null +++ b/extension/src/platform/UserInterface/PythonApplicationCamera.cpp @@ -0,0 +1,408 @@ +// 40250 UserInterface/PythonApplicationCamera.cpp plus the camera members' other functions in +// PythonApplication.cpp (SetCenterPosition, EnableSpecialCameraMode, SetCameraSpeed). +// PORT: there is no CPythonApplication object (see PythonApplication.cpp), so the camera members live +// in s_app below with 40250's names and constructor values, and m_pyGraphic is CPythonGraphic::Instance(). +#include "UserInterface/StdAfx.h" +#include "UserInterface/PythonApplication.h" + +#include "EterBase/Timer.h" +#include "EterLib/Camera.h" + +// 40250 PythonApplication.cpp:28-30 +float c_fDefaultCameraRotateSpeed = 1.5f; +float c_fDefaultCameraPitchSpeed = 1.5f; +float c_fDefaultCameraZoomSpeed = 0.05f; + +namespace +{ +struct ApplicationCamera +{ + D3DXVECTOR3 m_v3CenterPosition{0.0f, 0.0f, 0.0f}; + + CPythonApplication::SCameraSetting m_DefaultCameraSetting; + CPythonApplication::SCameraSetting m_kEventCameraSetting; + + int m_iCameraMode = CPythonApplication::CAMERA_MODE_NORMAL; + float m_fBlendCameraStartTime = 0.0f; + float m_fBlendCameraBlendTime = 0.0f; + CPythonApplication::SCameraSetting m_kEndBlendCameraSetting; + + float m_fRotationSpeed = 0.0f; + float m_fPitchSpeed = 0.0f; + float m_fZoomSpeed = 0.0f; + float m_fCameraRotateSpeed = c_fDefaultCameraRotateSpeed; + float m_fCameraPitchSpeed = c_fDefaultCameraPitchSpeed; + float m_fCameraZoomSpeed = c_fDefaultCameraZoomSpeed; + + CPythonApplication::SCameraPos m_kCmrPos; + CPythonApplication::SCameraSpeed m_kCmrSpd; + + BOOL m_isSpecialCameraMode = FALSE; + + // The constructor's CCameraManager::Instance().AddCamera(EVENT_CAMERA_NUMBER), on first use. + ApplicationCamera() { CCameraManager::Instance().AddCamera(CPythonApplication::EVENT_CAMERA_NUMBER); } +}; + +ApplicationCamera& app() +{ + static ApplicationCamera s_app; + return s_app; +} +} + +float BlendValueByLinear(float fElapsedTime, float fDuration, float fBeginValue, float fEndValue) +{ + if (fElapsedTime >= fDuration) + return fEndValue; + + return (fEndValue - fBeginValue) * (fElapsedTime / fDuration) + fBeginValue; +} + +void CPythonApplication::__UpdateCamera() +{ + ApplicationCamera& s_app = app(); + + ////////////////////// + // Camera Setting + CCamera * pMainCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pMainCamera) + return; + + if (CAMERA_MODE_BLEND == s_app.m_iCameraMode) + { + float fcurTime = CTimer::Instance().GetCurrentSecond(); + float fElapsedTime = fcurTime - s_app.m_fBlendCameraStartTime; + + float fxCenter = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.v3CenterPosition.x, s_app.m_kEndBlendCameraSetting.v3CenterPosition.x); + float fyCenter = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.v3CenterPosition.y, s_app.m_kEndBlendCameraSetting.v3CenterPosition.y); + float fzCenter = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.v3CenterPosition.z, s_app.m_kEndBlendCameraSetting.v3CenterPosition.z); + + float fDistance = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.fZoom, s_app.m_kEndBlendCameraSetting.fZoom); + float fPitch = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.fPitch, s_app.m_kEndBlendCameraSetting.fPitch); + float fRotation = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.fRotation, s_app.m_kEndBlendCameraSetting.fRotation); + + float fUpDir = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.kCmrPos.m_fUpDir, s_app.m_kEndBlendCameraSetting.kCmrPos.m_fUpDir); + float fViewDir = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.kCmrPos.m_fViewDir, s_app.m_kEndBlendCameraSetting.kCmrPos.m_fViewDir); + float fCrossDir = BlendValueByLinear(fElapsedTime, s_app.m_fBlendCameraBlendTime, s_app.m_kEventCameraSetting.kCmrPos.m_fCrossDir, s_app.m_kEndBlendCameraSetting.kCmrPos.m_fCrossDir); + + // Temporary. Have to fix that this work in camera class. - [levites] + pMainCamera->Unlock(); + CPythonGraphic::Instance().SetPositionCamera(fxCenter, fyCenter, fzCenter, fDistance, fPitch, fRotation); + pMainCamera->MoveVertical(fUpDir); + pMainCamera->MoveFront(fViewDir); + pMainCamera->MoveAlongCross(fCrossDir); + pMainCamera->Lock(); + } + else if (CAMERA_MODE_STAND == s_app.m_iCameraMode) + { + float fDistance, fPitch, fRotation, fHeight; + GetCamera(&fDistance, &fPitch, &fRotation, &fHeight); + CPythonGraphic::Instance().SetPositionCamera(s_app.m_kEventCameraSetting.v3CenterPosition.x, + s_app.m_kEventCameraSetting.v3CenterPosition.y, + s_app.m_kEventCameraSetting.v3CenterPosition.z + pMainCamera->GetTargetHeight(), + fDistance, fPitch, fRotation); + } + else if (CAMERA_MODE_NORMAL == s_app.m_iCameraMode) + { + float fDistance, fPitch, fRotation, fHeight; + GetCamera(&fDistance, &fPitch, &fRotation, &fHeight); + CPythonGraphic::Instance().SetPositionCamera(s_app.m_v3CenterPosition.x, s_app.m_v3CenterPosition.y, s_app.m_v3CenterPosition.z + pMainCamera->GetTargetHeight(), fDistance, fPitch, fRotation); + } + + if (0.0f != s_app.m_fRotationSpeed) + pMainCamera->Roll(s_app.m_fRotationSpeed); + if (0.0f != s_app.m_fPitchSpeed) + pMainCamera->Pitch(s_app.m_fPitchSpeed); + if (0.0f != s_app.m_fZoomSpeed) + pMainCamera->Zoom(s_app.m_fZoomSpeed); + + if (0.0f !=s_app.m_kCmrSpd.m_fViewDir) + s_app.m_kCmrPos.m_fViewDir+=s_app.m_kCmrSpd.m_fViewDir; + if (0.0f !=s_app.m_kCmrSpd.m_fCrossDir) + s_app.m_kCmrPos.m_fCrossDir+=s_app.m_kCmrSpd.m_fCrossDir; + if (0.0f !=s_app.m_kCmrSpd.m_fUpDir) + s_app.m_kCmrPos.m_fUpDir+=s_app.m_kCmrSpd.m_fUpDir; + + if (0.0f != s_app.m_kCmrPos.m_fViewDir) + pMainCamera->MoveFront(s_app.m_kCmrPos.m_fViewDir); + if (0.0f != s_app.m_kCmrPos.m_fCrossDir) + pMainCamera->MoveAlongCross(s_app.m_kCmrPos.m_fCrossDir); + if (0.0f != s_app.m_kCmrPos.m_fUpDir) + pMainCamera->MoveVertical(s_app.m_kCmrPos.m_fUpDir); + + // PORT: SkipRenderBuffering while dragging and the listener update of m_SoundManager follow here in + // 40250; there is no render buffering and sound is not ported (2V4). +} + +void CPythonApplication::SetViewDirCameraSpeed(float fSpeed) +{ + if (IsLockCurrentCamera()) + return; + + app().m_kCmrSpd.m_fViewDir=fSpeed; +} + +void CPythonApplication::SetCrossDirCameraSpeed(float fSpeed) +{ + if (IsLockCurrentCamera()) + return; + + app().m_kCmrSpd.m_fCrossDir=fSpeed; +} + +void CPythonApplication::SetUpDirCameraSpeed(float fSpeed) +{ + if (IsLockCurrentCamera()) + return; + + app().m_kCmrSpd.m_fUpDir=fSpeed; +} + +void CPythonApplication::SetCamera(float Distance, float Pitch, float Rotation, float fDestinationHeight) +{ + if (IsLockCurrentCamera()) + return; + + CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCurrentCamera) + return; + + D3DXVECTOR3 v3Target = pCurrentCamera->GetTarget(); + CPythonGraphic::Instance().SetPositionCamera(v3Target.x, v3Target.y, v3Target.z, Distance, Pitch, Rotation); + + CCamera * pMainCamera = CCameraManager::Instance().GetCurrentCamera(); + if (pMainCamera) + pMainCamera->SetTargetHeight(fDestinationHeight); +} + +void CPythonApplication::GetCamera(float * Distance, float * Pitch, float * Rotation, float * DestinationHeight) +{ + CCamera * pCurrentCamera = CCameraManager::Instance().GetCurrentCamera(); + *Distance = pCurrentCamera->GetDistance(); + *Pitch = pCurrentCamera->GetPitch(); + *Rotation = pCurrentCamera->GetRoll(); + *DestinationHeight = pCurrentCamera->GetTarget().z; +} + +void CPythonApplication::RotateCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fDegree = app().m_fCameraRotateSpeed * float(iDirection); + app().m_fRotationSpeed = fDegree; +} + +void CPythonApplication::PitchCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fDegree = app().m_fCameraPitchSpeed * float(iDirection); + app().m_fPitchSpeed = fDegree; +} + +void CPythonApplication::ZoomCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fRatio = 1.0f + app().m_fCameraZoomSpeed * float(iDirection); + app().m_fZoomSpeed = fRatio; +} + +// PORT: in special camera mode 40250 checks GetKeyState(VK_SCROLL) & 1 (Scroll Lock on) to move the +// camera instead; the platform has no Scroll Lock state, so it is always off. +void CPythonApplication::MovieRotateCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fDegree = app().m_fCameraRotateSpeed * float(iDirection); + app().m_fRotationSpeed = fDegree; +} + +void CPythonApplication::MoviePitchCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fDegree = app().m_fCameraPitchSpeed * float(iDirection); + app().m_fPitchSpeed = fDegree; +} + +void CPythonApplication::MovieZoomCamera(int iDirection) +{ + if (IsLockCurrentCamera()) + return; + + float fRatio = 1.0f + app().m_fCameraZoomSpeed * float(iDirection); + app().m_fZoomSpeed = fRatio; +} + +void CPythonApplication::MovieResetCamera() +{ + if (IsLockCurrentCamera()) + return; + + ApplicationCamera& s_app = app(); + if (s_app.m_isSpecialCameraMode) + { + SetCrossDirCameraSpeed(0.0f); + SetViewDirCameraSpeed(0.0f); + SetUpDirCameraSpeed(0.0f); + + s_app.m_kCmrPos.m_fViewDir = 0; + s_app.m_kCmrPos.m_fCrossDir = 0; + s_app.m_kCmrPos.m_fUpDir = 0; + } +} + +float CPythonApplication::GetRotation() +{ + return CCameraManager::Instance().GetCurrentCamera()->GetRoll(); +} + +float CPythonApplication::GetPitch() +{ + return CCameraManager::Instance().GetCurrentCamera()->GetPitch(); +} + +bool CPythonApplication::IsLockCurrentCamera() +{ + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return false; + + return pCamera->IsLock(); +} + +void CPythonApplication::SetEventCamera(const SCameraSetting & c_rCameraSetting) +{ + ApplicationCamera& s_app = app(); + if (CCameraManager::DEFAULT_PERSPECTIVE_CAMERA == CCameraManager::Instance().GetCurrentCameraNum()) + { + GetCameraSetting(&s_app.m_DefaultCameraSetting); + } + + ///// + + CCameraManager::Instance().SetCurrentCamera(EVENT_CAMERA_NUMBER); + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + SetCameraSetting(c_rCameraSetting); + s_app.m_kEventCameraSetting = c_rCameraSetting; + s_app.m_iCameraMode = CAMERA_MODE_STAND; +} + +void CPythonApplication::BlendEventCamera(const SCameraSetting & c_rCameraSetting, float fBlendTime) +{ + ApplicationCamera& s_app = app(); + s_app.m_iCameraMode = CAMERA_MODE_BLEND; + s_app.m_fBlendCameraStartTime = CTimer::Instance().GetCurrentSecond(); + s_app.m_fBlendCameraBlendTime = fBlendTime; + s_app.m_kEndBlendCameraSetting = c_rCameraSetting; + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (pCamera) + pCamera->Lock(); +} + +void CPythonApplication::SetDefaultCamera() +{ + ApplicationCamera& s_app = app(); + s_app.m_iCameraMode = CAMERA_MODE_NORMAL; + s_app.m_fBlendCameraStartTime = 0.0f; + s_app.m_fBlendCameraBlendTime = 0.0f; + + ///// + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (pCamera) + pCamera->Unlock(); + + if (CCameraManager::DEFAULT_PERSPECTIVE_CAMERA != CCameraManager::Instance().GetCurrentCameraNum()) + { + CCameraManager::Instance().SetCurrentCamera(CCameraManager::DEFAULT_PERSPECTIVE_CAMERA); + SetCameraSetting(s_app.m_DefaultCameraSetting); + } +} + +void CPythonApplication::SetCameraSetting(const SCameraSetting & c_rCameraSetting) +{ + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + CPythonGraphic::Instance().SetPositionCamera( c_rCameraSetting.v3CenterPosition.x, + c_rCameraSetting.v3CenterPosition.y, + c_rCameraSetting.v3CenterPosition.z, + c_rCameraSetting.fZoom, + c_rCameraSetting.fPitch, + c_rCameraSetting.fRotation); + + if (0.0f != c_rCameraSetting.kCmrPos.m_fViewDir) + pCamera->MoveFront(c_rCameraSetting.kCmrPos.m_fViewDir); + if (0.0f != c_rCameraSetting.kCmrPos.m_fCrossDir) + pCamera->MoveAlongCross(c_rCameraSetting.kCmrPos.m_fCrossDir); + if (0.0f != c_rCameraSetting.kCmrPos.m_fUpDir) + pCamera->MoveVertical(c_rCameraSetting.kCmrPos.m_fUpDir); + + ApplicationCamera& s_app = app(); + s_app.m_kCmrPos.m_fUpDir = 0.0f; + s_app.m_kCmrPos.m_fViewDir = 0.0f; + s_app.m_kCmrPos.m_fCrossDir = 0.0f; + s_app.m_kCmrSpd.m_fUpDir = 0.0f; + s_app.m_kCmrSpd.m_fViewDir = 0.0f; + s_app.m_kCmrSpd.m_fCrossDir = 0.0f; + s_app.m_fZoomSpeed = 0.0f; + s_app.m_fPitchSpeed = 0.0f; + s_app.m_fRotationSpeed = 0.0f; +} + +void CPythonApplication::GetCameraSetting(SCameraSetting * pCameraSetting) +{ + ApplicationCamera& s_app = app(); + pCameraSetting->v3CenterPosition = s_app.m_v3CenterPosition; + pCameraSetting->kCmrPos = s_app.m_kCmrPos; + + if (CCameraManager::Instance().GetCurrentCamera()) + pCameraSetting->v3CenterPosition.z += CCameraManager::Instance().GetCurrentCamera()->GetTargetHeight(); + + float fHeight; + GetCamera(&pCameraSetting->fZoom, &pCameraSetting->fPitch, &pCameraSetting->fRotation, &fHeight); +} + +// 40250 PythonApplication.cpp:1294 +void CPythonApplication::SetCenterPosition(float fx, float fy, float fz) +{ + ApplicationCamera& s_app = app(); + s_app.m_v3CenterPosition.x = +fx; + s_app.m_v3CenterPosition.y = -fy; + s_app.m_v3CenterPosition.z = +fz; +} + +// 40250 PythonApplication.cpp:1301 +void CPythonApplication::GetCenterPosition(TPixelPosition * pPixelPosition) +{ + ApplicationCamera& s_app = app(); + pPixelPosition->x = +s_app.m_v3CenterPosition.x; + pPixelPosition->y = -s_app.m_v3CenterPosition.y; + pPixelPosition->z = +s_app.m_v3CenterPosition.z; +} + +// 40250 PythonApplication.cpp:1365 +void CPythonApplication::EnableSpecialCameraMode() +{ + app().m_isSpecialCameraMode = TRUE; +} + +void CPythonApplication::SetCameraSpeed(int iPercentage) +{ + ApplicationCamera& s_app = app(); + s_app.m_fCameraRotateSpeed = c_fDefaultCameraRotateSpeed * float(iPercentage) / 100.0f; + s_app.m_fCameraPitchSpeed = c_fDefaultCameraPitchSpeed * float(iPercentage) / 100.0f; + s_app.m_fCameraZoomSpeed = c_fDefaultCameraZoomSpeed * float(iPercentage) / 100.0f; +} diff --git a/extension/src/platform/pending/GameLib/MapManager.cpp b/extension/src/platform/pending/GameLib/MapManager.cpp index 2975e43c..4a8e9307 100644 --- a/extension/src/platform/pending/GameLib/MapManager.cpp +++ b/extension/src/platform/pending/GameLib/MapManager.cpp @@ -78,3 +78,12 @@ auto CMapManager::EndEnvironment() -> void { MT_PLATFORM_STUB(); } + +// 40250 MapManager.cpp:144 (CPythonApplication::OnCameraUpdate); m_pkMap stays null until LoadMap is ported. +bool CMapManager::IsMapReady() +{ + if (!m_pkMap) + return false; + + return m_pkMap->IsReady(); +} diff --git a/extension/src/platform/pending/UserInterface/PythonPlayer.cpp b/extension/src/platform/pending/UserInterface/PythonPlayer.cpp index 35e5693b..1c9ce605 100644 --- a/extension/src/platform/pending/UserInterface/PythonPlayer.cpp +++ b/extension/src/platform/pending/UserInterface/PythonPlayer.cpp @@ -3,6 +3,9 @@ // that ports the unit into port/ (docs/PORT-PLAN.md 2V1). #include "UserInterface/StdAfx.h" #include "UserInterface/PythonPlayer.h" +#include "UserInterface/PythonApplication.h" +#include "UserInterface/PythonCharacterManager.h" +#include "UserInterface/InstanceBase.h" #include "../../PlatformStub.h" @@ -20,6 +23,9 @@ auto CPythonPlayer::SPlayerStatus::GetPoint(UINT) -> long CPythonPlayer::CPythonPlayer() { MT_PLATFORM_STUB(); + // PORT: the one member the stand-in's ported functions read; 40250's constructor reaches it + // through Clear() (PythonPlayer.cpp:1624). + m_dwMainCharacterIndex = 0; } CPythonPlayer::~CPythonPlayer() @@ -63,9 +69,21 @@ auto CPythonPlayer::SetAttackKeyState(bool) -> void MT_PLATFORM_STUB(); } -auto CPythonPlayer::NEW_GetMainActorPosition(TPixelPosition *) -> void +// 40250 PythonPlayer.cpp:87, verbatim: UpdateGame centres the camera on the main actor. +void CPythonPlayer::NEW_GetMainActorPosition(TPixelPosition* pkPPosActor) { - MT_PLATFORM_STUB(); + TPixelPosition kPPosMainActor; + + IAbstractPlayer& rkPlayer=IAbstractPlayer::GetSingleton(); + CInstanceBase * pInstance = rkPlayer.NEW_GetMainActorPtr(); + if (pInstance) + { + pInstance->NEW_GetPixelPosition(pkPPosActor); + } + else + { + CPythonApplication::Instance().GetCenterPosition(pkPPosActor); + } } auto CPythonPlayer::RegisterEffect(DWORD, const char *, bool) -> bool @@ -194,16 +212,17 @@ auto CPythonPlayer::AlarmHaveToGo() -> void MT_PLATFORM_STUB(); } -auto CPythonPlayer::NEW_FindActorPtr(DWORD) -> CInstanceBase * +// 40250 PythonPlayer.cpp:127 +CInstanceBase* CPythonPlayer::NEW_FindActorPtr(DWORD dwVID) { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + CPythonCharacterManager& rkChrMgr = CPythonCharacterManager::Instance(); + return rkChrMgr.GetInstancePtr(dwVID); } -auto CPythonPlayer::NEW_GetMainActorPtr() -> CInstanceBase * +// 40250 PythonPlayer.cpp +CInstanceBase* CPythonPlayer::NEW_GetMainActorPtr() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return NEW_FindActorPtr(m_dwMainCharacterIndex); } auto CPythonPlayer::Clear() -> void @@ -237,15 +256,18 @@ auto CPythonPlayer::SetPlayTime(DWORD) -> void MT_PLATFORM_STUB(); } -auto CPythonPlayer::SetMainCharacterIndex(int) -> void +// 40250 PythonPlayer.cpp:276 +// PORT: the main instance's SetEventHandler(CPythonPlayerEventHandler) is left out; the player event +// handler (PythonPlayerEventHandler.cpp) is not ported. +void CPythonPlayer::SetMainCharacterIndex(int iIndex) { - MT_PLATFORM_STUB(); + m_dwMainCharacterIndex = iIndex; } -auto CPythonPlayer::GetMainCharacterIndex() -> DWORD +// 40250 PythonPlayer.cpp:288 +DWORD CPythonPlayer::GetMainCharacterIndex() { - MT_PLATFORM_STUB(); - return mt_platform_stub_return(); + return m_dwMainCharacterIndex; } auto CPythonPlayer::IsMainCharacterIndex(DWORD) -> bool diff --git a/extension/src/port/EterLib/GrpBase.cpp b/extension/src/port/EterLib/GrpBase.cpp new file mode 100644 index 00000000..f8bba470 --- /dev/null +++ b/extension/src/port/EterLib/GrpBase.cpp @@ -0,0 +1,512 @@ +#include "StdAfx.h" +#include "../EterBase/Utils.h" +#include "../EterBase/Timer.h" +#include "GrpBase.h" +#include "Camera.h" +#include "StateManager.h" + +void PixelPositionToD3DXVECTOR3(const D3DXVECTOR3& c_rkPPosSrc, D3DXVECTOR3* pv3Dst) +{ + pv3Dst->x=+c_rkPPosSrc.x; + pv3Dst->y=-c_rkPPosSrc.y; + pv3Dst->z=+c_rkPPosSrc.z; +} + +void D3DXVECTOR3ToPixelPosition(const D3DXVECTOR3& c_rv3Src, D3DXVECTOR3* pv3Dst) +{ + pv3Dst->x=+c_rv3Src.x; + pv3Dst->y=-c_rv3Src.y; + pv3Dst->z=+c_rv3Src.z; +} + +UINT CGraphicBase::ms_iD3DAdapterInfo=0; +UINT CGraphicBase::ms_iD3DDevInfo=0; +UINT CGraphicBase::ms_iD3DModeInfo=0; +D3D_CDisplayModeAutoDetector CGraphicBase::ms_kD3DDetector; + +HWND CGraphicBase::ms_hWnd; +HDC CGraphicBase::ms_hDC; + +LPDIRECT3D8 CGraphicBase::ms_lpd3d = NULL; +LPDIRECT3DDEVICE8 CGraphicBase::ms_lpd3dDevice = NULL; +ID3DXMatrixStack * CGraphicBase::ms_lpd3dMatStack = NULL; +D3DPRESENT_PARAMETERS CGraphicBase::ms_d3dPresentParameter; +D3DVIEWPORT8 CGraphicBase::ms_Viewport; + +HRESULT CGraphicBase::ms_hLastResult = NULL; + +int CGraphicBase::ms_iWidth; +int CGraphicBase::ms_iHeight; + +DWORD CGraphicBase::ms_faceCount = 0; + +D3DCAPS8 CGraphicBase::ms_d3dCaps; + +DWORD CGraphicBase::ms_dwD3DBehavior = 0; + +DWORD CGraphicBase::ms_ptVS = 0; +DWORD CGraphicBase::ms_pntVS = 0; +DWORD CGraphicBase::ms_pnt2VS = 0; + +D3DXMATRIX CGraphicBase::ms_matIdentity; + +D3DXMATRIX CGraphicBase::ms_matView; +D3DXMATRIX CGraphicBase::ms_matProj; +D3DXMATRIX CGraphicBase::ms_matInverseView; +D3DXMATRIX CGraphicBase::ms_matInverseViewYAxis; + +D3DXMATRIX CGraphicBase::ms_matWorld; +D3DXMATRIX CGraphicBase::ms_matWorldView; + +D3DXMATRIX CGraphicBase::ms_matScreen0; +D3DXMATRIX CGraphicBase::ms_matScreen1; +D3DXMATRIX CGraphicBase::ms_matScreen2; + +D3DXVECTOR3 CGraphicBase::ms_vtPickRayOrig; +D3DXVECTOR3 CGraphicBase::ms_vtPickRayDir; + +float CGraphicBase::ms_fFieldOfView; +float CGraphicBase::ms_fNearY; +float CGraphicBase::ms_fFarY; +float CGraphicBase::ms_fAspect; + +DWORD CGraphicBase::ms_dwWavingEndTime; +int CGraphicBase::ms_iWavingPower; +DWORD CGraphicBase::ms_dwFlashingEndTime; +D3DXCOLOR CGraphicBase::ms_FlashingColor; + +// Terrain picking용 Ray... CCamera 이용하는 버전.. 기존의 Ray와 통합 필요... +CRay CGraphicBase::ms_Ray; +bool CGraphicBase::ms_bSupportDXT = true; +bool CGraphicBase::ms_isLowTextureMemory = false; +bool CGraphicBase::ms_isHighTextureMemory = false; + +// 2004.11.18.myevan.DynamicVertexBuffer로 교체 +/* +std::vector CGraphicBase::ms_lineIdxVector; +std::vector CGraphicBase::ms_lineTriIdxVector; +std::vector CGraphicBase::ms_lineRectIdxVector; +std::vector CGraphicBase::ms_lineCubeIdxVector; + +std::vector CGraphicBase::ms_fillTriIdxVector; +std::vector CGraphicBase::ms_fillRectIdxVector; +std::vector CGraphicBase::ms_fillCubeIdxVector; +*/ + +LPD3DXMESH CGraphicBase::ms_lpSphereMesh = NULL; +LPD3DXMESH CGraphicBase::ms_lpCylinderMesh = NULL; + +LPDIRECT3DVERTEXBUFFER8 CGraphicBase::ms_alpd3dPDTVB[PDT_VERTEXBUFFER_NUM]; + +LPDIRECT3DINDEXBUFFER8 CGraphicBase::ms_alpd3dDefIB[DEFAULT_IB_NUM]; + +bool CGraphicBase::IsLowTextureMemory() +{ + return ms_isLowTextureMemory; +} + +bool CGraphicBase::IsHighTextureMemory() +{ + return ms_isHighTextureMemory; +} + +bool CGraphicBase::IsFastTNL() +{ + if (ms_dwD3DBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING || + ms_dwD3DBehavior & D3DCREATE_MIXED_VERTEXPROCESSING) + { + if (ms_d3dCaps.VertexShaderVersion>D3DVS_VERSION(1,0)) + return true; + } + return false; +} + +bool CGraphicBase::IsTLVertexClipping() +{ + if (ms_d3dCaps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS) + return true; + + return false; +} + +void CGraphicBase::GetBackBufferSize(UINT* puWidth, UINT* puHeight) +{ + *puWidth=ms_d3dPresentParameter.BackBufferWidth; + *puHeight=ms_d3dPresentParameter.BackBufferHeight; +} + +void CGraphicBase::SetDefaultIndexBuffer(UINT eDefIB) +{ + if (eDefIB>=DEFAULT_IB_NUM) + return; + + STATEMANAGER.SetIndices(ms_alpd3dDefIB[eDefIB], 0); +} + +bool CGraphicBase::SetPDTStream(SPDTVertex* pVertices, UINT uVtxCount) +{ + return SetPDTStream((SPDTVertexRaw*)pVertices, uVtxCount); +} + +bool CGraphicBase::SetPDTStream(SPDTVertexRaw* pSrcVertices, UINT uVtxCount) +{ + if (!uVtxCount) + return false; + + static DWORD s_dwVBPos=0; + + if (s_dwVBPos>=PDT_VERTEXBUFFER_NUM) + s_dwVBPos=0; + + IDirect3DVertexBuffer8* plpd3dFillRectVB=ms_alpd3dPDTVB[s_dwVBPos]; + ++s_dwVBPos; + + assert(PDT_VERTEX_NUM>=uVtxCount); + if (uVtxCount >= PDT_VERTEX_NUM) + return false; + + TPDTVertex* pDstVertices; + if (FAILED( + plpd3dFillRectVB->Lock(0, sizeof(TPDTVertex)*uVtxCount, (BYTE**)&pDstVertices, D3DLOCK_DISCARD) + )) + { + STATEMANAGER.SetStreamSource(0, NULL, 0); + return false; + } + + + memcpy(pDstVertices, pSrcVertices, sizeof(TPDTVertex)*uVtxCount); + + plpd3dFillRectVB->Unlock(); + + STATEMANAGER.SetStreamSource(0, plpd3dFillRectVB, sizeof(TPDTVertex)); + + return true; +} + +DWORD CGraphicBase::GetAvailableTextureMemory() +{ + assert(ms_lpd3dDevice!=NULL && "CGraphicBase::GetAvailableTextureMemory - D3DDevice is EMPTY"); + + static DWORD s_dwNextUpdateTime=0; + static DWORD s_dwTexMemSize=0;//ms_lpd3dDevice->GetAvailableTextureMem(); + + DWORD dwCurTime=ELTimer_GetMSec(); + if (s_dwNextUpdateTimeGetAvailableTextureMem(); + } + + return s_dwTexMemSize; +} + +const D3DXMATRIX& CGraphicBase::GetViewMatrix() +{ + return ms_matView; +} + +const D3DXMATRIX & CGraphicBase::GetIdentityMatrix() +{ + return ms_matIdentity; +} + +void CGraphicBase::SetEyeCamera(float xEye, float yEye, float zEye, + float xCenter, float yCenter, float zCenter, + float xUp, float yUp, float zUp) +{ + D3DXVECTOR3 vectorEye(xEye, yEye, zEye); + D3DXVECTOR3 vectorCenter(xCenter, yCenter, zCenter); + D3DXVECTOR3 vectorUp(xUp, yUp, zUp); + +// CCameraManager::Instance().SetCurrentCamera(CCameraManager::DEFAULT_PERSPECTIVE_CAMERA); + CCameraManager::Instance().GetCurrentCamera()->SetViewParams(vectorEye, vectorCenter, vectorUp); + UpdateViewMatrix(); +} + +void CGraphicBase::SetSimpleCamera(float x, float y, float z, float pitch, float roll) +{ + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + D3DXVECTOR3 vectorEye(x, y, z); + + pCamera->SetViewParams(D3DXVECTOR3(0.0f, y, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 1.0f)); + pCamera->RotateEyeAroundTarget(pitch, roll); + pCamera->Move(vectorEye); + + UpdateViewMatrix(); + + // This is levites's virtual(?) code which you should not trust. + ms_lpd3dDevice->GetTransform(D3DTS_WORLD, &ms_matWorld); + D3DXMatrixMultiply(&ms_matWorldView, &ms_matWorld, &ms_matView); +} + +void CGraphicBase::SetAroundCamera(float distance, float pitch, float roll, float lookAtZ) +{ + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + pCamera->SetViewParams(D3DXVECTOR3(0.0f, -distance, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 1.0f)); + pCamera->RotateEyeAroundTarget(pitch, roll); + D3DXVECTOR3 v3Target = pCamera->GetTarget(); + v3Target.z = lookAtZ; + pCamera->SetTarget(v3Target); +// pCamera->Move(v3Target); + + UpdateViewMatrix(); + + // This is levites's virtual(?) code which you should not trust. + ms_lpd3dDevice->GetTransform(D3DTS_WORLD, &ms_matWorld); + D3DXMatrixMultiply(&ms_matWorldView, &ms_matWorld, &ms_matView); +} + +void CGraphicBase::SetPositionCamera(float fx, float fy, float fz, float distance, float pitch, float roll) +{ + // I wanna downward this code to the game control level. - [levites] + if (ms_dwWavingEndTime > CTimer::Instance().GetCurrentMillisecond()) + { + if (ms_iWavingPower>0) + { + fx += float(rand() % ms_iWavingPower) / 10.0f; + fy += float(rand() % ms_iWavingPower) / 10.0f; + fz += float(rand() % ms_iWavingPower) / 10.0f; + } + } + + CCamera * pCamera = CCameraManager::Instance().GetCurrentCamera(); + if (!pCamera) + return; + + pCamera->SetViewParams(D3DXVECTOR3(0.0f, -distance, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 0.0f), D3DXVECTOR3(0.0f, 0.0f, 1.0f)); + pitch = fMIN(80.0f, fMAX(-80.0f, pitch) ); +// Tracef("SetPosition Camera : %f, %f\n", pitch, roll); + pCamera->RotateEyeAroundTarget(pitch, roll); + pCamera->Move(D3DXVECTOR3(fx, fy, fz)); + + UpdateViewMatrix(); + + // This is levites's virtual(?) code which you should not trust. + STATEMANAGER.GetTransform(D3DTS_WORLD, &ms_matWorld); + D3DXMatrixMultiply(&ms_matWorldView, &ms_matWorld, &ms_matView); +} + +void CGraphicBase::SetOrtho2D(float hres, float vres, float zres) +{ + //CCameraManager::Instance().SetCurrentCamera(CCameraManager::DEFAULT_ORTHO_CAMERA); + D3DXMatrixOrthoOffCenterRH(&ms_matProj, 0, hres, vres, 0, 0, zres); + //UpdatePipeLineMatrix(); + UpdateProjMatrix(); +} + +void CGraphicBase::SetOrtho3D(float hres, float vres, float zmin, float zmax) +{ + //CCameraManager::Instance().SetCurrentCamera(CCameraManager::DEFAULT_PERSPECTIVE_CAMERA); + D3DXMatrixOrthoRH(&ms_matProj, hres, vres, zmin, zmax); + //UpdatePipeLineMatrix(); + UpdateProjMatrix(); +} + +void CGraphicBase::SetPerspective(float fov, float aspect, float nearz, float farz) +{ + ms_fFieldOfView = fov; + + + //if (ms_d3dPresentParameter.BackBufferWidth>0 && ms_d3dPresentParameter.BackBufferHeight>0) + // ms_fAspect = float(ms_d3dPresentParameter.BackBufferWidth)/float(ms_d3dPresentParameter.BackBufferHeight); + //else + ms_fAspect = aspect; + + ms_fNearY = nearz; + ms_fFarY = farz; + + //CCameraManager::Instance().SetCurrentCamera(CCameraManager::DEFAULT_PERSPECTIVE_CAMERA); + D3DXMatrixPerspectiveFovRH(&ms_matProj, D3DXToRadian(fov), ms_fAspect, nearz, farz); + //UpdatePipeLineMatrix(); + UpdateProjMatrix(); +} + +void CGraphicBase::UpdateProjMatrix() +{ + STATEMANAGER.SetTransform(D3DTS_PROJECTION, &ms_matProj); +} + +void CGraphicBase::UpdateViewMatrix() +{ + CCamera* pkCamera=CCameraManager::Instance().GetCurrentCamera(); + if (!pkCamera) + return; + + ms_matView = pkCamera->GetViewMatrix(); + STATEMANAGER.SetTransform(D3DTS_VIEW, &ms_matView); + + D3DXMatrixInverse(&ms_matInverseView, NULL, &ms_matView); + ms_matInverseViewYAxis._11 = ms_matInverseView._11; + ms_matInverseViewYAxis._12 = ms_matInverseView._12; + ms_matInverseViewYAxis._21 = ms_matInverseView._21; + ms_matInverseViewYAxis._22 = ms_matInverseView._22; +} + +void CGraphicBase::UpdatePipeLineMatrix() +{ + UpdateProjMatrix(); + UpdateViewMatrix(); +} + +void CGraphicBase::SetViewport(DWORD dwX, DWORD dwY, DWORD dwWidth, DWORD dwHeight, float fMinZ, float fMaxZ) +{ + ms_Viewport.X = dwX; + ms_Viewport.Y = dwY; + ms_Viewport.Width = dwWidth; + ms_Viewport.Height = dwHeight; + ms_Viewport.MinZ = fMinZ; + ms_Viewport.MaxZ = fMaxZ; +} + +void CGraphicBase::GetTargetPosition(float * px, float * py, float * pz) +{ + *px = CCameraManager::Instance().GetCurrentCamera()->GetTarget().x; + *py = CCameraManager::Instance().GetCurrentCamera()->GetTarget().y; + *pz = CCameraManager::Instance().GetCurrentCamera()->GetTarget().z; +} + +void CGraphicBase::GetCameraPosition(float * px, float * py, float * pz) +{ + *px = CCameraManager::Instance().GetCurrentCamera()->GetEye().x; + *py = CCameraManager::Instance().GetCurrentCamera()->GetEye().y; + *pz = CCameraManager::Instance().GetCurrentCamera()->GetEye().z; +} + +void CGraphicBase::GetMatrix(D3DXMATRIX* pRetMatrix) const +{ + assert(ms_lpd3dMatStack != NULL); + *pRetMatrix = *ms_lpd3dMatStack->GetTop(); +} + +const D3DXMATRIX* CGraphicBase::GetMatrixPointer() const +{ + assert(ms_lpd3dMatStack!=NULL); + return ms_lpd3dMatStack->GetTop(); +} + +void CGraphicBase::GetSphereMatrix(D3DXMATRIX * pMatrix, float fValue) +{ + D3DXMatrixIdentity(pMatrix); + pMatrix->_11 = fValue * ms_matWorldView._11; + pMatrix->_21 = fValue * ms_matWorldView._21; + pMatrix->_31 = fValue * ms_matWorldView._31; + pMatrix->_41 = fValue; + pMatrix->_12 = -fValue * ms_matWorldView._12; + pMatrix->_22 = -fValue * ms_matWorldView._22; + pMatrix->_32 = -fValue * ms_matWorldView._32; + pMatrix->_42 = -fValue; +} + +float CGraphicBase::GetFOV() +{ + return ms_fFieldOfView; +} + +void CGraphicBase::PushMatrix() +{ + ms_lpd3dMatStack->Push(); +} + +void CGraphicBase::Scale(float x, float y, float z) +{ + ms_lpd3dMatStack->Scale(x, y, z); +} + +void CGraphicBase::Rotate(float degree, float x, float y, float z) +{ + D3DXVECTOR3 vec(x, y, z); + ms_lpd3dMatStack->RotateAxis(&vec, D3DXToRadian(degree)); +} + +void CGraphicBase::RotateLocal(float degree, float x, float y, float z) +{ + D3DXVECTOR3 vec(x, y, z); + ms_lpd3dMatStack->RotateAxisLocal(&vec, D3DXToRadian(degree)); +} + +void CGraphicBase::MultMatrix( const D3DXMATRIX* pMat) +{ + ms_lpd3dMatStack->MultMatrix(pMat); +} + +void CGraphicBase::MultMatrixLocal( const D3DXMATRIX* pMat) +{ + ms_lpd3dMatStack->MultMatrixLocal(pMat); +} + +void CGraphicBase::RotateYawPitchRollLocal(float fYaw, float fPitch, float fRoll) +{ + ms_lpd3dMatStack->RotateYawPitchRollLocal(D3DXToRadian(fYaw), D3DXToRadian(fPitch), D3DXToRadian(fRoll)); +} + +void CGraphicBase::Translate(float x, float y, float z) +{ + ms_lpd3dMatStack->Translate(x, y, z); +} + +void CGraphicBase::LoadMatrix(const D3DXMATRIX& c_rSrcMatrix) +{ + ms_lpd3dMatStack->LoadMatrix(&c_rSrcMatrix); +} + +void CGraphicBase::PopMatrix() +{ + ms_lpd3dMatStack->Pop(); +} + +DWORD CGraphicBase::GetColor(float r, float g, float b, float a) +{ + BYTE argb[4] = + { + (BYTE) (255.0f * b), + (BYTE) (255.0f * g), + (BYTE) (255.0f * r), + (BYTE) (255.0f * a) + }; + + return *((DWORD *) argb); +} + +void CGraphicBase::InitScreenEffect() +{ + ms_dwWavingEndTime = 0; + ms_dwFlashingEndTime = 0; + ms_iWavingPower = 0; + ms_FlashingColor = D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f); +} + +void CGraphicBase::SetScreenEffectWaving(float fDuringTime, int iPower) +{ + ms_dwWavingEndTime = CTimer::Instance().GetCurrentMillisecond() + long(fDuringTime * 1000.0f); + ms_iWavingPower = iPower; +} + +void CGraphicBase::SetScreenEffectFlashing(float fDuringTime, const D3DXCOLOR & c_rColor) +{ + ms_dwFlashingEndTime = CTimer::Instance().GetCurrentMillisecond() + long(fDuringTime * 1000.0f); + ms_FlashingColor = c_rColor; +} + +DWORD CGraphicBase::GetFaceCount() +{ + return ms_faceCount; +} + +void CGraphicBase::ResetFaceCount() +{ + ms_faceCount = 0; +} + +HRESULT CGraphicBase::GetLastResult() +{ + return ms_hLastResult; +} + +CGraphicBase::CGraphicBase() +{ +} + +CGraphicBase::~CGraphicBase() +{ +} diff --git a/extension/src/port/EterLib/StateManager.cpp b/extension/src/port/EterLib/StateManager.cpp new file mode 100644 index 00000000..5f3724a0 --- /dev/null +++ b/extension/src/port/EterLib/StateManager.cpp @@ -0,0 +1,769 @@ +#include "StdAfx.h" +#include "StateManager.h" + +//#define StateManager_Assert(a) if (!(a)) puts("assert"#a) +#define StateManager_Assert(a) assert(a) + +struct SLightData +{ + enum + { + LIGHT_NUM = 8, + }; + D3DLIGHT8 m_akD3DLight[LIGHT_NUM]; +} m_kLightData; + + + +void CStateManager::SetLight(DWORD index, CONST D3DLIGHT8* pLight) +{ + assert(indexSetLight(index, pLight); +} + +void CStateManager::GetLight(DWORD index, D3DLIGHT8* pLight) +{ + assert(index<8); + *pLight=m_kLightData.m_akD3DLight[index]; +} + +bool CStateManager::BeginScene() +{ + m_bScene=true; + + D3DXMATRIX m4Proj; + D3DXMATRIX m4View; + D3DXMATRIX m4World; + GetTransform(D3DTS_WORLD, &m4World); + GetTransform(D3DTS_PROJECTION, &m4Proj); + GetTransform(D3DTS_VIEW, &m4View); + SetTransform(D3DTS_WORLD, &m4World); + SetTransform(D3DTS_PROJECTION, &m4Proj); + SetTransform(D3DTS_VIEW, &m4View); + + if (FAILED(m_lpD3DDev->BeginScene())) + return false; + return true; +} + +void CStateManager::EndScene() +{ + m_lpD3DDev->EndScene(); + m_bScene=false; +} + +CStateManager::CStateManager(LPDIRECT3DDEVICE8 lpDevice) : m_lpD3DDev(NULL) +{ + m_bScene = false; + m_dwBestMinFilter = D3DTEXF_LINEAR; + m_dwBestMagFilter = D3DTEXF_LINEAR; + SetDevice(lpDevice); +} + +CStateManager::~CStateManager() +{ + if (m_lpD3DDev) + { + m_lpD3DDev->Release(); + m_lpD3DDev = NULL; + } +} + +void CStateManager::SetDevice(LPDIRECT3DDEVICE8 lpDevice) +{ + StateManager_Assert(lpDevice); + lpDevice->AddRef(); + + if (m_lpD3DDev) + { + m_lpD3DDev->Release(); + m_lpD3DDev = NULL; + } + + m_lpD3DDev = lpDevice; + + D3DCAPS8 d3dCaps; + m_lpD3DDev->GetDeviceCaps(&d3dCaps); + + if (d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFANISOTROPIC) + m_dwBestMagFilter = D3DTEXF_ANISOTROPIC; + else + m_dwBestMagFilter = D3DTEXF_LINEAR; + + if (d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) + m_dwBestMinFilter = D3DTEXF_ANISOTROPIC; + else + m_dwBestMinFilter = D3DTEXF_LINEAR; + + DWORD dwMax = d3dCaps.MaxAnisotropy; + dwMax = dwMax < 4 ? dwMax : 4; + + for (int i = 0; i < 8; ++i) + m_lpD3DDev->SetTextureStageState(i, D3DTSS_MAXANISOTROPY, dwMax); + + SetDefaultState(); +} + +void CStateManager::SetBestFiltering(DWORD dwStage) +{ + SetTextureStageState(dwStage, D3DTSS_MINFILTER, m_dwBestMinFilter); + SetTextureStageState(dwStage, D3DTSS_MAGFILTER, m_dwBestMagFilter); + SetTextureStageState(dwStage, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); +} + +void CStateManager::Restore() +{ + int i, j; + + m_bForce = true; + + for (i = 0; i < STATEMANAGER_MAX_RENDERSTATES; ++i) + SetRenderState(D3DRENDERSTATETYPE(i), m_CurrentState.m_RenderStates[i]); + + for (i = 0; i < STATEMANAGER_MAX_STAGES; ++i) + for (j = 0; j < STATEMANAGER_MAX_TEXTURESTATES; ++j) + SetTextureStageState(i, D3DTEXTURESTAGESTATETYPE(j), m_CurrentState.m_TextureStates[i][j]); + + for (i = 0; i < STATEMANAGER_MAX_STAGES; ++i) + SetTexture(i, m_CurrentState.m_Textures[i]); + + m_bForce = false; +} + +void CStateManager::SetDefaultState() +{ + m_CurrentState.ResetState(); + m_CopyState.ResetState(); + m_ChipState.ResetState(); + + m_bScene = false; + m_bForce = true; + + D3DXMATRIX Identity; + D3DXMatrixIdentity(&Identity); + + SetTransform(D3DTS_WORLD, &Identity); + SetTransform(D3DTS_VIEW, &Identity); + SetTransform(D3DTS_PROJECTION, &Identity); + + D3DMATERIAL8 DefaultMat; + ZeroMemory(&DefaultMat, sizeof(D3DMATERIAL8)); + + DefaultMat.Diffuse.r = 1.0f; + DefaultMat.Diffuse.g = 1.0f; + DefaultMat.Diffuse.b = 1.0f; + DefaultMat.Diffuse.a = 1.0f; + DefaultMat.Ambient.r = 1.0f; + DefaultMat.Ambient.g = 1.0f; + DefaultMat.Ambient.b = 1.0f; + DefaultMat.Ambient.a = 1.0f; + DefaultMat.Emissive.r = 0.0f; + DefaultMat.Emissive.g = 0.0f; + DefaultMat.Emissive.b = 0.0f; + DefaultMat.Emissive.a = 0.0f; + DefaultMat.Specular.r = 0.0f; + DefaultMat.Specular.g = 0.0f; + DefaultMat.Specular.b = 0.0f; + DefaultMat.Specular.a = 0.0f; + DefaultMat.Power = 0.0f; + + SetMaterial(&DefaultMat); + + SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); + SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL); + SetRenderState(D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL); + SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); + + SetRenderState(D3DRS_LINEPATTERN, 0xFFFFFFFF); + SetRenderState(D3DRS_LASTPIXEL, FALSE); + SetRenderState(D3DRS_ALPHAREF, 1); + SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); + SetRenderState(D3DRS_ZVISIBLE, FALSE); + SetRenderState(D3DRS_FOGSTART, 0); + SetRenderState(D3DRS_FOGEND, 0); + SetRenderState(D3DRS_FOGDENSITY, 0); + SetRenderState(D3DRS_EDGEANTIALIAS, FALSE); + SetRenderState(D3DRS_ZBIAS, 0); + SetRenderState(D3DRS_STENCILWRITEMASK, 0xFFFFFFFF); + SetRenderState(D3DRS_AMBIENT, 0x00000000); + SetRenderState(D3DRS_LOCALVIEWER, FALSE); + SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); + SetRenderState(D3DRS_VERTEXBLEND, D3DVBF_DISABLE); + SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE); + SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE); + SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + SetRenderState(D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE); + SetRenderState(D3DRS_COLORWRITEENABLE, 0xFFFFFFFF); + SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); + SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + SetRenderState(D3DRS_FOGENABLE, FALSE); + SetRenderState(D3DRS_FOGCOLOR, 0xFF000000); + SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_NONE); + SetRenderState(D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); + SetRenderState(D3DRS_RANGEFOGENABLE, FALSE); + SetRenderState(D3DRS_ZENABLE, TRUE); + SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL); + SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + SetRenderState(D3DRS_DITHERENABLE, TRUE); + SetRenderState(D3DRS_STENCILENABLE, FALSE); + SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + SetRenderState(D3DRS_CLIPPING, TRUE); + SetRenderState(D3DRS_LIGHTING, FALSE); + SetRenderState(D3DRS_SPECULARENABLE, FALSE); + SetRenderState(D3DRS_COLORVERTEX, FALSE); + SetRenderState(D3DRS_WRAP0, 0); + SetRenderState(D3DRS_WRAP1, 0); + SetRenderState(D3DRS_WRAP2, 0); + SetRenderState(D3DRS_WRAP3, 0); + SetRenderState(D3DRS_WRAP4, 0); + SetRenderState(D3DRS_WRAP5, 0); + SetRenderState(D3DRS_WRAP6, 0); + SetRenderState(D3DRS_WRAP7, 0); + + SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); + SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); + SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + + SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(2, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(2, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(2, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(2, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(3, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(3, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(3, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(3, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(3, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(3, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(4, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(4, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(4, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(4, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(4, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(4, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(5, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(5, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(5, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(5, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(5, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(5, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(6, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(6, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(6, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(6, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(6, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(6, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(7, D3DTSS_COLOROP, D3DTOP_DISABLE); + SetTextureStageState(7, D3DTSS_COLORARG1, D3DTA_TEXTURE); + SetTextureStageState(7, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + SetTextureStageState(7, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + SetTextureStageState(7, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + SetTextureStageState(7, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); + SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1); + SetTextureStageState(2, D3DTSS_TEXCOORDINDEX, 2); + SetTextureStageState(3, D3DTSS_TEXCOORDINDEX, 3); + SetTextureStageState(4, D3DTSS_TEXCOORDINDEX, 4); + SetTextureStageState(5, D3DTSS_TEXCOORDINDEX, 5); + SetTextureStageState(6, D3DTSS_TEXCOORDINDEX, 6); + SetTextureStageState(7, D3DTSS_TEXCOORDINDEX, 7); + + SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(1, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(2, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(2, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(3, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(3, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(4, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(4, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(4, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(5, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(5, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(5, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(6, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(6, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(6, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(7, D3DTSS_MINFILTER, D3DTEXF_LINEAR); + SetTextureStageState(7, D3DTSS_MAGFILTER, D3DTEXF_LINEAR); + SetTextureStageState(7, D3DTSS_MIPFILTER, D3DTEXF_LINEAR); + + SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(2, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(2, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(3, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(3, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(4, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(4, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(5, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(5, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(6, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(6, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + SetTextureStageState(7, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP); + SetTextureStageState(7, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); + + SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(2, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(3, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(4, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(5, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(6, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + SetTextureStageState(7, D3DTSS_TEXTURETRANSFORMFLAGS, 0); + + SetTexture(0, NULL); + SetTexture(1, NULL); + SetTexture(2, NULL); + SetTexture(3, NULL); + SetTexture(4, NULL); + SetTexture(5, NULL); + SetTexture(6, NULL); + SetTexture(7, NULL); + + SetPixelShader(0); + SetVertexShader(D3DFVF_XYZ); + + D3DXVECTOR4 av4Null[STATEMANAGER_MAX_VCONSTANTS]; + memset(av4Null, 0, sizeof(av4Null)); + SetVertexShaderConstant(0, av4Null, STATEMANAGER_MAX_VCONSTANTS); + SetPixelShaderConstant(0, av4Null, STATEMANAGER_MAX_PCONSTANTS); + + m_bForce = false; + +#ifdef _DEBUG + int i, j; + for (i = 0; i < STATEMANAGER_MAX_RENDERSTATES; i++) + m_bRenderStateSavingFlag[i] = FALSE; + + for (j = 0; j < STATEMANAGER_MAX_TRANSFORMSTATES; j++) + m_bTransformSavingFlag[j] = FALSE; + + for (j = 0; j < STATEMANAGER_MAX_STAGES; ++j) + for (i = 0; i < STATEMANAGER_MAX_TEXTURESTATES; ++i) + m_bTextureStageStateSavingFlag[j][i] = FALSE; +#endif _DEBUG +} + +// Material +void CStateManager::SaveMaterial() +{ + m_CopyState.m_D3DMaterial = m_CurrentState.m_D3DMaterial; +} + +void CStateManager::SaveMaterial(const D3DMATERIAL8 * pMaterial) +{ + // Check that we have set this up before, if not, the default is this. + m_CopyState.m_D3DMaterial = m_CurrentState.m_D3DMaterial; + SetMaterial(pMaterial); +} + +void CStateManager::RestoreMaterial() +{ + SetMaterial(&m_CopyState.m_D3DMaterial); +} + +void CStateManager::SetMaterial(const D3DMATERIAL8 * pMaterial) +{ + m_lpD3DDev->SetMaterial(pMaterial); + m_CurrentState.m_D3DMaterial = *pMaterial; +} + +void CStateManager::GetMaterial(D3DMATERIAL8 * pMaterial) +{ + // Set the renderstate and remember it. + *pMaterial = m_CurrentState.m_D3DMaterial; +} + +// Renderstates +DWORD CStateManager::GetRenderState(D3DRENDERSTATETYPE Type) +{ + return m_CurrentState.m_RenderStates[Type]; +} + +void CStateManager::SaveRenderState(D3DRENDERSTATETYPE Type, DWORD dwValue) +{ +#ifdef _DEBUG + if (m_bRenderStateSavingFlag[Type]) + { + Tracef(" CStateManager::SaveRenderState - This render state is already saved [%d, %d]\n", Type, dwValue); + StateManager_Assert(!" This render state is already saved!"); + } + m_bRenderStateSavingFlag[Type] = TRUE; +#endif _DEBUG + + // Check that we have set this up before, if not, the default is this. + m_CopyState.m_RenderStates[Type] = m_CurrentState.m_RenderStates[Type]; + SetRenderState(Type, dwValue); +} + +void CStateManager::RestoreRenderState(D3DRENDERSTATETYPE Type) +{ +#ifdef _DEBUG + if (!m_bRenderStateSavingFlag[Type]) + { + Tracef(" CStateManager::SaveRenderState - This render state was not saved [%d, %d]\n", Type); + StateManager_Assert(!" This render state was not saved!"); + } + m_bRenderStateSavingFlag[Type] = FALSE; +#endif _DEBUG + + SetRenderState(Type, m_CopyState.m_RenderStates[Type]); +} + +void CStateManager::SetRenderState(D3DRENDERSTATETYPE Type, DWORD Value) +{ + if (m_CurrentState.m_RenderStates[Type] == Value) + return; + + m_lpD3DDev->SetRenderState(Type, Value); + m_CurrentState.m_RenderStates[Type] = Value; +} + +void CStateManager::GetRenderState(D3DRENDERSTATETYPE Type, DWORD * pdwValue) +{ + *pdwValue = m_CurrentState.m_RenderStates[Type]; +} + +// Textures +void CStateManager::SaveTexture(DWORD dwStage, LPDIRECT3DBASETEXTURE8 pTexture) +{ + // Check that we have set this up before, if not, the default is this. + m_CopyState.m_Textures[dwStage] = m_CurrentState.m_Textures[dwStage]; + SetTexture(dwStage, pTexture); +} + +void CStateManager::RestoreTexture(DWORD dwStage) +{ + SetTexture(dwStage, m_CopyState.m_Textures[dwStage]); +} + +void CStateManager::SetTexture(DWORD dwStage, LPDIRECT3DBASETEXTURE8 pTexture) +{ + if (pTexture == m_CurrentState.m_Textures[dwStage]) + return; + + m_lpD3DDev->SetTexture(dwStage, pTexture); + m_CurrentState.m_Textures[dwStage] = pTexture; +} + +void CStateManager::GetTexture(DWORD dwStage, LPDIRECT3DBASETEXTURE8 * ppTexture) +{ + *ppTexture = m_CurrentState.m_Textures[dwStage]; +} + +// Texture stage states +void CStateManager::SaveTextureStageState(DWORD dwStage,D3DTEXTURESTAGESTATETYPE Type, DWORD dwValue) +{ + // Check that we have set this up before, if not, the default is this. +#ifdef _DEBUG + if (m_bTextureStageStateSavingFlag[dwStage][Type]) + { + Tracef(" CStateManager::SaveTextureStageState - This texture stage state is already saved [%d, %d]\n", dwStage, Type); + StateManager_Assert(!" This texture stage state is already saved!"); + } + m_bTextureStageStateSavingFlag[dwStage][Type] = TRUE; +#endif _DEBUG + m_CopyState.m_TextureStates[dwStage][Type] = m_CurrentState.m_TextureStates[dwStage][Type]; + SetTextureStageState(dwStage, Type, dwValue); +} + +void CStateManager::RestoreTextureStageState(DWORD dwStage, D3DTEXTURESTAGESTATETYPE Type) +{ +#ifdef _DEBUG + if (!m_bTextureStageStateSavingFlag[dwStage][Type]) + { + Tracef(" CStateManager::RestoreTextureStageState - This texture stage state was not saved [%d, %d]\n", dwStage, Type); + StateManager_Assert(!" This texture stage state was not saved!"); + } + m_bTextureStageStateSavingFlag[dwStage][Type] = FALSE; +#endif _DEBUG + SetTextureStageState(dwStage, Type, m_CopyState.m_TextureStates[dwStage][Type]); +} + +void CStateManager::SetTextureStageState(DWORD dwStage, D3DTEXTURESTAGESTATETYPE Type, DWORD dwValue) +{ + if (m_CurrentState.m_TextureStates[dwStage][Type] == dwValue) + return; + + m_lpD3DDev->SetTextureStageState(dwStage, Type, dwValue); + m_CurrentState.m_TextureStates[dwStage][Type] = dwValue; +} + +void CStateManager::GetTextureStageState(DWORD dwStage, D3DTEXTURESTAGESTATETYPE Type, DWORD * pdwValue) +{ + *pdwValue = m_CurrentState.m_TextureStates[dwStage][Type]; +} + +// Vertex Shader +void CStateManager::SaveVertexShader(DWORD dwShader) +{ + m_CopyState.m_dwVertexShader = m_CurrentState.m_dwVertexShader; + SetVertexShader(dwShader); +} + +void CStateManager::RestoreVertexShader() +{ + SetVertexShader(m_CopyState.m_dwVertexShader); +} + +void CStateManager::SetVertexShader(DWORD dwShader) +{ + if (m_CurrentState.m_dwVertexShader == dwShader) + return; + + m_lpD3DDev->SetVertexShader(dwShader); + m_CurrentState.m_dwVertexShader = dwShader; +} + +void CStateManager::GetVertexShader(DWORD * pdwShader) +{ + *pdwShader = m_CurrentState.m_dwVertexShader; +} + +// Pixel Shader +void CStateManager::SavePixelShader(DWORD dwShader) +{ + m_CopyState.m_dwPixelShader = m_CurrentState.m_dwPixelShader; + SetPixelShader(dwShader); +} + +void CStateManager::RestorePixelShader() +{ + SetPixelShader(m_CopyState.m_dwPixelShader); +} + +void CStateManager::SetPixelShader(DWORD dwShader) +{ + if (m_CurrentState.m_dwPixelShader == dwShader) + return; + + m_lpD3DDev->SetPixelShader(dwShader); + m_CurrentState.m_dwPixelShader = dwShader; +} + +void CStateManager::GetPixelShader(DWORD * pdwShader) +{ + *pdwShader = m_CurrentState.m_dwPixelShader; +} + +// *** These states are cached, but not protected from multiple sends of the same value. +// Transform +void CStateManager::SaveTransform(D3DTRANSFORMSTATETYPE Type, const D3DMATRIX* pMatrix) +{ +#ifdef _DEBUG + if (m_bTransformSavingFlag[Type]) + { + Tracef(" CStateManager::SaveTransform - This transform is already saved [%d]\n", Type); + StateManager_Assert(!" This trasform is already saved!"); + } + m_bTransformSavingFlag[Type] = TRUE; +#endif _DEBUG + + m_CopyState.m_Matrices[Type] = m_CurrentState.m_Matrices[Type]; + SetTransform(Type, (D3DXMATRIX *)pMatrix); +} + +void CStateManager::RestoreTransform(D3DTRANSFORMSTATETYPE Type) +{ +#ifdef _DEBUG + if (!m_bTransformSavingFlag[Type]) + { + Tracef(" CStateManager::RestoreTransform - This transform was not saved [%d]\n", Type); + StateManager_Assert(!" This render state was not saved!"); + } + m_bTransformSavingFlag[Type] = FALSE; +#endif _DEBUG + + SetTransform(Type, &m_CopyState.m_Matrices[Type]); +} + +// Don't cache-check the transform. To much to do +void CStateManager::SetTransform(D3DTRANSFORMSTATETYPE Type, const D3DMATRIX* pMatrix) +{ + if (m_bScene) + { + m_lpD3DDev->SetTransform(Type, pMatrix); + } + else + { + assert(D3DTS_VIEW==Type || D3DTS_PROJECTION==Type || D3DTS_WORLD==Type); + } + + m_CurrentState.m_Matrices[Type] = *pMatrix; +} + +void CStateManager::GetTransform(D3DTRANSFORMSTATETYPE Type, D3DMATRIX * pMatrix) +{ + *pMatrix = m_CurrentState.m_Matrices[Type]; +} + +// SetVertexShaderConstant +void CStateManager::SaveVertexShaderConstant(DWORD dwRegister,CONST void* pConstantData,DWORD dwConstantCount) +{ + DWORD i; + + for (i = 0; i < dwConstantCount; i++) + { + StateManager_Assert((dwRegister + i) < STATEMANAGER_MAX_VCONSTANTS); + m_CopyState.m_VertexShaderConstants[dwRegister + i] = m_CurrentState.m_VertexShaderConstants[dwRegister + i]; + } + + SetVertexShaderConstant(dwRegister, pConstantData, dwConstantCount); +} + +void CStateManager::RestoreVertexShaderConstant(DWORD dwRegister, DWORD dwConstantCount) +{ + SetVertexShaderConstant(dwRegister, &m_CopyState.m_VertexShaderConstants[dwRegister], dwConstantCount); +} + +void CStateManager::SetVertexShaderConstant(DWORD dwRegister,CONST void* pConstantData,DWORD dwConstantCount) +{ + m_lpD3DDev->SetVertexShaderConstant(dwRegister, pConstantData, dwConstantCount); + + // Set the renderstate and remember it. + for (DWORD i = 0; i < dwConstantCount; i++) + { + StateManager_Assert((dwRegister + i) < STATEMANAGER_MAX_VCONSTANTS); + m_CurrentState.m_VertexShaderConstants[dwRegister + i] = *(((D3DXVECTOR4*)pConstantData) + i); + } +} + +// SetPixelShaderConstant +void CStateManager::SavePixelShaderConstant(DWORD dwRegister,CONST void* pConstantData,DWORD dwConstantCount) +{ + DWORD i; + + for (i = 0; i < dwConstantCount; i++) + { + StateManager_Assert((dwRegister + i) < STATEMANAGER_MAX_VCONSTANTS); + m_CopyState.m_PixelShaderConstants[dwRegister + i] = *(((D3DXVECTOR4*)pConstantData) + i); + } + + SetPixelShaderConstant(dwRegister, pConstantData, dwConstantCount); +} + +void CStateManager::RestorePixelShaderConstant(DWORD dwRegister, DWORD dwConstantCount) +{ + SetPixelShaderConstant(dwRegister, &m_CopyState.m_PixelShaderConstants[dwRegister], dwConstantCount); +} + +void CStateManager::SetPixelShaderConstant(DWORD dwRegister,CONST void* pConstantData,DWORD dwConstantCount) +{ + m_lpD3DDev->SetPixelShaderConstant(dwRegister, pConstantData, dwConstantCount); + + // Set the renderstate and remember it. + for (DWORD i = 0; i < dwConstantCount; i++) + { + StateManager_Assert((dwRegister + i) < STATEMANAGER_MAX_VCONSTANTS); + m_CurrentState.m_PixelShaderConstants[dwRegister + i] = *(((D3DXVECTOR4*)pConstantData) + i); + } +} + +void CStateManager::SaveStreamSource(UINT StreamNumber, LPDIRECT3DVERTEXBUFFER8 pStreamData,UINT Stride) +{ + // Check that we have set this up before, if not, the default is this. + m_CopyState.m_StreamData[StreamNumber] = m_CurrentState.m_StreamData[StreamNumber]; + SetStreamSource(StreamNumber, pStreamData, Stride); +} + +void CStateManager::RestoreStreamSource(UINT StreamNumber) +{ + SetStreamSource(StreamNumber, + m_CopyState.m_StreamData[StreamNumber].m_lpStreamData, + m_CopyState.m_StreamData[StreamNumber].m_Stride); +} + +void CStateManager::SetStreamSource(UINT StreamNumber, LPDIRECT3DVERTEXBUFFER8 pStreamData, UINT Stride) +{ + CStreamData kStreamData(pStreamData, Stride); + if (m_CurrentState.m_StreamData[StreamNumber] == kStreamData) + return; + + m_lpD3DDev->SetStreamSource(StreamNumber, pStreamData, Stride); + m_CurrentState.m_StreamData[StreamNumber] = kStreamData; +} + +void CStateManager::SaveIndices(LPDIRECT3DINDEXBUFFER8 pIndexData, UINT BaseVertexIndex) +{ + m_CopyState.m_IndexData = m_CurrentState.m_IndexData; + SetIndices(pIndexData, BaseVertexIndex); +} + +void CStateManager::RestoreIndices() +{ + SetIndices(m_CopyState.m_IndexData.m_lpIndexData, m_CopyState.m_IndexData.m_BaseVertexIndex); +} + +void CStateManager::SetIndices(LPDIRECT3DINDEXBUFFER8 pIndexData, UINT BaseVertexIndex) +{ + CIndexData kIndexData(pIndexData, BaseVertexIndex); + + if (m_CurrentState.m_IndexData == kIndexData) + return; + + m_lpD3DDev->SetIndices(pIndexData, BaseVertexIndex); + m_CurrentState.m_IndexData = kIndexData; +} + +HRESULT CStateManager::DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) +{ + return (m_lpD3DDev->DrawPrimitive(PrimitiveType, StartVertex, PrimitiveCount)); +} + +HRESULT CStateManager::DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride) +{ + m_CurrentState.m_StreamData[0] = NULL; + return (m_lpD3DDev->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride)); +} + +HRESULT CStateManager::DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) +{ + return (m_lpD3DDev->DrawIndexedPrimitive(PrimitiveType, minIndex, NumVertices, startIndex, primCount)); +} + +HRESULT CStateManager::DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, CONST void * pIndexData, D3DFORMAT IndexDataFormat, CONST void * pVertexStreamZeroData, UINT VertexStreamZeroStride) +{ + m_CurrentState.m_IndexData = NULL; + m_CurrentState.m_StreamData[0] = NULL; + return (m_lpD3DDev->DrawIndexedPrimitiveUP(PrimitiveType, MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride)); +} diff --git a/extension/src/port/common/D3D8Types.h b/extension/src/port/common/D3D8Types.h index 730028f5..b995fe98 100644 --- a/extension/src/port/common/D3D8Types.h +++ b/extension/src/port/common/D3D8Types.h @@ -408,6 +408,56 @@ typedef enum _D3DCULL { D3DCULL_FORCE_DWORD = 0x7fffffff, } D3DCULL; +typedef enum _D3DTEXTUREFILTERTYPE { + D3DTEXF_NONE = 0, + D3DTEXF_POINT = 1, + D3DTEXF_LINEAR = 2, + D3DTEXF_ANISOTROPIC = 3, + D3DTEXF_FLATCUBIC = 4, + D3DTEXF_GAUSSIANCUBIC = 5, + D3DTEXF_FORCE_DWORD = 0x7fffffff +} D3DTEXTUREFILTERTYPE; + +typedef enum _D3DSHADEMODE { + D3DSHADE_FLAT = 1, + D3DSHADE_GOURAUD = 2, + D3DSHADE_PHONG = 3, + D3DSHADE_FORCE_DWORD = 0x7fffffff +} D3DSHADEMODE; + +typedef enum _D3DBLENDOP { + D3DBLENDOP_ADD = 1, + D3DBLENDOP_SUBTRACT = 2, + D3DBLENDOP_REVSUBTRACT = 3, + D3DBLENDOP_MIN = 4, + D3DBLENDOP_MAX = 5, + D3DBLENDOP_FORCE_DWORD = 0x7fffffff +} D3DBLENDOP; + +typedef enum _D3DFOGMODE { + D3DFOG_NONE = 0, + D3DFOG_EXP = 1, + D3DFOG_EXP2 = 2, + D3DFOG_LINEAR = 3, + D3DFOG_FORCE_DWORD = 0x7fffffff +} D3DFOGMODE; + +typedef enum _D3DMATERIALCOLORSOURCE { + D3DMCS_MATERIAL = 0, + D3DMCS_COLOR1 = 1, + D3DMCS_COLOR2 = 2, + D3DMCS_FORCE_DWORD = 0x7fffffff +} D3DMATERIALCOLORSOURCE; + +typedef enum _D3DVERTEXBLENDFLAGS { + D3DVBF_DISABLE = 0, + D3DVBF_1WEIGHTS = 1, + D3DVBF_2WEIGHTS = 2, + D3DVBF_3WEIGHTS = 3, + D3DVBF_TWEENING = 255, + D3DVBF_0WEIGHTS = 256 +} D3DVERTEXBLENDFLAGS; + #define D3DTS_WORLDMATRIX(index) (D3DTRANSFORMSTATETYPE)(index + 256) #define D3DTS_WORLD D3DTS_WORLDMATRIX(0) #define D3DTS_WORLD1 D3DTS_WORLDMATRIX(1) @@ -593,16 +643,72 @@ typedef struct _D3DCAPS8 float MaxPixelShaderValue; } D3DCAPS8; -// COM interfaces: no methods here; platform/ owns every instance. The resource hierarchy is kept -// so the implicit upcasts 40250 relies on (texture -> base texture) compile. +#define D3DDEVCAPS_HWTRANSFORMANDLIGHT 0x00010000L +#define D3DPTFILTERCAPS_MINFANISOTROPIC 0x00000400L +#define D3DPTFILTERCAPS_MAGFANISOTROPIC 0x04000000L +#define D3DPTADDRESSCAPS_WRAP 0x00000001L +#define D3DPTADDRESSCAPS_MIRROR 0x00000002L +#define D3DPTADDRESSCAPS_CLAMP 0x00000004L +#define D3DPTADDRESSCAPS_BORDER 0x00000008L + +#define D3DADAPTER_DEFAULT 0 +#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0x00000020L +#define D3DCREATE_HARDWARE_VERTEXPROCESSING 0x00000040L +#define D3DCREATE_MIXED_VERTEXPROCESSING 0x00000080L +#define D3DVS_VERSION(_Major, _Minor) (0xFFFE0000 | ((_Major) << 8) | (_Minor)) +#define D3DPMISCCAPS_CLIPTLVERTS 0x00000200L + +// COM interfaces: platform/ owns every instance. The resource hierarchy is kept so the implicit +// upcasts 40250 relies on (texture -> base texture) compile; of the resources only the buffers carry +// methods (Lock/Unlock, platform/EterLib/CpuBuffer.h). struct IDirect3D8; -struct IDirect3DDevice8; struct IDirect3DResource8 {}; struct IDirect3DBaseTexture8 : IDirect3DResource8 {}; struct IDirect3DTexture8 : IDirect3DBaseTexture8 {}; struct IDirect3DSurface8 : IDirect3DResource8 {}; -struct IDirect3DVertexBuffer8 : IDirect3DResource8 {}; -struct IDirect3DIndexBuffer8 : IDirect3DResource8 {}; +struct IDirect3DVertexBuffer8 : IDirect3DResource8 +{ + virtual ~IDirect3DVertexBuffer8() = default; + virtual HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags) = 0; + virtual HRESULT Unlock() = 0; +}; +struct IDirect3DIndexBuffer8 : IDirect3DResource8 +{ + virtual ~IDirect3DIndexBuffer8() = default; + virtual HRESULT Lock(UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags) = 0; + virtual HRESULT Unlock() = 0; +}; + +// The device methods the ported code calls (CStateManager), with D3D8's signatures. The platform +// implements it (platform/EterLib/RecordingDevice.h) as a device that records draw calls. +struct IDirect3DDevice8 +{ + virtual ~IDirect3DDevice8() = default; + virtual ULONG AddRef() = 0; + virtual ULONG Release() = 0; + virtual HRESULT GetDeviceCaps(D3DCAPS8* pCaps) = 0; + virtual HRESULT GetViewport(D3DVIEWPORT8* pViewport) = 0; + virtual UINT GetAvailableTextureMem() = 0; + virtual HRESULT BeginScene() = 0; + virtual HRESULT EndScene() = 0; + virtual HRESULT SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix) = 0; + virtual HRESULT GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) = 0; + virtual HRESULT SetMaterial(const D3DMATERIAL8* pMaterial) = 0; + virtual HRESULT SetLight(DWORD Index, const D3DLIGHT8* pLight) = 0; + virtual HRESULT SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) = 0; + virtual HRESULT SetTexture(DWORD Stage, IDirect3DBaseTexture8* pTexture) = 0; + virtual HRESULT SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) = 0; + virtual HRESULT SetVertexShader(DWORD Handle) = 0; + virtual HRESULT SetPixelShader(DWORD Handle) = 0; + virtual HRESULT SetVertexShaderConstant(DWORD Register, const void* pConstantData, DWORD ConstantCount) = 0; + virtual HRESULT SetPixelShaderConstant(DWORD Register, const void* pConstantData, DWORD ConstantCount) = 0; + virtual HRESULT SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer8* pStreamData, UINT Stride) = 0; + virtual HRESULT SetIndices(IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) = 0; + virtual HRESULT DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) = 0; + virtual HRESULT DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT MinIndex, UINT NumVertices, UINT StartIndex, UINT PrimitiveCount) = 0; + virtual HRESULT DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride) = 0; + virtual HRESULT DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertexIndices, UINT PrimitiveCount, const void* pIndexData, D3DFORMAT IndexDataFormat, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride) = 0; +}; typedef IDirect3D8* LPDIRECT3D8; typedef IDirect3DDevice8* LPDIRECT3DDEVICE8; typedef IDirect3DResource8* LPDIRECT3DRESOURCE8; diff --git a/extension/src/port/common/D3DXMath.cpp b/extension/src/port/common/D3DXMath.cpp index 22943e64..35600c42 100644 --- a/extension/src/port/common/D3DXMath.cpp +++ b/extension/src/port/common/D3DXMath.cpp @@ -341,3 +341,144 @@ D3DXQUATERNION* D3DXQuaternionRotationYawPitchRoll(D3DXQUATERNION* pOut, FLOAT y pOut->w = cyaw * cpitch * croll + syaw * spitch * sroll; return pOut; } + +D3DXMATRIX* D3DXMatrixPerspectiveFovRH(D3DXMATRIX* pOut, FLOAT fovy, FLOAT aspect, FLOAT zn, FLOAT zf) +{ + const FLOAT yScale = 1.0f / tanf(fovy / 2.0f); + *pOut = D3DXMATRIX(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + pOut->_11 = yScale / aspect; + pOut->_22 = yScale; + pOut->_33 = zf / (zn - zf); + pOut->_34 = -1.0f; + pOut->_43 = zn * zf / (zn - zf); + return pOut; +} + +D3DXMATRIX* D3DXMatrixOrthoRH(D3DXMATRIX* pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf) +{ + D3DXMatrixIdentity(pOut); + pOut->_11 = 2.0f / w; + pOut->_22 = 2.0f / h; + pOut->_33 = 1.0f / (zn - zf); + pOut->_43 = zn / (zn - zf); + return pOut; +} + +D3DXMATRIX* D3DXMatrixOrthoOffCenterRH(D3DXMATRIX* pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf) +{ + D3DXMatrixIdentity(pOut); + pOut->_11 = 2.0f / (r - l); + pOut->_22 = 2.0f / (t - b); + pOut->_33 = 1.0f / (zn - zf); + pOut->_41 = (l + r) / (l - r); + pOut->_42 = (t + b) / (b - t); + pOut->_43 = zn / (zn - zf); + return pOut; +} + +ID3DXMatrixStack::ID3DXMatrixStack() : m_stack(1) +{ + D3DXMatrixIdentity(&m_stack.back()); +} + +ULONG ID3DXMatrixStack::Release() +{ + delete this; + return 0; +} + +HRESULT ID3DXMatrixStack::Pop() +{ + if (m_stack.size() > 1) + m_stack.pop_back(); + return S_OK; +} + +HRESULT ID3DXMatrixStack::Push() +{ + m_stack.push_back(m_stack.back()); + return S_OK; +} + +HRESULT ID3DXMatrixStack::LoadIdentity() +{ + D3DXMatrixIdentity(&m_stack.back()); + return S_OK; +} + +HRESULT ID3DXMatrixStack::LoadMatrix(const D3DXMATRIX* pM) +{ + m_stack.back() = *pM; + return S_OK; +} + +HRESULT ID3DXMatrixStack::MultMatrix(const D3DXMATRIX* pM) +{ + D3DXMatrixMultiply(&m_stack.back(), &m_stack.back(), pM); + return S_OK; +} + +HRESULT ID3DXMatrixStack::MultMatrixLocal(const D3DXMATRIX* pM) +{ + D3DXMatrixMultiply(&m_stack.back(), pM, &m_stack.back()); + return S_OK; +} + +HRESULT ID3DXMatrixStack::RotateAxis(const D3DXVECTOR3* pV, FLOAT angle) +{ + D3DXMATRIX m; + return MultMatrix(D3DXMatrixRotationAxis(&m, pV, angle)); +} + +HRESULT ID3DXMatrixStack::RotateAxisLocal(const D3DXVECTOR3* pV, FLOAT angle) +{ + D3DXMATRIX m; + return MultMatrixLocal(D3DXMatrixRotationAxis(&m, pV, angle)); +} + +HRESULT ID3DXMatrixStack::RotateYawPitchRoll(FLOAT yaw, FLOAT pitch, FLOAT roll) +{ + D3DXMATRIX m; + return MultMatrix(D3DXMatrixRotationYawPitchRoll(&m, yaw, pitch, roll)); +} + +HRESULT ID3DXMatrixStack::RotateYawPitchRollLocal(FLOAT yaw, FLOAT pitch, FLOAT roll) +{ + D3DXMATRIX m; + return MultMatrixLocal(D3DXMatrixRotationYawPitchRoll(&m, yaw, pitch, roll)); +} + +HRESULT ID3DXMatrixStack::Scale(FLOAT x, FLOAT y, FLOAT z) +{ + D3DXMATRIX m; + return MultMatrix(D3DXMatrixScaling(&m, x, y, z)); +} + +HRESULT ID3DXMatrixStack::ScaleLocal(FLOAT x, FLOAT y, FLOAT z) +{ + D3DXMATRIX m; + return MultMatrixLocal(D3DXMatrixScaling(&m, x, y, z)); +} + +HRESULT ID3DXMatrixStack::Translate(FLOAT x, FLOAT y, FLOAT z) +{ + D3DXMATRIX m; + return MultMatrix(D3DXMatrixTranslation(&m, x, y, z)); +} + +HRESULT ID3DXMatrixStack::TranslateLocal(FLOAT x, FLOAT y, FLOAT z) +{ + D3DXMATRIX m; + return MultMatrixLocal(D3DXMatrixTranslation(&m, x, y, z)); +} + +D3DXMATRIX* ID3DXMatrixStack::GetTop() +{ + return &m_stack.back(); +} + +HRESULT D3DXCreateMatrixStack(DWORD, ID3DXMatrixStack** ppStack) +{ + *ppStack = new ID3DXMatrixStack; + return S_OK; +} diff --git a/extension/src/port/common/D3DXMath.h b/extension/src/port/common/D3DXMath.h index 04e6c16b..d1f8a3d4 100644 --- a/extension/src/port/common/D3DXMath.h +++ b/extension/src/port/common/D3DXMath.h @@ -8,6 +8,7 @@ #include "D3D8Types.h" #include +#include #define D3DX_PI ((FLOAT)3.141592654f) #define D3DX_1BYPI ((FLOAT)0.318309886f) @@ -368,6 +369,9 @@ D3DXMATRIX* D3DXMatrixRotationZ(D3DXMATRIX* pOut, FLOAT angle); D3DXMATRIX* D3DXMatrixRotationAxis(D3DXMATRIX* pOut, const D3DXVECTOR3* pV, FLOAT angle); D3DXMATRIX* D3DXMatrixRotationQuaternion(D3DXMATRIX* pOut, const D3DXQUATERNION* pQ); D3DXMATRIX* D3DXMatrixRotationYawPitchRoll(D3DXMATRIX* pOut, FLOAT yaw, FLOAT pitch, FLOAT roll); +D3DXMATRIX* D3DXMatrixPerspectiveFovRH(D3DXMATRIX* pOut, FLOAT fovy, FLOAT aspect, FLOAT zn, FLOAT zf); +D3DXMATRIX* D3DXMatrixOrthoRH(D3DXMATRIX* pOut, FLOAT w, FLOAT h, FLOAT zn, FLOAT zf); +D3DXMATRIX* D3DXMatrixOrthoOffCenterRH(D3DXMATRIX* pOut, FLOAT l, FLOAT r, FLOAT b, FLOAT t, FLOAT zn, FLOAT zf); // --- D3DXQUATERNION --- inline D3DXQUATERNION* D3DXQuaternionIdentity(D3DXQUATERNION* pOut) @@ -386,3 +390,29 @@ inline FLOAT D3DXPlaneDotCoord(const D3DXPLANE* pP, const D3DXVECTOR3* pV) { return pP->a * pV->x + pP->b * pV->y + pP->c * pV->z + pP->d; } + +// --- ID3DXMatrixStack --- (the D3DX8 interface, as a plain class: the Local variants pre-multiply) +struct ID3DXMatrixStack +{ + ID3DXMatrixStack(); + ULONG Release(); + HRESULT Pop(); + HRESULT Push(); + HRESULT LoadIdentity(); + HRESULT LoadMatrix(const D3DXMATRIX* pM); + HRESULT MultMatrix(const D3DXMATRIX* pM); + HRESULT MultMatrixLocal(const D3DXMATRIX* pM); + HRESULT RotateAxis(const D3DXVECTOR3* pV, FLOAT angle); + HRESULT RotateAxisLocal(const D3DXVECTOR3* pV, FLOAT angle); + HRESULT RotateYawPitchRoll(FLOAT yaw, FLOAT pitch, FLOAT roll); + HRESULT RotateYawPitchRollLocal(FLOAT yaw, FLOAT pitch, FLOAT roll); + HRESULT Scale(FLOAT x, FLOAT y, FLOAT z); + HRESULT ScaleLocal(FLOAT x, FLOAT y, FLOAT z); + HRESULT Translate(FLOAT x, FLOAT y, FLOAT z); + HRESULT TranslateLocal(FLOAT x, FLOAT y, FLOAT z); + D3DXMATRIX* GetTop(); + +private: + std::vector m_stack; +}; +HRESULT D3DXCreateMatrixStack(DWORD Flags, ID3DXMatrixStack** ppStack); diff --git a/extension/tests/port_login_flow_test.cpp b/extension/tests/port_login_flow_test.cpp index b5a5c664..c2058950 100644 --- a/extension/tests/port_login_flow_test.cpp +++ b/extension/tests/port_login_flow_test.cpp @@ -40,6 +40,7 @@ #include "../src/platform/ScriptLib/PythonHost.h" #include "../src/platform/UserInterface/UserInterface.h" #include "../src/platform/EterBase/TraceErrorObserver.h" +#include "../src/platform/EterLib/RenderCommands3D.h" #include "GameLib/StdAfx.h" #include "GameLib/RaceManager.h" #include "GameLib/RaceData.h" @@ -56,6 +57,7 @@ #include #include +#include #include #include #include @@ -346,6 +348,35 @@ int main(int argc, char** argv) const std::vector before = bones(); CHECK(pump_until(3, [&] { return bones() != before; })); } + // (批次 2V2-e.1) RenderGame drew the character through CStateManager into the recording device: + // a frame holds a textured, lit triangle draw (the PNT vertex format of RenderWithOneTexture) + // under CPythonGraphic::SetPerspective's right-handed projection (_34 = -1), and the camera that + // __UpdateCamera centred on the main actor puts every vertex of it on screen. + auto on_screen = [](const Render3DDraw& d) { + auto mul = [](const float* v, const float* m, float* o) { + for (int c = 0; c < 4; ++c) + o[c] = v[0] * m[c] + v[1] * m[4 + c] + v[2] * m[8 + c] + v[3] * m[12 + c]; + }; + for (size_t i = 0; i + 2 < d.positions.size(); i += 3) + { + const float local[4] = {d.positions[i], d.positions[i + 1], d.positions[i + 2], 1.0f}; + float world[4], view[4], clip[4]; + mul(local, d.world, world); + mul(world, d.view, view); + mul(view, d.proj, clip); + if (clip[3] <= 0.0f || std::fabs(clip[0]) > clip[3] || std::fabs(clip[1]) > clip[3]) + return false; + } + return true; + }; + auto character_draw = [&] { + for (const Render3DDraw& d : Render3DDraws()) + if (!d.pretransformed && !d.lines && !d.indices.empty() && !d.texture0.empty() && + !d.normals.empty() && !d.uv0.empty() && d.proj[11] == -1.0f && on_screen(d)) + return true; + return false; + }; + CHECK(pump_until(3, character_draw)); } if (server) {