RecurseSKLFile now builds a joint renderable for any node whose page name resolves to a live skeleton Joint: HingeX/Y/Z -> HingeRenderable (watching Joint::GetHinge), Ball -> BallJointRenderable (watching GetEulerAngles), otherwise the static path. Each holds the rest offset in one DCS and the live rotation in a child DCS, and its Execute diffs the watched value and calls DPL_FLUSH_DCS -- the engine's own mechanism (L4VIDRND.CPP:1026+). The value comes from the mech's JointSubsystem via ResolveJoint, so sim and renderer read one source. Gated on BT_JOINTS while it proves out. [skl] video\max.skl -> 26 nodes, 1 objects, 1 eye, 22 articulated The bridge reported anim_abs=1 joints=0 twist=+0.00 before; it now reports joints=1 twist=-0.86, matching the game's [torso] twist=-0.856. With the mech stationary, frames that differed by 0.0% now differ by 62-80%. A crash it exposed: Mech::ResolveJoint passed segment->GetJointIndex() straight to GetJoint unchecked, and a segment with no joint reports -1 -- GetNthImplementation then indexes [base + -1*4] and dies (guest 00426A1D). Torso never hit it because it only asks for its own authored joint name; the walk asks for every page. Now bounds-checked against GetJointCount. Open: the canopy does not stay rigid in the view, though it and the eye hang off the same articulated node. Cancelling the bridge's cage compensation (CAGE_TWIST_SIGN=0) did not close it. Leading hypothesis: SetupCull builds worldToEyeMatrix from GetSegmentToWorld(siteeyepoint) -- the SIMULATION's segment transform -- independent of the render tree, so the canopy follows our render chain and the eye follows the sim's, and they diverge whenever one carries the twist and the other does not. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
104 lines
3.5 KiB
C++
104 lines
3.5 KiB
C++
//===========================================================================//
|
|
// File: btl4vid.hpp //
|
|
// Project: BattleTech //
|
|
// Contents: Implementation details for the BT video renderer //
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#if !defined(BTL4VID_HPP)
|
|
# define BTL4VID_HPP
|
|
|
|
# if !defined(L4VIDEO_HPP)
|
|
# include <l4video.hpp>
|
|
# endif
|
|
|
|
# include <dpl.h>
|
|
# include <dplutils.h>
|
|
|
|
//###########################################################################
|
|
//####################### BTL4VideoRenderer #############################
|
|
//###########################################################################
|
|
|
|
class BTL4VideoRenderer:
|
|
public DPLRenderer
|
|
{
|
|
public:
|
|
BTL4VideoRenderer(
|
|
RendererRate calibration_rate,
|
|
RendererComplexity calibration_complexity,
|
|
RendererPriority calibration_priority,
|
|
InterestType interest_type,
|
|
InterestDepth depth_calibration
|
|
);
|
|
~BTL4VideoRenderer();
|
|
|
|
protected:
|
|
void
|
|
LoadMissionImplementation(Mission *mission);
|
|
|
|
//
|
|
// (A diagnostic ExecuteImplementation wrapper briefly lived here to
|
|
// count dynamic renderables per frame; it cannot exist, because
|
|
// DPLRenderer::ExecuteImplementation is PRIVATE -- virtual dispatch
|
|
// reaches it, but a subclass cannot chain it by name. The question
|
|
// it was built to answer got answered by the wire instead: zero
|
|
// vr_flush_dcs_artic records because NO dynamic renderable existed
|
|
// -- the engine rejects Skeleton resources, so chaining the base for
|
|
// the mech built nothing. See MakeEntityRenderables.)
|
|
//
|
|
|
|
//
|
|
// The bottom of this virtual chain is
|
|
// VideoRenderer::MakeEntityRenderables (VIDREND.CPP:231), whose own
|
|
// comment says it is only reached when nobody above could figure out
|
|
// what to build -- and it just complains. The engine's DPLRenderer
|
|
// layer knows the ENGINE classes; the game's own classes are ours.
|
|
//
|
|
void
|
|
MakeEntityRenderables(
|
|
Entity *entity,
|
|
ResourceDescription *model_resource,
|
|
ViewFrom view_type);
|
|
|
|
//
|
|
// The mech's model resource is a SKELETON, not an object, and the
|
|
// engine rejects it ("wrong video resource type") because building
|
|
// one is the GAME renderer's job. Shape taken from the surviving
|
|
// sibling header CODE/RP/RP_L4/RPL4VID.HPP.
|
|
//
|
|
dpl_DCS *
|
|
ReadSKLFile(
|
|
Entity *entity,
|
|
dpl_DCS *parent_dcs,
|
|
const char *skeleton_filename,
|
|
ViewFrom view_type,
|
|
int *eye_count,
|
|
int *joint_count);
|
|
|
|
dpl_DCS *
|
|
RecurseSKLFile(
|
|
Entity *entity,
|
|
dpl_DCS *parent_dcs,
|
|
NotationFile *skeleton,
|
|
const char *page_name,
|
|
int recursion_depth,
|
|
ViewFrom view_type,
|
|
dpl_ZONE *zone,
|
|
int *node_count,
|
|
int *object_count,
|
|
int *eye_count,
|
|
int *joint_count);
|
|
|
|
protected:
|
|
int reserved[16];
|
|
};
|
|
|
|
#endif
|