public void Render(IGameViewport viewport, IAnimatedModel model, AnimatedModelParams animParams, IList <Light3d> lights, MdfRenderOverrides materialOverrides = null) { var renderData = GetOrCreateState(model); var materialIds = model.GetSubmeshes(); for (var i = 0; i < materialIds.Length; ++i) { var material = materialIds[i]; var submesh = animParams.rotation3d ? model.GetSubmeshForParticles(animParams, i) : model.GetSubmesh(animParams, i); // Usually this should not happen, since it means there's // an unbound replacement material if (material == null) { continue; } material.Bind(viewport, mDevice, lights, materialOverrides); // Do we have to recalculate the normals? if (material.GetSpec().recalculateNormals) { RecalcNormals( submesh.VertexCount, submesh.Positions, submesh.Normals, submesh.PrimitiveCount, submesh.Indices ); } var submeshData = GetSubmeshData(renderData, i, submesh); submeshData.binding.Resource.Bind(); mDevice.SetIndexBuffer(submeshData.idxBuffer); mDevice.DrawIndexed(PrimitiveType.TriangleList, submesh.VertexCount, submesh.PrimitiveCount * 3); } }
public static AnimatedModelParams GetAnimParams(this GameObject obj) { var result = new AnimatedModelParams(); result.scale = obj.GetScalePercent() / 100.0f; // Special case for equippable items if (obj.type.IsEquipment()) { var itemFlags = obj.GetItemFlags(); if (itemFlags.HasFlag(ItemFlag.DRAW_WHEN_PARENTED)) { var parent = GameSystems.Item.GetParent(obj); if (parent != null) { result.scale *= parent.GetScalePercent() / 100.0f; result.attachedBoneName = GameSystems.Item.GetAttachBone(obj); if (result.attachedBoneName != null) { var parentLoc = parent.GetLocationFull(); result.x = parentLoc.location.locx; result.y = parentLoc.location.locy; result.offsetX = parentLoc.off_x; result.offsetY = parentLoc.off_y; var parentDepth = GameSystems.Height.GetDepth(parentLoc); var offsetZ = parent.OffsetZ; result.offsetZ = offsetZ - parentDepth; result.rotation = parent.Rotation; result.rotationPitch = parent.RotationPitch; result.parentAnim = parent.GetOrCreateAnimHandle(); return(result); } } } } var loc = obj.GetLocationFull(); result.x = loc.location.locx; result.y = loc.location.locy; result.offsetX = loc.off_x; result.offsetY = loc.off_y; var flags = obj.GetFlags(); sbyte depth = 0; if (!flags.HasFlag(ObjectFlag.NOHEIGHT)) { depth = GameSystems.Height.GetDepth(loc); } result.offsetZ = obj.OffsetZ - depth; result.rotation = obj.Rotation; result.rotationPitch = obj.RotationPitch; return(result); }
// TODO: Separate logic+rendering public void AdvanceAndRender( IGameViewport viewport, GameObject giantFrog, AnimatedModelParams animParams, IAnimatedModel model, IList <Light3d> lights, float alpha) { var grappleState = GetGrappleState(giantFrog); if (grappleState.state == 0) { return; } model.GetBoneWorldMatrixByName(animParams, "Tongue_Ref", out var worldMatrixFrog); var grappledOpponent = GetGrappledOpponent(giantFrog); float tongueLength, tonguePosX, tonguePosZ; if (grappledOpponent != null) { var opponentModel = grappledOpponent.GetOrCreateAnimHandle(); var opponentAnimParams = grappledOpponent.GetAnimParams(); opponentModel.GetBoneWorldMatrixByName(opponentAnimParams, "Bip01 Spine1", out var worldMatrixOpponent); tonguePosX = worldMatrixOpponent.M41; tonguePosZ = worldMatrixOpponent.M43; var tongueDirX = worldMatrixOpponent.M41 - worldMatrixFrog.M41; var tongueDirY = worldMatrixOpponent.M42 - worldMatrixFrog.M42; var tongueDirZ = worldMatrixOpponent.M43 - worldMatrixFrog.M43; tongueLength = MathF.Sqrt(tongueDirX * tongueDirX + tongueDirY * tongueDirY + tongueDirZ * tongueDirZ); worldMatrixFrog.M31 = tongueDirX / tongueLength; worldMatrixFrog.M32 = tongueDirY / tongueLength; worldMatrixFrog.M33 = tongueDirZ / tongueLength; if (tongueLength > 0) { tongueLength -= 6.0f; } } else { tongueLength = 120.0f; tonguePosX = worldMatrixFrog.M31 * 120.0f + worldMatrixFrog.M41; tonguePosZ = worldMatrixFrog.M33 * 120.0f + worldMatrixFrog.M43; } switch (grappleState.state) { // This state seems to mean . Extending tongue to full length case 1: grappleState.currentLength += locXY.INCH_PER_TILE; if (grappleState.currentLength > tongueLength) { grappleState.state = 2; grappleState.currentLength = tongueLength; } break; // This state seems to mean . Retracting tongue case 2: grappleState.currentLength -= locXY.INCH_PER_TILE; if (grappleState.currentLength <= 0) { grappleState.state = 0; grappleState.currentLength = 0; } break; case 3: grappleState.currentLength += locXY.INCH_PER_TILE; if (grappleState.currentLength > tongueLength) { grappleState.state = 4; grappleState.currentLength = tongueLength; var frogAnim = GameSystems.Critter.GetAnimId(giantFrog, WeaponAnim.Special2); giantFrog.SetAnimId(frogAnim); var opponentAnim = GameSystems.Critter.GetAnimId(grappledOpponent, WeaponAnim.Panic); grappledOpponent.SetAnimId(opponentAnim); } break; case 4: // Maintain Tongue between frog and opponent without progressing grappleState.currentLength = tongueLength; break; case 5: case 6: { if (grappleState.state == 5) { grappleState.targetLength = tongueLength - 12.0f; if (grappleState.targetLength < 0) { grappleState.targetLength = 0; } grappleState.state = 6; } grappleState.currentLength = grappleState.currentLength - locXY.INCH_PER_HALFTILE; // Move the opponent closer to the frog float newX = tonguePosX - worldMatrixFrog.M31 * locXY.INCH_PER_HALFTILE; float newZ = tonguePosZ - worldMatrixFrog.M33 * locXY.INCH_PER_HALFTILE; var newLoc = LocAndOffsets.FromInches(newX, newZ); GameSystems.MapObject.Move(grappledOpponent, newLoc); if (grappleState.currentLength < grappleState.targetLength) { newX = worldMatrixFrog.M41 + grappleState.targetLength * worldMatrixFrog.M31; newZ = worldMatrixFrog.M43 + grappleState.targetLength * worldMatrixFrog.M33; newLoc = LocAndOffsets.FromInches(newX, newZ); GameSystems.MapObject.Move(grappledOpponent, newLoc); grappleState.currentLength = grappleState.targetLength; grappleState.state = 4; } } break; case 7: { grappleState.currentLength = grappleState.currentLength - locXY.INCH_PER_HALFTILE; // Move the opponent closer to the frog float newX = tonguePosX - worldMatrixFrog.M31 * locXY.INCH_PER_HALFTILE; float newZ = tonguePosZ - worldMatrixFrog.M33 * locXY.INCH_PER_HALFTILE; var newLoc = LocAndOffsets.FromInches(newX, newZ); GameSystems.MapObject.Move(grappledOpponent, newLoc); if (grappleState.currentLength < 0) { newX = worldMatrixFrog.M41; newZ = worldMatrixFrog.M43; newLoc = LocAndOffsets.FromInches(newX, newZ); GameSystems.MapObject.Move(grappledOpponent, newLoc); GameSystems.ObjFade.FadeTo(grappledOpponent, 0, 0, 16, 0); grappleState.currentLength = 0; grappleState.state = 0; // Probably the swallow animation var animId = GameSystems.Critter.GetAnimId(giantFrog, WeaponAnim.Special3); giantFrog.SetAnimId(animId); } } break; default: break; } // Update to the new grapple state SetGrappleState(giantFrog, grappleState); // The directional vector of the tongue ref point on the frog var tongueUp = worldMatrixFrog.GetRow(0).ToVector3(); var tongueRight = worldMatrixFrog.GetRow(1).ToVector3(); var tongueDir = worldMatrixFrog.GetRow(2).ToVector3(); var tonguePos = worldMatrixFrog.GetRow(3).ToVector3(); RenderTongue(viewport, grappleState, tongueDir, tongueUp, tongueRight, tonguePos, lights, alpha); }