From dadee7e94ac4087f26af65aaaeed7007f1f7f083 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Tue, 24 Dec 2024 14:36:24 -0800 Subject: [PATCH] Some more camera cleanups And Zelda LegacyActor cleanups. --- src/Camera.ts | 56 +++++++----------- src/MathHelpers.ts | 4 +- src/Studio.ts | 8 +-- src/SuperMarioGalaxy/Actors/Enemy.ts | 8 +-- src/SuperMarioGalaxy/Actors/LensFlare.ts | 24 +++----- src/SuperMarioGalaxy/Actors/MapObj.ts | 4 +- src/SuperMarioGalaxy/Actors/MiscActor.ts | 8 +-- src/SuperMarioGalaxy/LiveActor.ts | 4 +- src/ZeldaTwilightPrincess/LegacyActor.ts | 70 ++++++++++++----------- src/ZeldaTwilightPrincess/d_kankyo.ts | 4 +- src/ZeldaTwilightPrincess/f_op_actor.ts | 6 +- src/ZeldaWindWaker/LegacyActor.ts | 72 +++++++++++++++--------- src/ZeldaWindWaker/f_op_actor.ts | 12 ++-- src/ZeldaWindWaker/framework.ts | 5 +- 14 files changed, 144 insertions(+), 141 deletions(-) diff --git a/src/Camera.ts b/src/Camera.ts index 5d93cfe4f..2cd1398e3 100644 --- a/src/Camera.ts +++ b/src/Camera.ts @@ -2,7 +2,7 @@ import { mat4, vec3, vec4, quat, ReadonlyVec3, ReadonlyMat4, ReadonlyVec4 } from 'gl-matrix'; import InputManager from './InputManager.js'; import { Frustum, AABB } from './Geometry.js'; -import { clampRange, projectionMatrixForFrustum, computeUnitSphericalCoordinates, projectionMatrixForCuboid, lerpAngle, MathConstants, getMatrixAxisY, transformVec3Mat4w1, Vec3Zero, Vec3UnitY, Vec3UnitX, Vec3UnitZ, transformVec3Mat4w0, getMatrixAxisZ, getMatrixAxisX, computeEulerAngleRotationFromSRTMatrix } from './MathHelpers.js'; +import { clampRange, projectionMatrixForFrustum, calcUnitSphericalCoordinates, projectionMatrixForCuboid, lerpAngle, MathConstants, getMatrixAxisY, transformVec3Mat4w1, Vec3Zero, Vec3UnitY, Vec3UnitX, Vec3UnitZ, transformVec3Mat4w0, getMatrixAxisZ, getMatrixAxisX, calcEulerAngleRotationFromSRTMatrix } from './MathHelpers.js'; import { projectionMatrixConvertClipSpaceNearZ } from './gfx/helpers/ProjectionHelpers.js'; import { WebXRContext } from './WebXR.js'; import { assert } from './util.js'; @@ -137,14 +137,13 @@ const scratchVec3c = vec3.create(); const scratchVec3d = vec3.create(); const scratchVec3e = vec3.create(); const scratchVec3f = vec3.create(); -const scratchVec4 = vec4.create(); const scratchMat4 = mat4.create(); const scratchQuat = quat.create(); /** - * Computes a view-space depth given @param viewMatrix and @param aabb in world-space. + * Computes a view-space depth given {@param viewMatrix} and {@param aabb} in world-space. * - * This is computed by taking the depth of the center of the passed-in @param aabb. + * This is computed by taking the depth of the center of the passed-in {@param aabb}. * * The convention of "view-space depth" is that 0 is near plane, +z is further away. * @@ -160,11 +159,11 @@ export function computeViewSpaceDepthFromWorldSpaceAABB(viewMatrix: ReadonlyMat4 } /** - * Computes a view-space depth given @param viewMatrix and @param v in world-space. + * Computes a view-space depth given {@param viewMatrix} and {@param v} in world-space. * * The convention of "view-space depth" is that 0 is near plane, +z is further away. * - * The returned value is not clamped to the near or far planes -- that is, the depth + * The returned value is not clamped to the near or far planes — that is, the depth * value is less than zero if the camera is behind the point. * * The returned value can be passed directly to {@see GfxRenderInst.setSortKeyDepth}, @@ -185,10 +184,10 @@ export class ScreenSpaceProjection { // These values are in "flat clip space" (that is, -1 corresponds to the left frustum plane, // and +1 corresponds to the right frustum plane). If the projected area extends beyond these // planes, then these values might go less than -1 or greater than +1. This is normal. - public projectedMinX!: number; - public projectedMinY!: number; - public projectedMaxX!: number; - public projectedMaxY!: number; + public projectedMinX: number; + public projectedMinY: number; + public projectedMaxX: number; + public projectedMaxY: number; constructor() { this.reset(); @@ -221,40 +220,25 @@ export class ScreenSpaceProjection { } } -/** - * Transforms the world-space point @param p, viewed by the camera @param Camera into - * normalized clip space and stores the result in @param output. Note that this is normalized - * clip space (between -1 and 1 on all three axes). Conversion into screen or viewport space - * is not done in this function. - */ -export function computeClipSpacePointFromWorldSpacePoint(output: vec3, camera: Camera, p: ReadonlyVec3, v4 = scratchVec4): void { - vec4.set(v4, p[0], p[1], p[2], 1.0); - vec4.transformMat4(v4, v4, camera.clipFromWorldMatrix); - const w = v4[3]; - vec3.set(output, v4[0] / w, v4[1] / w, v4[2] / w); -} - /** * Computes the screen-space projection @param screenSpaceProjection, that * a sphere in world-space coordinates with parameters @param center and @param radius * will take up when viewed by @param camera. */ -export function computeScreenSpaceProjectionFromWorldSpaceSphere(screenSpaceProjection: ScreenSpaceProjection, camera: Camera, center: ReadonlyVec3, radius: number, v: vec3 = scratchVec3a, v4: vec4 = scratchVec4): void { +export function calcScreenSpaceProjectionFromWorldSpaceSphere(screenSpaceProjection: ScreenSpaceProjection, camera: Camera, center: ReadonlyVec3, radius: number): void { screenSpaceProjection.reset(); + const v = scratchVec3a; transformVec3Mat4w1(v, camera.viewMatrix, center); - v[2] = -Math.max(Math.abs(v[2] - radius), camera.near); - const viewCenterX = v[0], viewCenterY = v[1], viewCenterZ = v[2]; // Compute the corners of screen-space square that encloses the sphere. for (let xs = -1; xs <= 1; xs += 2) { for (let ys = -1; ys <= 1; ys += 2) { - vec4.set(v4, viewCenterX + radius*xs, viewCenterY + radius*ys, viewCenterZ, 1.0); - vec4.transformMat4(v4, v4, camera.projectionMatrix); - divideByW(v4, v4); - screenSpaceProjection.union(v4[0], v4[1]); + vec3.set(v, viewCenterX + radius*xs, viewCenterY + radius*ys, viewCenterZ); + vec3.transformMat4(v, v, camera.projectionMatrix); + screenSpaceProjection.union(v[0], v[1]); } } } @@ -263,13 +247,11 @@ export function computeScreenSpaceProjectionFromWorldSpaceSphere(screenSpaceProj * Computes the screen-space projection @param screenSpaceProjection, that * world-space AABB @param aabb will take up when viewed by @param camera. */ -export function computeScreenSpaceProjectionFromWorldSpaceAABB(screenSpaceProjection: ScreenSpaceProjection, camera: Camera, aabb: AABB, v: vec3 = scratchVec3a, v4: vec4 = scratchVec4): void { +export function calcScreenSpaceProjectionFromWorldSpaceAABB(screenSpaceProjection: ScreenSpaceProjection, camera: Camera, aabb: AABB): void { const radius = aabb.boundingSphereRadius(); - // Compute view-space center. - aabb.centerPoint(v); - - return computeScreenSpaceProjectionFromWorldSpaceSphere(screenSpaceProjection, camera, v, radius, v, v4); + aabb.centerPoint(scratchVec3a); + return calcScreenSpaceProjectionFromWorldSpaceSphere(screenSpaceProjection, camera, scratchVec3a, radius); } export const enum CameraUpdateResult { @@ -790,7 +772,7 @@ export class OrbitCameraController implements CameraController { vec3.scaleAndAdd(this.translation, this.translation, scratchVec3a, this.tyVel); const eyePos = scratchVec3a; - computeUnitSphericalCoordinates(eyePos, this.x, this.y); + calcUnitSphericalCoordinates(eyePos, this.x, this.y); vec3.scale(eyePos, eyePos, this.z); vec3.add(eyePos, eyePos, this.translation); this.camera.isOrthographic = false; @@ -968,7 +950,7 @@ export class OrthoCameraController implements CameraController { const eyePos = scratchVec3a; - computeUnitSphericalCoordinates(eyePos, this.x, this.y); + calcUnitSphericalCoordinates(eyePos, this.x, this.y); vec3.scale(eyePos, eyePos, -this.farPlane / 2); vec3.add(eyePos, eyePos, this.translation); mat4.targetTo(this.camera.worldMatrix, eyePos, this.translation, Vec3UnitY); diff --git a/src/MathHelpers.ts b/src/MathHelpers.ts index 33385122e..f9bf7497f 100644 --- a/src/MathHelpers.ts +++ b/src/MathHelpers.ts @@ -385,7 +385,7 @@ export function projectionMatrixForCuboid(m: mat4, left: number, right: number, m[15] = 1; } -export function computeEulerAngleRotationFromSRTMatrix(dst: vec3, m: ReadonlyMat4): void { +export function calcEulerAngleRotationFromSRTMatrix(dst: vec3, m: ReadonlyMat4): void { // "Euler Angle Conversion", Ken Shoemake, Graphics Gems IV. http://www.gregslabaugh.net/publications/euler.pdf if (compareEpsilon(m[2], 1.0)) { @@ -403,7 +403,7 @@ export function computeEulerAngleRotationFromSRTMatrix(dst: vec3, m: ReadonlyMat } } -export function computeUnitSphericalCoordinates(dst: vec3, azimuthal: number, polar: number): void { +export function calcUnitSphericalCoordinates(dst: vec3, azimuthal: number, polar: number): void { // https://en.wikipedia.org/wiki/Spherical_coordinate_system // https://en.wikipedia.org/wiki/List_of_common_coordinate_transformations#From_spherical_coordinates // Wikipedia uses the convention of Z-up, we use Y-up here. diff --git a/src/Studio.ts b/src/Studio.ts index 4760fb57e..5aa2a95fe 100644 --- a/src/Studio.ts +++ b/src/Studio.ts @@ -4,7 +4,7 @@ import { FloatingPanel } from './DebugFloaters.js'; import { drawWorldSpaceLine, drawWorldSpacePoint, getDebugOverlayCanvas2D } from './DebugJunk.js'; import { Blue, Color, Green, Red, Magenta, Cyan } from './Color.js'; import { StudioCameraController } from './Camera.js'; -import { clamp, computeEulerAngleRotationFromSRTMatrix, getMatrixAxisZ, lerp, invlerp, Vec3UnitY, Vec3Zero, MathConstants } from './MathHelpers.js'; +import { clamp, calcEulerAngleRotationFromSRTMatrix, getMatrixAxisZ, lerp, invlerp, Vec3UnitY, Vec3Zero, MathConstants } from './MathHelpers.js'; import { mat4, ReadonlyMat4, vec3, vec2 } from 'gl-matrix'; import { GlobalSaveManager } from './SaveManager.js'; import { getPointHermite } from './Spline.js'; @@ -2479,7 +2479,7 @@ export class StudioPanel extends FloatingPanel { } else { mat4.rotateZ(this.scratchMat, this.scratchMat, this.animationPreviewSteps[i].bank); } - computeEulerAngleRotationFromSRTMatrix(this.scratchVec3a, this.scratchMat); + calcEulerAngleRotationFromSRTMatrix(this.scratchVec3a, this.scratchMat); vec3.copy(this.scratchVec3c, Vec3UnitY); vec3.rotateZ(this.scratchVec3c, this.scratchVec3c, Vec3Zero, -this.scratchVec3a[2]); vec3.rotateY(this.scratchVec3c, this.scratchVec3c, Vec3Zero, -this.scratchVec3a[1]); @@ -2511,7 +2511,7 @@ export class StudioPanel extends FloatingPanel { } else { mat4.rotateZ(this.scratchMat, this.scratchMat, this.animationPreviewSteps[stepIndex].bank); } - computeEulerAngleRotationFromSRTMatrix(this.scratchVec3a, this.scratchMat); + calcEulerAngleRotationFromSRTMatrix(this.scratchVec3a, this.scratchMat); vec3.copy(this.scratchVec3c, Vec3UnitY); vec3.rotateZ(this.scratchVec3c, this.scratchVec3c, Vec3Zero, -this.scratchVec3a[2]); vec3.rotateY(this.scratchVec3c, this.scratchVec3c, Vec3Zero, -this.scratchVec3a[1]); @@ -3603,7 +3603,7 @@ export class StudioPanel extends FloatingPanel { const lookAtYKf: Keyframe = { time: t, value: this.scratchVecLook[1], tangentIn: 0, tangentOut: 0, interpInType: interpType, interpOutType: interpType, easeInCoeff: 1, easeOutCoeff: 1 }; const lookAtZKf: Keyframe = { time: t, value: this.scratchVecLook[2], tangentIn: 0, tangentOut: 0, interpInType: interpType, interpOutType: interpType, easeInCoeff: 1, easeOutCoeff: 1 }; - computeEulerAngleRotationFromSRTMatrix(this.scratchVecPos, mat); + calcEulerAngleRotationFromSRTMatrix(this.scratchVecPos, mat); vec3.copy(this.scratchVecLook, Vec3UnitY); vec3.rotateZ(this.scratchVecLook, this.scratchVecLook, Vec3Zero, -this.scratchVecPos[2]); vec3.rotateY(this.scratchVecLook, this.scratchVecLook, Vec3Zero, -this.scratchVecPos[1]); diff --git a/src/SuperMarioGalaxy/Actors/Enemy.ts b/src/SuperMarioGalaxy/Actors/Enemy.ts index e8dd5cc4d..7e43061b9 100644 --- a/src/SuperMarioGalaxy/Actors/Enemy.ts +++ b/src/SuperMarioGalaxy/Actors/Enemy.ts @@ -1,7 +1,7 @@ import { mat4, quat, ReadonlyMat4, ReadonlyQuat, ReadonlyVec3, vec3 } from 'gl-matrix'; import { GfxRenderInstManager } from '../../gfx/render/GfxRenderInstManager.js'; -import { clamp, computeEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixT, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, lerpAngle, MathConstants, normToLength, normToLengthAndAdd, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, transformVec3Mat4w1, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; +import { clamp, calcEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixT, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, lerpAngle, MathConstants, normToLength, normToLengthAndAdd, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, transformVec3Mat4w1, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; import { assert, assertExists, fallback, nArray } from '../../util.js'; import * as Viewer from '../../viewer.js'; import { addVelocityFromPush, addVelocityFromPushHorizon, addVelocityMoveToDirection, addVelocityToGravity, appearStarPiece, attenuateVelocity, blendQuatUpFront, calcDistanceToPlayer, calcFrontVec, calcGravity, calcGravityVector, calcMtxFromGravityAndZAxis, calcNearestRailPos, calcNearestRailDirection, calcPerpendicFootToLine, calcRailPointPos, calcRailStartPos, calcSqDistanceToPlayer, calcUpVec, calcVelocityMoveToDirection, connectToScene, connectToSceneCollisionEnemyNoShadowedMapObjStrongLight, connectToSceneCollisionEnemyStrongLight, connectToSceneEnemy, connectToSceneEnemyMovement, connectToSceneIndirectEnemy, declareStarPiece, excludeCalcShadowToMyCollision, FixedPosition, getBckFrameMax, getBrkFrameMax, getCamYdir, getCamZdir, getCurrentRailPointArg0, getEaseInOutValue, getEaseInValue, getGroupFromArray, getJointMtxByName, getPlayerPos, getRailDirection, getRailPointNum, getRandomInt, getRandomVector, hideModel, initCollisionParts, initDefaultPos, invalidateShadowAll, isActionEnd, isBckOneTimeAndStopped, isBckPlaying, isBckStopped, isBrkStopped, isBtpStopped, isHiddenModel, isInDeath, isNearPlayer, isNearPlayerPose, isOnSwitchA, isSameDirection, isValidSwitchA, isValidSwitchAppear, isValidSwitchB, isValidSwitchDead, joinToGroupArray, listenStageSwitchOnOffA, listenStageSwitchOnOffB, makeMtxFrontUp, makeMtxFrontUpPos, makeMtxTRFromQuatVec, makeMtxUpFront, makeMtxUpFrontPos, makeMtxUpNoSupportPos, makeQuatFromVec, makeQuatUpFront, moveCoordAndFollowTrans, moveCoordAndTransToNearestRailPos, moveCoordAndTransToRailStartPoint, moveCoordToRailPoint, moveCoordToStartPos, moveTransToCurrentRailPos, quatFromMat4, quatGetAxisX, quatGetAxisY, quatGetAxisZ, quatSetRotate, reboundVelocityFromCollision, reboundVelocityFromEachCollision, restrictVelocity, reverseRailDirection, rotateQuatRollBall, sendMsgPushAndKillVelocityToTarget, setBckFrameAndStop, setBckRate, setBrkFrameAndStop, setBvaRate, setRailCoord, setRailCoordSpeed, setRailDirectionToEnd, showModel, startAction, startBck, startBckNoInterpole, startBckWithInterpole, startBpk, startBrk, startBtk, startBtp, startBtpIfExist, startBva, syncStageSwitchAppear, tryStartBck, turnVecToVecCos, turnVecToVecCosOnPlane, useStageSwitchReadAppear, useStageSwitchSleep, useStageSwitchWriteA, useStageSwitchWriteB, useStageSwitchWriteDead, validateShadowAll, vecKillElement, setBtkFrameAndStop, getBckFrame, setBckFrame, isRailReachedGoal, isRailReachedNearGoal, setRailDirectionToStart, moveCoordToNearestPos, moveTransToOtherActorRailPos, moveCoord, calcNearestRailPosAndDirection, isLoopRail, isRailGoingToEnd, getRandomFloat, calcVecToPlayerH, calcVecFromPlayerH, calcDistanceToPlayerH, makeQuatSideUp, turnQuatYDirRad, setMtxQuat, calcRailEndPointDirection, rotateVecDegree, calcSideVec, connectToSceneMapObj, makeMtxSideUp, makeMtxSideFront, appearStarPieceToDirection, isNearPlayerAnyTime, addVelocityMoveToTarget, addVelocityAwayFromTarget, blendMtx, getRailPos, getRailTotalLength, connectToSceneMapObjDecorationStrongLight, connectToSceneMapObjMovement, getRailCoord, calcRailPosAtCoord, calcRailDirectionAtCoord, moveRailRider, getCurrentRailPointNo, getNextRailPointNo, moveCoordAndTransToRailPoint, getBckFrameMaxNamed, clampVecAngleDeg, connectToSceneEnvironment, isBtkExist, isBtkStopped, clampVecAngleRad, connectToSceneEnemyDecorationMovementCalcAnim, isExistRail, getRailPointArg0, getRailPointCoord, calcReboundVelocity, calcReboundVelocitySimple, calcNerveEaseInOutValue } from '../ActorUtil.js'; @@ -1388,7 +1388,7 @@ export class Unizo extends LiveActor { getCamZdir(scratchVec3b, sceneObjHolder.viewerInput.camera); vec3.negate(scratchVec3b, scratchVec3b); makeMtxFrontUp(scratchMatrix, scratchVec3b, scratchVec3a); - computeEulerAngleRotationFromSRTMatrix(this.breakModel.rotation, scratchMatrix); + calcEulerAngleRotationFromSRTMatrix(this.breakModel.rotation, scratchMatrix); this.breakModel.makeActorAppeared(sceneObjHolder); hideModel(this); @@ -4508,7 +4508,7 @@ function calcRotate(actor: LiveActor, front: ReadonlyVec3, turnSpeedDegrees: num vec3.copy(scratchVec3a, scratchVec3b); makeMtxUpFront(scratchMatrix, scratchVec3a, scratchVec3c); - computeEulerAngleRotationFromSRTMatrix(actor.rotation, scratchMatrix); + calcEulerAngleRotationFromSRTMatrix(actor.rotation, scratchMatrix); } function moveAndTurnToTarget(actor: LiveActor, target: ReadonlyVec3, moveSpeed: number, gravitySpeed: number, velocityDamp: number, turnSpeedDegrees: number): void { @@ -7109,7 +7109,7 @@ export class Mogucchi extends LiveActor { getRailDirection(scratchVec3a, this); vec3.negate(scratchVec3b, this.gravityStrikeVec); makeMtxUpFront(scratchMatrix, scratchVec3b, scratchVec3a); - computeEulerAngleRotationFromSRTMatrix(this.rotation, scratchMatrix); + calcEulerAngleRotationFromSRTMatrix(this.rotation, scratchMatrix); } public override makeActorAppeared(sceneObjHolder: SceneObjHolder): void { diff --git a/src/SuperMarioGalaxy/Actors/LensFlare.ts b/src/SuperMarioGalaxy/Actors/LensFlare.ts index b24b15f51..e4d563bae 100644 --- a/src/SuperMarioGalaxy/Actors/LensFlare.ts +++ b/src/SuperMarioGalaxy/Actors/LensFlare.ts @@ -43,16 +43,10 @@ const scratchVec2 = vec2.create(); const scratchVec3a = vec3.create(); const scratchVec3b = vec3.create(); const scratchVec3c = vec3.create(); -const scratchVec4 = vec4.create(); +const scratchVec3 = vec3.create(); const scratchMatrix = mat4.create(); -function project(dst: vec4, v: ReadonlyVec3, viewerInput: ViewerRenderInput): void { - vec4.set(dst, v[0], v[1], v[2], 1.0); - vec4.transformMat4(dst, dst, viewerInput.camera.clipFromWorldMatrix); - divideByW(dst, dst); -} - -function calcScreenPosition(dst: vec2, v: ReadonlyVec4, viewerInput: ViewerRenderInput): void { +function calcScreenPosition(dst: vec2, v: ReadonlyVec3, viewerInput: ViewerRenderInput): void { dst[0] = (v[0] * 0.5 + 0.5) * viewerInput.backbufferWidth; dst[1] = (v[1] * 0.5 + 0.5) * viewerInput.backbufferHeight; } @@ -88,8 +82,8 @@ export class BrightObjBase { checkArg.pointsVisibleNum = 0; vec2.set(checkArg.posCenterAccum, 0.0, 0.0); - project(scratchVec4, position, sceneObjHolder.viewerInput); - calcScreenPosition(checkArg.posCenter, scratchVec4, sceneObjHolder.viewerInput); + vec3.transformMat4(scratchVec3, position, sceneObjHolder.viewerInput.camera.clipFromWorldMatrix); + calcScreenPosition(checkArg.posCenter, scratchVec3, sceneObjHolder.viewerInput); this.checkVisible(sceneObjHolder, checkArg, position); for (let i = 0; i < 8; i++) { @@ -114,7 +108,7 @@ export class BrightObjBase { } private checkVisible(sceneObjHolder: SceneObjHolder, checkArg: BrightObjCheckArg, position: ReadonlyVec3): void { - project(scratchVec4, position, sceneObjHolder.viewerInput); + vec3.transformMat4(scratchVec3, position, sceneObjHolder.viewerInput.camera.clipFromWorldMatrix); let peekZResult: PeekZResult; if (checkArg.pointsNum === checkArg.peekZ.length) { @@ -124,8 +118,8 @@ export class BrightObjBase { peekZResult = checkArg.peekZ[checkArg.pointsNum]; } - let x = scratchVec4[0]; - let y = scratchVec4[1]; + let x = scratchVec3[0]; + let y = scratchVec3[1]; if (!gfxDeviceNeedsFlipY(sceneObjHolder.modelCache.device)) y *= -1; @@ -137,7 +131,7 @@ export class BrightObjBase { // Test if the depth buffer is less than our projected Z coordinate. // Depth buffer readback should result in 0.0 for the near plane, and 1.0 for the far plane. // Put projected coordinate in 0-1 normalized space. - let projectedZ = scratchVec4[2]; + let projectedZ = scratchVec3[2]; if (sceneObjHolder.modelCache.device.queryVendorInfo().clipSpaceNearZ === GfxClipSpaceNearZ.NegativeOne) projectedZ = projectedZ * 0.5 + 0.5; @@ -146,7 +140,7 @@ export class BrightObjBase { if (visible) { checkArg.pointsVisibleNum++; - calcScreenPosition(scratchVec2, scratchVec4, sceneObjHolder.viewerInput); + calcScreenPosition(scratchVec2, scratchVec3, sceneObjHolder.viewerInput); vec2.add(checkArg.posCenterAccum, checkArg.posCenterAccum, scratchVec2); } } diff --git a/src/SuperMarioGalaxy/Actors/MapObj.ts b/src/SuperMarioGalaxy/Actors/MapObj.ts index fa1438fbc..14b344259 100644 --- a/src/SuperMarioGalaxy/Actors/MapObj.ts +++ b/src/SuperMarioGalaxy/Actors/MapObj.ts @@ -8,7 +8,7 @@ import { drawWorldSpacePoint, drawWorldSpaceVector, getDebugOverlayCanvas2D } fr import { GfxRenderInstManager } from '../../gfx/render/GfxRenderInstManager.js'; import { GXMaterialBuilder } from '../../gx/GXMaterialBuilder.js'; import { ColorKind, DrawParams, GXMaterialHelperGfx, MaterialParams } from '../../gx/gx_render.js'; -import { clamp, computeEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixSRT, computeModelMatrixT, getMatrixAxis, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, MathConstants, normToLength, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, Vec3One, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; +import { clamp, calcEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixSRT, computeModelMatrixT, getMatrixAxis, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, MathConstants, normToLength, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, Vec3One, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; import { assert, assertExists, fallback, nArray } from '../../util.js'; import * as Viewer from '../../viewer.js'; import { addVelocityToGravity, attenuateVelocity, calcDistToCamera, calcFrontVec, calcGravity, calcGravityVector, calcMtxFromGravityAndZAxis, calcRailPointPos, calcRailPosAtCoord, calcUpVec, connectToSceneCollisionMapObj, connectToSceneCollisionMapObjStrongLight, connectToSceneCollisionMapObjWeakLight, connectToSceneEnvironment, connectToSceneEnvironmentStrongLight, connectToSceneIndirectMapObj, connectToSceneMapObj, connectToSceneMapObjMovement, connectToSceneMapObjStrongLight, connectToSceneNoShadowedMapObjStrongLight, connectToSceneNoSilhouettedMapObj, connectToScenePlanet, getBckFrameMaxNamed, getBrkFrameMax, getCamPos, getCurrentRailPointArg0, getCurrentRailPointArg1, getCurrentRailPointNo, getEaseOutValue, getJointMtx, getJointMtxByName, getNextRailPointArg2, getPlayerPos, getRailDirection, getRailPointNum, getRailPos, getRailTotalLength, getRandomFloat, getRandomInt, getRandomVector, hideModel, initCollisionParts, initCollisionPartsAutoEqualScaleOne, initDefaultPos, invalidateCollisionPartsForActor, invalidateShadowAll, isBckExist, isBckOneTimeAndStopped, isBckStopped, isBtkExist, isBtpExist, isExistCollisionResource, isExistRail, isHiddenModel, isLoopRail, isNearPlayer, isRailReachedGoal, isSameDirection, isValidSwitchB, isValidSwitchDead, isZeroGravity, joinToGroupArray, listenStageSwitchOnOffA, listenStageSwitchOnOffB, makeMtxFrontNoSupportPos, makeMtxFrontSidePos, makeMtxFrontUpPos, makeMtxUpFrontPos, makeMtxUpNoSupportPos, moveCoord, moveCoordAndFollowTrans, moveCoordAndTransToNearestRailPos, moveCoordAndTransToRailPoint, moveCoordToNearestPos, reboundVelocityFromCollision, reverseRailDirection, rotateVecDegree, setBckFrameAndStop, setBrkFrameAndStop, setBtkFrameAndStop, setBtpFrameAndStop, showModel, startBck, startBrk, startBtk, startBtp, startBva, syncStageSwitchAppear, tryStartAllAnim, turnVecToVecCosOnPlane, useStageSwitchReadAppear, useStageSwitchSleep, useStageSwitchWriteA, useStageSwitchWriteB, useStageSwitchWriteDead, validateCollisionPartsForActor, validateShadowAll, vecKillElement, appearStarPieceToDirection, declareStarPiece, isValidSwitchAppear, connectToScene, calcSqDistToCamera, quatFromMat4, turnVecToVecCos, getBckFrameMax, setBvaFrameAndStop, getBvaFrameMax, isBckPlaying, setBckRate, makeAxisCrossPlane, initCollisionPartsAutoEqualScale, connectToSceneEnemy, makeMtxTRFromQuatVec, isValidSwitchA, isOnSwitchA, turnDirectionToTargetRadians, quatGetAxisX, quatGetAxisY, connectToClippedMapParts, blendMtx, drawSimpleModel, listenStageSwitchOnOffAppear, startAction, isActionEnd, stopBck, isOnSwitchB, calcDistanceToPlayer, getCamZdir, getCamYdir, getCamXdir } from '../ActorUtil.js'; @@ -2776,7 +2776,7 @@ export class MeteorStrike extends LiveActor { if (this.breakObj !== null) { vec3.copy(this.breakObj.translation, this.translation); - computeEulerAngleRotationFromSRTMatrix(this.breakObj.rotation, dst); + calcEulerAngleRotationFromSRTMatrix(this.breakObj.rotation, dst); } } diff --git a/src/SuperMarioGalaxy/Actors/MiscActor.ts b/src/SuperMarioGalaxy/Actors/MiscActor.ts index 845e25082..232d7f8b9 100644 --- a/src/SuperMarioGalaxy/Actors/MiscActor.ts +++ b/src/SuperMarioGalaxy/Actors/MiscActor.ts @@ -19,7 +19,7 @@ import { VertexAttributeInput } from '../../gx/gx_displaylist.js'; import * as GX from '../../gx/gx_enum.js'; import { getVertexInputLocation } from '../../gx/gx_material.js'; import { ColorKind, GXMaterialHelperGfx, MaterialParams, DrawParams } from '../../gx/gx_render.js'; -import { clamp, clampRange, computeEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixS, computeModelMatrixSRT, computeNormalMatrix, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, MathConstants, normToLength, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, transformVec3Mat4w1, vec3FromBasis2, vec3FromBasis3, Vec3NegY, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; +import { clamp, clampRange, calcEulerAngleRotationFromSRTMatrix, computeModelMatrixR, computeModelMatrixS, computeModelMatrixSRT, computeNormalMatrix, getMatrixAxisX, getMatrixAxisY, getMatrixAxisZ, getMatrixTranslation, invlerp, isNearZero, isNearZeroVec3, lerp, MathConstants, normToLength, quatFromEulerRadians, saturate, scaleMatrix, setMatrixTranslation, transformVec3Mat4w0, transformVec3Mat4w1, vec3FromBasis2, vec3FromBasis3, Vec3NegY, vec3SetAll, Vec3UnitX, Vec3UnitY, Vec3UnitZ, Vec3Zero } from '../../MathHelpers.js'; import { TextureMapping } from '../../TextureHolder.js'; import { assert, assertExists, fallback, leftPad, mod, nArray } from '../../util.js'; import * as Viewer from '../../viewer.js'; @@ -7171,7 +7171,7 @@ class PlantMember extends LiveActor { const angle = getRandomFloat(-Math.PI, Math.PI); mat4.rotateY(scratchMatrix, scratchMatrix, angle); - computeEulerAngleRotationFromSRTMatrix(this.rotation, scratchMatrix); + calcEulerAngleRotationFromSRTMatrix(this.rotation, scratchMatrix); } public tryEmitHint(): boolean { @@ -7686,7 +7686,7 @@ export class BrightSun extends LiveActor { quatSetRotate(scratchQuat, Vec3UnitZ, scratchVec3); mat4.fromQuat(scratchMatrix, scratchQuat); - computeEulerAngleRotationFromSRTMatrix(this.sun.rotation, scratchMatrix); + calcEulerAngleRotationFromSRTMatrix(this.sun.rotation, scratchMatrix); } public static override requestArchives(sceneObjHolder: SceneObjHolder, infoIter: JMapInfoIter): void { @@ -8669,7 +8669,7 @@ class HeatHazeEffect extends LiveActor { getMatrixTranslation(this.translation, sceneObjHolder.viewerInput.camera.worldMatrix); vec3.scaleAndAdd(this.translation, this.translation, scratchVec3, this.depth); - computeEulerAngleRotationFromSRTMatrix(this.rotation, sceneObjHolder.viewerInput.camera.worldMatrix); + calcEulerAngleRotationFromSRTMatrix(this.rotation, sceneObjHolder.viewerInput.camera.worldMatrix); const scale = this.depth / 1000.0; vec3SetAll(this.scale, scale); diff --git a/src/SuperMarioGalaxy/LiveActor.ts b/src/SuperMarioGalaxy/LiveActor.ts index 663abb57e..66fafc6c6 100644 --- a/src/SuperMarioGalaxy/LiveActor.ts +++ b/src/SuperMarioGalaxy/LiveActor.ts @@ -5,7 +5,7 @@ import { J3DFrameCtrl, J3DFrameCtrl__UpdateFlags } from "../Common/JSYSTEM/J3D/J import { J3DModelData, J3DModelInstance, MaterialInstance, TEX1Data } from "../Common/JSYSTEM/J3D/J3DGraphBase.js"; import { GfxDevice, GfxFormat } from "../gfx/platform/GfxPlatform.js"; import { LoadedVertexData, LoadedVertexLayout, VertexAttributeInput } from "../gx/gx_displaylist.js"; -import { computeEulerAngleRotationFromSRTMatrix, computeModelMatrixSRT, computeNormalMatrix, Mat4Identity } from "../MathHelpers.js"; +import { calcEulerAngleRotationFromSRTMatrix, computeModelMatrixSRT, computeNormalMatrix, Mat4Identity } from "../MathHelpers.js"; import { align, assertExists, fallback, nArray, nullify } from "../util.js"; import * as Viewer from '../viewer.js'; import { calcGravity, connectToScene, invalidateCollisionPartsForActor, isBckExist, isBckPlaying, isBpkExist, isBpkPlaying, isBrkExist, isBrkPlaying, isBtkExist, isBtkPlaying, isBtpExist, isBtpPlaying, isBvaExist, isBvaPlaying, resetAllCollisionMtx, startBck, startBpk, startBrk, startBtk, startBtp, startBva, validateCollisionPartsForActor } from "./ActorUtil.js"; @@ -569,7 +569,7 @@ export function getJMapInfoRotate(dst: vec3, sceneObjHolder: SceneObjHolder, inf const stageDataHolder = assertExists(sceneObjHolder.stageDataHolder.findPlacedStageDataHolder(infoIter)); mat4.mul(scratch, stageDataHolder.placementMtx, scratch); - computeEulerAngleRotationFromSRTMatrix(dst, scratch); + calcEulerAngleRotationFromSRTMatrix(dst, scratch); } export function makeMtxTRFromActor(dst: mat4, actor: LiveActor): void { diff --git a/src/ZeldaTwilightPrincess/LegacyActor.ts b/src/ZeldaTwilightPrincess/LegacyActor.ts index 3b35aa183..a40317b81 100644 --- a/src/ZeldaTwilightPrincess/LegacyActor.ts +++ b/src/ZeldaTwilightPrincess/LegacyActor.ts @@ -1,30 +1,27 @@ -import * as Viewer from '../viewer.js'; import * as RARC from '../Common/JSYSTEM/JKRArchive.js'; +import * as Viewer from '../viewer.js'; -import { TwilightPrincessRenderer, dGlobals } from "./Main.js"; -import { mat4, vec3 } from "gl-matrix"; +import { mat4, ReadonlyVec3, vec3 } from "gl-matrix"; +import AnimationController from '../AnimationController.js'; +import { colorNewFromRGBA8 } from '../Color.js'; import { J3DModelData } from '../Common/JSYSTEM/J3D/J3DGraphBase.js'; import { J3DModelInstanceSimple } from '../Common/JSYSTEM/J3D/J3DGraphSimple.js'; -import { GfxRendererLayer } from '../gfx/render/GfxRenderInstManager.js'; -import { LoopMode, ANK1, TTK1, TRK1, TPT1 } from '../Common/JSYSTEM/J3D/J3DLoader.js'; -import { assertExists, hexzero, leftPad } from '../util.js'; -import { ResType, ResEntry, ResAssetType } from './d_resorce.js'; -import AnimationController from '../AnimationController.js'; +import { ANK1, LoopMode, TPT1, TRK1, TTK1 } from '../Common/JSYSTEM/J3D/J3DLoader.js'; import { AABB } from '../Geometry.js'; -import { computeModelMatrixSRT, scaleMatrix } from '../MathHelpers.js'; -import { LightType, dKy_tevstr_init, dKy_tevstr_c, settingTevStruct, setLightTevColorType_MAJI } from './d_kankyo.js'; -import { JPABaseEmitter } from '../Common/JSYSTEM/JPA.js'; -import { cPhs__Status, fGlobals, fpcPf__RegisterFallback } from '../ZeldaWindWaker/framework.js' -import { ScreenSpaceProjection, computeScreenSpaceProjectionFromWorldSpaceAABB } from '../Camera.js'; import { GfxDevice } from '../gfx/platform/GfxPlatform.js'; -import { GfxRenderInstManager } from '../gfx/render/GfxRenderInstManager.js'; +import { GfxRenderInstManager, GfxRendererLayer } from '../gfx/render/GfxRenderInstManager.js'; import { ColorKind } from '../gx/gx_render.js'; -import { colorNewFromRGBA8 } from '../Color.js'; -import { calc_mtx, MtxTrans, mDoMtx_ZXYrotM, mDoMtx_YrotM } from '../ZeldaWindWaker/m_do_mtx.js'; +import { computeModelMatrixSRT } from '../MathHelpers.js'; +import { assertExists, leftPad } from '../util.js'; +import { cPhs__Status, fGlobals, fpcPf__RegisterFallback } from '../ZeldaWindWaker/framework.js'; +import { MtxTrans, calc_mtx, mDoMtx_YrotM, mDoMtx_ZXYrotM } from '../ZeldaWindWaker/m_do_mtx.js'; import { cM_s2rad } from '../ZeldaWindWaker/SComponent.js'; -import { fopAc_ac_c, fopAcM_GetParamBit, fopAcM_prm_class } from './f_op_actor.js'; import { dProcName_e } from './d_a.js'; +import { LightType, dKy_tevstr_c, dKy_tevstr_init, setLightTevColorType_MAJI, settingTevStruct } from './d_kankyo.js'; +import { ResAssetType, ResEntry, ResType } from './d_resorce.js'; +import { fopAcM_GetParamBit, fopAcM_prm_class, fopAc_ac_c } from './f_op_actor.js'; +import { dGlobals } from "./Main.js"; const scratchVec3a = vec3.create(); @@ -52,13 +49,34 @@ class d_a_noclip_legacy extends fopAc_ac_c { this.phase = cPhs__Status.Loading; spawnLegacyActor(globals, this, prm).then(() => { - this.phase = cPhs__Status.Next; + this.phase = this.finishLoading(globals); }); } return this.phase; } + private finishLoading(globals: dGlobals): cPhs__Status { + const baseObj = this.objectRenderers[0]; + if (baseObj === undefined) + return cPhs__Status.Stop; + + this.cullMtx = baseObj.modelMatrix; + + if (this.cullSizeSphere !== null && !Object.isFrozen(this.cullSizeSphere)) { + // Convert us to a box. + this.cullSizeSphere = null; + this.cullSizeBox = new AABB(); + } + + if (this.cullSizeBox !== null && !Object.isFrozen(this.cullSizeBox)) { + // Compute the cull box using only the parent. + this.cullSizeBox.copy(baseObj.modelInstance.modelData.bbox); + } + + return cPhs__Status.Next; + } + public override draw(globals: dGlobals, renderInstManager: GfxRenderInstManager, viewerInput: Viewer.ViewerRenderInput): void { const device = globals.modelCache.device; @@ -79,7 +97,6 @@ class d_a_noclip_legacy extends fopAc_ac_c { function spawnLegacyActor(globals: dGlobals, legacy: d_a_noclip_legacy, actor: fopAcM_prm_class): Promise { const modelCache = globals.modelCache; - const renderer = globals.renderer; const resCtrl = modelCache.resCtrl; const actorName = globals.dStage__searchNameRev(legacy.processName, legacy.subtype); @@ -165,16 +182,12 @@ function spawnLegacyActor(globals: dGlobals, legacy: d_a_noclip_legacy, actor: f return resInfo.lazyLoadResource(ResType.Btp, assertExists(resInfo.res.find((res) => path.endsWith(res.file.name)))); } - function createEmitter(context: TwilightPrincessRenderer, resourceId: number): JPABaseEmitter { - return globals.particleCtrl.set(globals, 0, resourceId, null)!; - } - const enum TagShape { Cube, Cylinder, } - function createTag(shape: TagShape, rgba8Color: number, scale: vec3): void { + function createTag(shape: TagShape, rgba8Color: number, scale: ReadonlyVec3): void { if (shape === TagShape.Cube) { fetchArchive(`K_cube00`).then((rarc) => { const m = buildModel(rarc, `bmdr/k_size_cube.bmd`, true); @@ -1394,8 +1407,6 @@ function spawnLegacyActor(globals: dGlobals, legacy: d_a_noclip_legacy, actor: f // Special-case actors -const bboxScratch = new AABB(); -const screenProjection = new ScreenSpaceProjection(); class BMDObjectRenderer { public visible = true; public isTag = false; @@ -1448,13 +1459,6 @@ class BMDObjectRenderer { mat4.mul(this.modelInstance.modelMatrix, this.parentJointMatrix, this.modelMatrix); } else { mat4.copy(this.modelInstance.modelMatrix, this.modelMatrix); - - // Don't compute screen area culling on child meshes (don't want heads to disappear before bodies.) - bboxScratch.transform(this.modelInstance.modelData.bbox, this.modelInstance.modelMatrix); - computeScreenSpaceProjectionFromWorldSpaceAABB(screenProjection, viewerInput.camera, bboxScratch); - - if (screenProjection.getScreenArea() <= 0.0002) - return; } mat4.getTranslation(scratchVec3a, this.modelMatrix); diff --git a/src/ZeldaTwilightPrincess/d_kankyo.ts b/src/ZeldaTwilightPrincess/d_kankyo.ts index cdffbc380..ee5ccd8ee 100644 --- a/src/ZeldaTwilightPrincess/d_kankyo.ts +++ b/src/ZeldaTwilightPrincess/d_kankyo.ts @@ -5,7 +5,7 @@ import { Camera } from "../Camera.js"; import { Color, OpaqueBlack, TransparentBlack, White, colorCopy, colorFromRGBA, colorNewCopy, colorNewFromRGBA8 } from "../Color.js"; import { J3DModelInstance, MaterialInstance } from "../Common/JSYSTEM/J3D/J3DGraphBase.js"; import { LoopMode } from "../Common/JSYSTEM/J3D/J3DLoader.js"; -import { MathConstants, Vec3Zero, computeUnitSphericalCoordinates, invlerp, lerp, saturate } from "../MathHelpers.js"; +import { MathConstants, Vec3Zero, calcUnitSphericalCoordinates, invlerp, lerp, saturate } from "../MathHelpers.js"; import { cLib_addCalc, cM_rndF } from "../ZeldaWindWaker/SComponent.js"; import { GfxRenderInstManager } from "../gfx/render/GfxRenderInstManager.js"; import * as GX from "../gx/gx_enum.js"; @@ -977,7 +977,7 @@ export function settingTevStruct_colget_player(envLight: dScnKy_env_light_c, tev } export function dKy_lightdir_set(dst: vec3, x: number, y: number): void { - computeUnitSphericalCoordinates(dst, x * MathConstants.DEG_TO_RAD, y * MathConstants.DEG_TO_RAD); + calcUnitSphericalCoordinates(dst, x * MathConstants.DEG_TO_RAD, y * MathConstants.DEG_TO_RAD); } export function settingTevStruct(globals: dGlobals, lightType: LightType, pos: vec3 | null, tevStr: dKy_tevstr_c): void { diff --git a/src/ZeldaTwilightPrincess/f_op_actor.ts b/src/ZeldaTwilightPrincess/f_op_actor.ts index 5c64030b2..1164602d1 100644 --- a/src/ZeldaTwilightPrincess/f_op_actor.ts +++ b/src/ZeldaTwilightPrincess/f_op_actor.ts @@ -1,7 +1,7 @@ import { mat4, vec3, vec4 } from "gl-matrix"; import { AABB } from "../Geometry.js"; -import { Camera, computeScreenSpaceProjectionFromWorldSpaceAABB, computeScreenSpaceProjectionFromWorldSpaceSphere, ScreenSpaceProjection } from "../Camera.js"; +import { Camera, calcScreenSpaceProjectionFromWorldSpaceAABB, calcScreenSpaceProjectionFromWorldSpaceSphere, ScreenSpaceProjection } from "../Camera.js"; import { base_process_class, cPhs__Status, fGlobals, fopDwTg_DrawQTo, fopDwTg_ToDrawQ, fpcPc__IsVisible, fpcSCtRq_Request, leafdraw_class } from "../ZeldaWindWaker/framework.js"; import { dKy_tevstr_c, dKy_tevstr_init } from "./d_kankyo.js"; import { dGlobals } from "./Main.js"; @@ -121,7 +121,7 @@ export class fopAc_ac_c extends leafdraw_class { if (!frustum.contains(scratchAABB)) return false; - computeScreenSpaceProjectionFromWorldSpaceAABB(scratchScreenSpaceProjection, camera, scratchAABB); + calcScreenSpaceProjectionFromWorldSpaceAABB(scratchScreenSpaceProjection, camera, scratchAABB); if (scratchScreenSpaceProjection.getScreenArea() <= 0.0002) return false; } else if (this.cullSizeSphere !== null) { @@ -132,7 +132,7 @@ export class fopAc_ac_c extends leafdraw_class { if (!frustum.containsSphere(scratchVec3a, radius)) return false; - computeScreenSpaceProjectionFromWorldSpaceSphere(scratchScreenSpaceProjection, camera, scratchVec3a, radius); + calcScreenSpaceProjectionFromWorldSpaceSphere(scratchScreenSpaceProjection, camera, scratchVec3a, radius); if (scratchScreenSpaceProjection.getScreenArea() <= 0.0002) return false; } diff --git a/src/ZeldaWindWaker/LegacyActor.ts b/src/ZeldaWindWaker/LegacyActor.ts index abc4ca0c5..208b28a39 100644 --- a/src/ZeldaWindWaker/LegacyActor.ts +++ b/src/ZeldaWindWaker/LegacyActor.ts @@ -1,30 +1,28 @@ -import * as Viewer from '../viewer.js'; import * as RARC from '../Common/JSYSTEM/JKRArchive.js'; +import * as Viewer from '../viewer.js'; -import { WindWakerRenderer, ZWWExtraTextures, dGlobals } from "./Main.js"; import { mat4, vec3 } from "gl-matrix"; +import AnimationController from '../AnimationController.js'; import { J3DModelData } from '../Common/JSYSTEM/J3D/J3DGraphBase.js'; import { J3DModelInstanceSimple } from '../Common/JSYSTEM/J3D/J3DGraphSimple.js'; -import { GfxRendererLayer } from '../gfx/render/GfxRenderInstManager.js'; -import { LoopMode, ANK1, TTK1, TRK1, TPT1 } from '../Common/JSYSTEM/J3D/J3DLoader.js'; -import { assertExists, hexzero, leftPad } from '../util.js'; -import { ResType, ResEntry, ResAssetType } from './d_resorce.js'; -import AnimationController from '../AnimationController.js'; -import { AABB } from '../Geometry.js'; -import { computeModelMatrixSRT, scaleMatrix } from '../MathHelpers.js'; -import { LightType, dKy_tevstr_init, dKy_tevstr_c, settingTevStruct, setLightTevColorType } from './d_kankyo.js'; +import { ANK1, LoopMode, TPT1, TRK1, TTK1 } from '../Common/JSYSTEM/J3D/J3DLoader.js'; import { JPABaseEmitter } from '../Common/JSYSTEM/JPA.js'; -import { cPhs__Status, fGlobals, fpcPf__RegisterFallback } from './framework.js'; -import { ScreenSpaceProjection, computeScreenSpaceProjectionFromWorldSpaceAABB } from '../Camera.js'; +import { AABB } from '../Geometry.js'; import { GfxDevice } from '../gfx/platform/GfxPlatform.js'; -import { GfxRenderInstManager } from '../gfx/render/GfxRenderInstManager.js'; +import { GfxRenderInstManager, GfxRendererLayer } from '../gfx/render/GfxRenderInstManager.js'; +import { computeModelMatrixSRT, scaleMatrix } from '../MathHelpers.js'; +import { assertExists, hexzero, leftPad } from '../util.js'; import { dBgS_GndChk } from './d_bg.js'; -import { fopAc_ac_c, fopAcM_prm_class } from './f_op_actor.js'; +import { dDemo_setDemoData } from './d_demo.js'; +import { LightType, dKy_tevstr_c, dKy_tevstr_init, setLightTevColorType, settingTevStruct } from './d_kankyo.js'; import { dProcName_e } from './d_procname.js'; +import { ResAssetType, ResEntry, ResType } from './d_resorce.js'; +import { fopAcM_prm_class, fopAc_ac_c } from './f_op_actor.js'; +import { cPhs__Status, fGlobals, fpcPf__RegisterFallback } from './framework.js'; import { mDoExt_McaMorf } from './m_do_ext.js'; -import { dDemo_setDemoData } from './d_demo.js'; -import { calc_mtx, mDoMtx_ZXYrotM, MtxTrans } from './m_do_mtx.js'; +import { MtxTrans, calc_mtx, mDoMtx_ZXYrotM } from './m_do_mtx.js'; +import { WindWakerRenderer, ZWWExtraTextures, dGlobals } from "./Main.js"; const scratchMat4a = mat4.create(); const scratchVec3a = vec3.create(); @@ -56,19 +54,46 @@ class d_a_noclip_legacy extends fopAc_ac_c { this.phase = cPhs__Status.Loading; spawnLegacyActor(globals, this, prm).then(() => { - this.phase = cPhs__Status.Next; + this.phase = this.finishLoading(globals); }); } return this.phase; } + private finishLoading(globals: dGlobals): cPhs__Status { + const baseObj = this.objectRenderers[0]; + if (baseObj === undefined) + return cPhs__Status.Stop; + + this.cullMtx = baseObj.modelMatrix; + + if (this.cullSizeSphere !== null && !Object.isFrozen(this.cullSizeSphere)) { + // Convert us to a box. + this.cullSizeSphere = null; + this.cullSizeBox = new AABB(); + } + + if (this.cullSizeBox !== null && !Object.isFrozen(this.cullSizeBox)) { + // Compute the cull box using only the parent. + this.cullSizeBox.copy(baseObj.modelInstance.modelData.bbox); + } + + return cPhs__Status.Next; + } + public override draw(globals: dGlobals, renderInstManager: GfxRenderInstManager, viewerInput: Viewer.ViewerRenderInput): void { + if (this.objectRenderers.length === 0) + return; + + if (!this.cullingCheck(viewerInput.camera)) + return; + const device = globals.modelCache.device; const dtFrames = Math.min(viewerInput.deltaTime / 1000 * 30, 5); const isDemoActor = dDemo_setDemoData(globals, dtFrames, this, 0x6A, this.morf); - if( isDemoActor ) { + if (isDemoActor) { MtxTrans(this.pos, false); mDoMtx_ZXYrotM(calc_mtx, this.rot); mat4.copy(this.objectRenderers[0].modelMatrix, calc_mtx); @@ -1786,8 +1811,6 @@ function spawnLegacyActor(globals: dGlobals, legacy: d_a_noclip_legacy, actor: f // Special-case actors -const bboxScratch = new AABB(); -const screenProjection = new ScreenSpaceProjection(); export class BMDObjectRenderer { public visible = true; public modelMatrix: mat4 = mat4.create(); @@ -1796,7 +1819,7 @@ export class BMDObjectRenderer { public tevstr = new dKy_tevstr_c(); private childObjects: BMDObjectRenderer[] = []; - private parentJointMatrix: mat4 | null = null; + public parentJointMatrix: mat4 | null = null; constructor(public modelInstance: J3DModelInstanceSimple) { } @@ -1846,13 +1869,6 @@ export class BMDObjectRenderer { mat4.mul(this.modelInstance.modelMatrix, this.parentJointMatrix, this.modelMatrix); } else { mat4.copy(this.modelInstance.modelMatrix, this.modelMatrix); - - // Don't compute screen area culling on child meshes (don't want heads to disappear before bodies.) - bboxScratch.transform(this.modelInstance.modelData.bbox, this.modelInstance.modelMatrix); - computeScreenSpaceProjectionFromWorldSpaceAABB(screenProjection, viewerInput.camera, bboxScratch); - - if (screenProjection.getScreenArea() <= 0.0002) - return; } mat4.getTranslation(scratchVec3a, this.modelMatrix); diff --git a/src/ZeldaWindWaker/f_op_actor.ts b/src/ZeldaWindWaker/f_op_actor.ts index 671ce5cbc..9f1b2fbe0 100644 --- a/src/ZeldaWindWaker/f_op_actor.ts +++ b/src/ZeldaWindWaker/f_op_actor.ts @@ -1,8 +1,8 @@ import { mat4, ReadonlyVec3, vec3, vec4 } from "gl-matrix"; import { AABB } from "../Geometry.js"; -import { Camera, computeScreenSpaceProjectionFromWorldSpaceAABB, computeScreenSpaceProjectionFromWorldSpaceSphere, ScreenSpaceProjection } from "../Camera.js"; -import { base_process_class, cPhs__Status, fGlobals, fopDwTg_DrawQTo, fopDwTg_ToDrawQ, fpcPc__IsVisible, fpcSCtRq_Request, leafdraw_class } from "./framework.js"; +import { Camera, calcScreenSpaceProjectionFromWorldSpaceAABB, ScreenSpaceProjection, calcScreenSpaceProjectionFromWorldSpaceSphere } from "../Camera.js"; +import { base_process_class, cPhs__Status, fGlobals, fopDwTg_DrawQTo, fopDwTg_ToDrawQ, fpcDt_Delete, fpcM_Management, fpcPc__IsVisible, fpcSCtRq_Request, leafdraw_class } from "./framework.js"; import { dKy_tevstr_c, dKy_tevstr_init } from "./d_kankyo.js"; import { dGlobals } from "./Main.js"; import { assert } from "../util.js"; @@ -122,7 +122,7 @@ export class fopAc_ac_c extends leafdraw_class { if (!frustum.contains(scratchAABB)) return false; - computeScreenSpaceProjectionFromWorldSpaceAABB(scratchScreenSpaceProjection, camera, scratchAABB); + calcScreenSpaceProjectionFromWorldSpaceAABB(scratchScreenSpaceProjection, camera, scratchAABB); if (scratchScreenSpaceProjection.getScreenArea() <= 0.0002) return false; } else if (this.cullSizeSphere !== null) { @@ -133,7 +133,7 @@ export class fopAc_ac_c extends leafdraw_class { if (!frustum.containsSphere(scratchVec3a, radius)) return false; - computeScreenSpaceProjectionFromWorldSpaceSphere(scratchScreenSpaceProjection, camera, scratchVec3a, radius); + calcScreenSpaceProjectionFromWorldSpaceSphere(scratchScreenSpaceProjection, camera, scratchVec3a, radius); if (scratchScreenSpaceProjection.getScreenArea() <= 0.0002) return false; } @@ -166,6 +166,10 @@ export interface fopAcM_prm_class { layer: number; } +export function fopAcM_delete(globals: fGlobals, ac: fopAc_ac_c): void { + return fpcDt_Delete(globals, ac); +} + export function fopAcM_create(globals: fGlobals, pcName: dProcName_e, parameters: number, pos: ReadonlyVec3 | null, roomNo: number, rot: ReadonlyVec3 | null, scale: ReadonlyVec3 | null, subtype: number, parentPcId: number): number | null { // Create on current layer. const prm: fopAcM_prm_class = { diff --git a/src/ZeldaWindWaker/framework.ts b/src/ZeldaWindWaker/framework.ts index cf2cc9502..1fe133aa0 100644 --- a/src/ZeldaWindWaker/framework.ts +++ b/src/ZeldaWindWaker/framework.ts @@ -46,6 +46,7 @@ export const enum cPhs__Status { Started, Loading, Next, + Stop, Complete, Error, } @@ -110,7 +111,7 @@ function fpcDt_Handler(globals: fGlobals, globalUserData: GlobalUserData): void globals.dtQueue.length = 0; } -function fpcDt_Delete(globals: fGlobals, pc: base_process_class): void { +export function fpcDt_Delete(globals: fGlobals, pc: base_process_class): void { fpcDt_ToDeleteQ(globals, pc); } @@ -181,6 +182,8 @@ export function fpcCt_Handler(globals: fGlobals, globalUserData: GlobalUserData) } else if (status === cPhs__Status.Error) { console.error(`Had error loading`); shouldDelete = true; + } else if (status === cPhs__Status.Stop) { + shouldDelete = true; } else if (status === cPhs__Status.Loading) { hadAnyLoading = true; }