test(vehicle): a review shot, and the judge that proves the car is missing
Adds demo-vehicle to the camera list and the visual targets, plus shot 9 in Screenshots/README.md - marked FAIL, because that is what it shows. The vehicle is staged and runs: spawned at (-12950,-900,120), 9 visual panels attached, panel 0 visible with a 238 cm extent, settled at Z 119 cm. The capture shows an empty road with a soft shadow. Two checks disagree in a useful way: visual_loop --verify PASSES the frame (it only tests size, blankness and tonal range, so a well-exposed empty road passes), while judge_screenshot returns verdict=no confidence=1.0. Strongest clue, recorded in TODO.md: a downward trace from the vehicle finds no ground at all (ground at Z -9999), so the car sits over a surface without collision or inside geometry - the shadow and the panels are not in the same place. Diagnostics added along the way: mesh/visibility/bounds at BeginPlay, per-panel world positions and extents, and the ground trace. The visual panels were also unhidden from the physics mesh: SetVisibility(false, ...) hid them whether or not propagation was requested.
This commit is contained in:
1 parent
5dd53ac30b
commit
627737062b
42 files changed
+172
-44
No files matched your search
@@ -36,6 +36,68 @@ AGigLineVehicle::AGigLineVehicle()
|
||||
}
|
||||
}
|
||||
|
||||
void AGigLineVehicle::BuildVisuals()
|
||||
{
|
||||
// One component per authored system: body, glass, front and rear lights, mirrors and
|
||||
// the four wheels. Each points at the static asset imported from the same Blender
|
||||
// build, so the render matches what the model tool produced.
|
||||
struct FPanelSpec
|
||||
{
|
||||
const TCHAR* Path;
|
||||
FVector Offset;
|
||||
FRotator Rotation;
|
||||
};
|
||||
const float HalfBase = 139.0f; // wheelbase 278 cm / 2
|
||||
const float HalfTrack = 81.0f; // track 162 cm / 2
|
||||
const FPanelSpec Specs[] = {
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Body.SM_Vehicle_Body"), FVector::ZeroVector, FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Glass.SM_Vehicle_Glass"), FVector::ZeroVector, FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Light_Front.SM_Vehicle_Light_Front"), FVector::ZeroVector, FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Light_Rear.SM_Vehicle_Light_Rear"), FVector::ZeroVector, FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Mirrors.SM_Vehicle_Mirrors"), FVector::ZeroVector, FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Wheel.SM_Vehicle_Wheel"), FVector(HalfBase, HalfTrack, -16.f), FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Wheel.SM_Vehicle_Wheel"), FVector(HalfBase, -HalfTrack, -16.f), FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Wheel.SM_Vehicle_Wheel"), FVector(-HalfBase, HalfTrack, -16.f), FRotator::ZeroRotator},
|
||||
{TEXT("/Game/Hollywood/Vehicle/SM_Vehicle_Wheel.SM_Vehicle_Wheel"), FVector(-HalfBase, -HalfTrack, -16.f), FRotator::ZeroRotator},
|
||||
};
|
||||
|
||||
int32 Index = 0;
|
||||
for (const FPanelSpec& Spec : Specs)
|
||||
{
|
||||
if (UStaticMesh* Mesh = LoadObject<UStaticMesh>(nullptr, Spec.Path))
|
||||
{
|
||||
UStaticMeshComponent* Component = NewObject<UStaticMeshComponent>(this,
|
||||
*FString::Printf(TEXT("Panel_%d"), Index));
|
||||
// Attach to the actor root rather than to the physics mesh, so the visuals are
|
||||
// independent of the simulated component's own state.
|
||||
Component->SetupAttachment(GetRootComponent());
|
||||
Component->SetStaticMesh(Mesh);
|
||||
Component->SetRelativeLocation(Spec.Offset);
|
||||
Component->SetRelativeRotation(Spec.Rotation);
|
||||
Component->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
Component->SetMobility(EComponentMobility::Movable);
|
||||
Component->RegisterComponent();
|
||||
Panels.Add(Component);
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
UE_LOG(LogTemp, Warning, TEXT("GigLine vehicle: %d visual panels attached"), Panels.Num());
|
||||
for (int32 PanelIndex = 0; PanelIndex < Panels.Num(); ++PanelIndex)
|
||||
{
|
||||
const UStaticMeshComponent* Panel = Panels[PanelIndex];
|
||||
if (!Panel)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const FVector Where = Panel->GetComponentLocation();
|
||||
const FBoxSphereBounds B = Panel->Bounds;
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: panel %d at (%.0f,%.0f,%.0f) visible=%d extent=%.0f"),
|
||||
PanelIndex, Where.X, Where.Y, Where.Z,
|
||||
Panel->IsVisible() ? 1 : 0, B.BoxExtent.GetMax());
|
||||
}
|
||||
}
|
||||
|
||||
void AGigLineVehicle::ConfigureWheels()
|
||||
{
|
||||
UChaosWheeledVehicleMovementComponent* Movement =
|
||||
@@ -92,6 +154,17 @@ void AGigLineVehicle::BeginPlay()
|
||||
{
|
||||
Super::BeginPlay();
|
||||
|
||||
// The skeletal mesh is the physics driver only: its imported geometry is unusable
|
||||
// (1 cm bounds), so it is hidden and the visible car comes from the static panels.
|
||||
if (USkeletalMeshComponent* PhysicsMesh = GetMesh())
|
||||
{
|
||||
// Do not hide the physics mesh at all. It has no usable geometry (1 cm bounds), so
|
||||
// it renders nothing either way, and every attempt to hide it also hid the visual
|
||||
// panels - with and without propagation. Leaving it visible avoids the fight.
|
||||
PhysicsMesh->SetCastShadow(false);
|
||||
}
|
||||
BuildVisuals();
|
||||
|
||||
// Wheel objects do not exist until the component is registered, so the per-wheel
|
||||
// flags set in the constructor went nowhere - which is why the drive test measured
|
||||
// zero speed with throttle held. Apply them again now that they exist, and give the
|
||||
@@ -106,6 +179,16 @@ void AGigLineVehicle::BeginPlay()
|
||||
Movement->TransmissionSetup.bUseAutomaticGears = true;
|
||||
Movement->TransmissionSetup.FinalRatio = 3.5f;
|
||||
Movement->SetThrottleInput(0.0f);
|
||||
if (const USkeletalMeshComponent* BodyComp = GetMesh())
|
||||
{
|
||||
const USkeletalMesh* Asset = BodyComp->GetSkeletalMeshAsset();
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: mesh=%s visible=%d hidden=%d bounds=%s"),
|
||||
Asset ? *Asset->GetName() : TEXT("NONE"),
|
||||
BodyComp->IsVisible() ? 1 : 0,
|
||||
BodyComp->bHiddenInGame ? 1 : 0,
|
||||
*BodyComp->Bounds.BoxExtent.ToString());
|
||||
}
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: %d wheel objects after register, torque %.0f"),
|
||||
Movement->Wheels.Num(), Movement->EngineSetup.MaxTorque);
|
||||
@@ -158,6 +241,17 @@ void AGigLineVehicle::Tick(float DeltaSeconds)
|
||||
if (!bSettleReported && SettleElapsed > 3.0f)
|
||||
{
|
||||
bSettleReported = true;
|
||||
if (UWorld* World = GetWorld())
|
||||
{
|
||||
FHitResult Hit;
|
||||
FCollisionQueryParams Q(TEXT("GigLineVehicleGround"), false, this);
|
||||
const bool bGround = World->LineTraceSingleByChannel(Hit, GetActorLocation(),
|
||||
GetActorLocation() - FVector(0.f, 0.f, 2000.f), ECC_Visibility, Q);
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: ground at Z %.0f cm, actor %.0f cm, height above ground %.0f cm"),
|
||||
bGround ? Hit.ImpactPoint.Z : -9999.f, GetActorLocation().Z,
|
||||
bGround ? GetActorLocation().Z - Hit.ImpactPoint.Z : -9999.f);
|
||||
}
|
||||
const USkeletalMeshComponent* Body = GetMesh();
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: settled at Z %.0f cm, simulating=%d, speed=%.0f cm/s"),
|
||||
|
||||
@@ -29,6 +29,18 @@ public:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
/**
|
||||
* Visual panels, as static mesh components.
|
||||
*
|
||||
* The skeletal vehicle asset imported with no usable geometry (runtime bounds of
|
||||
* 1 cm), so the car was invisible in the scene while its physics body still cast a
|
||||
* shadow - the "no vehicle in scene" report. The static assets are correct (body
|
||||
* 476 x 176 x 128 cm), so the visible car is assembled from them and the skeletal
|
||||
* mesh stays as the physics/animation driver only.
|
||||
*/
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Visual")
|
||||
TArray<TObjectPtr<UStaticMeshComponent>> Panels;
|
||||
|
||||
/** True once the vehicle reports a forward speed above a walking pace. */
|
||||
bool IsMoving() const;
|
||||
|
||||
@@ -36,6 +48,9 @@ private:
|
||||
/** Configure the Chaos wheels from the modelled dimensions. */
|
||||
void ConfigureWheels();
|
||||
|
||||
/** Attach the visible panels from the imported static systems. */
|
||||
void BuildVisuals();
|
||||
|
||||
float DriveElapsed = 0.f;
|
||||
bool bDriveReported = false;
|
||||
FVector DriveStart = FVector::ZeroVector;
|
||||
|
||||
Reference in new issue
Block a user