protected override void setupScene() { base.setupScene(); laserOccDiskScene3d = new SSScene(mainShader, pssmShader, instancingShader, instancingPssmShader); laserFlareScene2d = new SSScene(mainShader, pssmShader, instancingShader, instancingPssmShader); var mesh = SSAssetManager.GetInstance <SSMesh_wfOBJ>("./drone2/Drone2.obj"); // add drones droneObj1 = new SSObjectMesh(mesh); droneObj1.Pos = new OpenTK.Vector3(-20f, 0f, -15f); droneObj1.Orient(Quaternion.FromAxisAngle(Vector3.UnitY, (float)Math.PI / 2f)); //droneObj1.renderState.visible = false; droneObj1.Name = "attacker drone"; main3dScene.AddObject(droneObj1); droneObj2 = new SSObjectMesh(mesh); droneObj2.Pos = new OpenTK.Vector3(20f, 0f, -15f); droneObj2.Name = "target drone"; droneObj2.MainColor = new Color4(1f, 0f, 0.7f, 1f); //droneObj2.renderState.visible = false; main3dScene.AddObject(droneObj2); // manages laser objects laserManager = new SLaserManager(alpha3dScene, laserOccDiskScene3d, laserFlareScene2d); // tweak the laser start point (by adding an offset in object-local coordinates) laserSourceTxfm = Matrix4.CreateTranslation(0f, 1f, 2.75f); // debugging snippets: //droneObj1.MainColor = Color4.Green; //droneObj1.renderState.visible = false; }
protected override void setupScene() { base.setupScene(); var droneMesh = SSAssetManager.GetInstance <SSMesh_wfOBJ> ("./drone2/Drone2.obj"); //var droneMesh = SSAssetManager.GetInstance<SSMesh_wfOBJ> ("missiles", "missile.obj"); var vandalMesh = SSAssetManager.GetInstance <SSMesh_wfOBJ> ("missiles/vandal_assembled.obj"); // add drones attackerDrone = new SSObjectMesh(droneMesh); attackerDrone.Pos = new OpenTK.Vector3(-20f, 0f, 0f); attackerDrone.Orient(Vector3.UnitX, Vector3.UnitY); attackerDrone.AmbientMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f); attackerDrone.DiffuseMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); attackerDrone.SpecularMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); attackerDrone.EmissionMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); attackerDrone.Name = "attacker drone"; main3dScene.AddObject(attackerDrone); targetDrone = new SSObjectMesh(droneMesh); targetDrone.Pos = new OpenTK.Vector3(200f, 0f, 0f); targetDrone.Orient(-Vector3.UnitX, Vector3.UnitY); targetDrone.AmbientMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f); targetDrone.DiffuseMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); targetDrone.SpecularMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); targetDrone.EmissionMatColor = new Color4(0.3f, 0.3f, 0.3f, 0.3f); targetDrone.Name = "target drone"; targetDrone.MainColor = new Color4(1f, 0f, 0.7f, 1f); main3dScene.AddObject(targetDrone); vandalShip = new SSObjectMesh(vandalMesh); vandalShip.Pos = new OpenTK.Vector3(100f, 0f, 0f); vandalShip.Scale = new Vector3(0.05f); vandalShip.AmbientMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f); vandalShip.DiffuseMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f); vandalShip.SpecularMatColor = new Color4(0.1f, 0.1f, 0.1f, 0.1f); vandalShip.EmissionMatColor = new Color4(0.0f, 0.0f, 0.0f, 0.0f); vandalShip.Name = "Vandal ship"; vandalShip.MainColor = new Color4(0.6f, 0.6f, 0.6f, 1f); //vandalShip.MainColor = new Color4(1f, 0f, 0.7f, 1f); //droneObj2.renderState.visible = false; vandalShip.Orient((targetDrone.Pos - vandalShip.Pos).Normalized(), Vector3.UnitY); main3dScene.AddObject(vandalShip); // shows explosions explosionManager = new SExplosionRenderManager(); explosionManager.particleSystem.doShockwave = false; explosionManager.particleSystem.doDebris = false; explosionManager.particleSystem.timeScale = 3f; //explosionManager.renderState.visible = false; alpha3dScene.AddObject(explosionManager); // attacker drone missile parameters attackerDroneFieldGen = new BodiesFieldGenerator( new ParticlesSphereGenerator(Vector3.Zero, 1f)); attackerDroneMissileParams = new SSpaceMissileVisualParameters(); // vandal missile params vandalShipFieldGen = new BodiesRingGenerator( new ParticlesOvalGenerator(1f, 1f), ringCenter: new Vector3(0f, 0f, 0f), up: Vector3.UnitZ, ringRadius: 80f, oriPolicy: BodiesFieldGenerator.OrientPolicy.None ); vandalShipMissileParams = new SSpaceMissileVisualParameters(); vandalShipMissileParams.ejectionMaxRotationVel = 0.05f; vandalShipMissileParams.ejectionVelocity = 30f; vandalShipMissileParams.pursuitActivationTime = 0.1f; vandalShipMissileParams.ejectionSmokeDuration = 0.5f; vandalShipMissileParams.ejectionSmokeSizeMax = 5f; cameraMissileParams = new SSpaceMissileVisualParameters(); //cameraMissileParams.spawnGenerator = null; //cameraMissileParams.spawnTxfm = straightMissileSpawnTxfm; cameraMissileParams.ejectionMaxRotationVel = 0.05f; cameraMissileParams.ejectionVelocity = 10f; // missile manager missileManager = new SSpaceMissilesRenderManager(main3dScene, alpha3dScene, hud2dScene); // additional statistics text missileStatsText = new SSObjectGDISurface_Text(); missileStatsText.alphaBlendingEnabled = true; missileStatsText.Label = "stats placeholder..."; missileStatsText.Pos = new Vector3(100f, 100f, 0f); //missileStatsText.Size = 20f; hud2dScene.AddObject(missileStatsText); var targetsManager = new SHudTargetsManager(main3dScene, hud2dScene); targetHud = targetsManager.addTarget( (o) => Color4.Red, _showDistanceFunc, (o) => o != null ? o.Name : "none", getTargetObject() ); }
protected void moveShips(float timeElapsed) { if (timeElapsed <= 0f) { return; } // make the target drone move from side to side localTime += timeElapsed; Vector3 pos = targetDrone.Pos; pos.Z = 30f * (float)Math.Sin(localTime); targetDrone.Pos = pos; // make the vandal ship orbit missile target Vector3 desiredPos; Vector3 desiredDir; float angle = localTime * 0.5f; float desiredXOffset = 100f * (float)Math.Cos(angle); float desiredYOffset = 20f * (float)Math.Sin(angle * 0.77f); float desiredZOffset = 80f * (float)Math.Sin(angle * 0.88f); Vector3 desiredOffset = new Vector3(desiredXOffset, desiredYOffset, desiredZOffset); var target = getTargetObject(); if (missileLauncher != MissileLaunchers.VandalShip || target == null || target == vandalShip) { desiredPos = new Vector3(100f, 0f, 0f); desiredDir = -Vector3.UnitX; } else if (target == main3dScene.ActiveCamera) { desiredPos = main3dScene.ActiveCamera.Pos + -main3dScene.ActiveCamera.Dir * 300f; Quaternion cameraOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, -main3dScene.ActiveCamera.Up); desiredPos += Vector3.Transform(desiredOffset * 0.1f, cameraOrient); desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } else { //float desiredZOffset = 5f * (float)Math.Sin(angle + 0.2f); desiredPos = target.Pos + desiredOffset; desiredDir = (target.Pos - vandalShip.Pos).Normalized(); } Vector3 desiredMotion = desiredPos - vandalShip.Pos; const float vel = 100f; float displacement = vel * timeElapsed; Vector3 vandalNewPos; if (displacement > desiredMotion.LengthFast) { vandalNewPos = desiredPos; } else { vandalNewPos = vandalShip.Pos + desiredMotion.Normalized() * displacement; } vandalVelocity = (vandalNewPos - vandalShip.Pos) / timeElapsed; vandalShip.Pos = vandalNewPos; Quaternion vandalOrient = OpenTKHelper.neededRotation(Vector3.UnitZ, desiredDir); vandalShip.Orient(desiredDir, Vector3.Transform(Vector3.UnitY, vandalOrient)); }
protected override void setupScene() { base.setupScene(); // checkerboard floor #if true { SSTexture tex = SSAssetManager.GetInstance <SSTexture> (".", "checkerboard.png"); const float tileSz = 4f; const int gridSz = 10; var tileVertices = new SSVertex_PosNormTex[SSTexturedNormalQuad.c_doubleFaceVertices.Length]; SSTexturedNormalQuad.c_doubleFaceVertices.CopyTo(tileVertices, 0); for (int v = 0; v < tileVertices.Length; ++v) { tileVertices[v].TexCoord *= (float)gridSz; } var quadMesh = new SSVertexMesh <SSVertex_PosNormTex>(tileVertices); quadMesh.textureMaterial = new SSTextureMaterial(tex); var tileObj = new SSObjectMesh(quadMesh); tileObj.Name = "Tiles"; tileObj.selectable = false; tileObj.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, (float)Math.PI / 2f)); tileObj.Scale = new Vector3(tileSz * gridSz); //tileObj.boundingSphere = new SSObjectSphere(0f); main3dScene.AddObject(tileObj); } #endif // skeleton mesh test #if true { SSSkeletalAnimation animIdle = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_idle.md5anim"); SSSkeletalAnimation animRunning = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_running.md5anim"); SSSkeletalAnimation animAttack = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>("./boneman", "boneman_attack.md5anim"); SSSkeletalMesh[] meshes = SSAssetManager.GetInstance <SSSkeletalMeshMD5[]>("./boneman", "boneman.md5mesh"); var tex = SSAssetManager.GetInstance <SSTexture>("./boneman", "skin.png"); foreach (var skeliMesh in meshes) { #if true var renderMesh0 = new SSSkeletalRenderMesh(skeliMesh); var obj0 = new SSObjectMesh(renderMesh0); obj0.MainColor = Color4.DarkGray; obj0.Name = "grey bones (bind pose)"; obj0.Pos = new Vector3(-18f, 0f, -18f); obj0.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); main3dScene.AddObject(obj0); tracker0 = new SSSimpleObjectTrackingJoint(obj0); tracker0.jointPositionLocal = animIdle.computeJointFrame(11, 0).position; tracker0.neutralViewOrientationLocal = animIdle.computeJointFrame(11, 0).orientation; tracker0.neutralViewDirectionBindPose = Vector3.UnitY; tracker0.neutralViewUpBindPose = Vector3.UnitZ; renderMesh0.addCustomizedJoint(11, tracker0); #endif #if true var renderMesh1 = new SSSkeletalRenderMesh(skeliMesh); var obj1 = new SSObjectMesh(renderMesh1); obj1.MainColor = Color4.DarkRed; obj1.Name = "red bones (running loop)"; obj1.Pos = new Vector3(6f, 0f, -12f); obj1.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); main3dScene.AddObject(obj1); renderMesh1.playAnimationLoop(animRunning, 0f); #endif #if true var renderMesh2 = new SSSkeletalRenderMesh(skeliMesh); renderMesh2.playAnimationLoop(animIdle, 0f, "all"); renderMesh2.playAnimationLoop(animRunning, 0f, "LeftClavicle", "RightClavicle"); var obj2 = new SSObjectMesh(renderMesh2); obj2.MainColor = Color.Green; obj2.Name = "green bones (idle + running loop mixed)"; obj2.Pos = new Vector3(0f, 0f, -12f); obj2.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); main3dScene.AddObject(obj2); #endif #if true var renderMesh3 = new SSSkeletalRenderMesh(skeliMesh); renderMesh3.playAnimationLoop(animIdle, 0f, "all"); var obj3 = new SSObjectMesh(renderMesh3); obj3.MainColor = Color.DarkCyan; obj3.Name = "blue bones (idle loop)"; obj3.Pos = new Vector3(-6f, 0f, -12f); obj3.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); main3dScene.AddObject(obj3); #endif // state machines setup for skeletal render mesh 4 and 5 var skeletonWalkDescr = new SSAnimationStateMachine(); skeletonWalkDescr.addState("idle", animIdle, true); skeletonWalkDescr.addState("running1", animRunning); skeletonWalkDescr.addState("running2", animRunning); skeletonWalkDescr.addAnimationEndsTransition("idle", "running1", 0.3f); skeletonWalkDescr.addAnimationEndsTransition("running1", "running2", 0f); skeletonWalkDescr.addAnimationEndsTransition("running2", "idle", 0.3f); var skeletonAttackDescr = new SSAnimationStateMachine(); skeletonAttackDescr.addState("inactive", null, true); skeletonAttackDescr.addState("attack", animAttack); skeletonAttackDescr.addStateTransition(null, "attack", 0.5f); skeletonAttackDescr.addAnimationEndsTransition("attack", "inactive", 0.5f); #if true // state machine test (in slow motion) var renderMesh4 = new SSSkeletalRenderMesh(skeliMesh); renderMesh4.timeScale = 0.25f; var obj4 = new SSObjectMesh(renderMesh4); obj4.MainColor = Color.DarkMagenta; obj4.Name = "magenta bones (looping idle/walk; interactive attack; slowmo)"; obj4.Pos = new Vector3(-12f, 0f, 0f); obj4.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); main3dScene.AddObject(obj4); var renderMesh4WallSm = renderMesh4.addStateMachine(skeletonWalkDescr, "all"); renderMesh4AttackSm = renderMesh4.addStateMachine(skeletonAttackDescr, "LeftClavicle", "RightClavicle"); tracker4 = new SSSimpleObjectTrackingJoint(obj4); tracker4.jointPositionLocal = animRunning.computeJointFrame(11, 0).position; tracker4.neutralViewOrientationLocal = animRunning.computeJointFrame(11, 0).orientation; tracker4.neutralViewDirectionBindPose = Vector3.UnitY; renderMesh4.addCustomizedJoint(11, tracker4); #endif #if true // another mesh, using the same state machine but running at normal speed var renderMesh5 = new SSSkeletalRenderMesh(skeliMesh); var renderMesh5WalkSm = renderMesh5.addStateMachine(skeletonWalkDescr, "all"); renderMesh5AttackSm = renderMesh5.addStateMachine(skeletonAttackDescr, "LeftClavicle", "RightClavicle"); var obj5 = new SSObjectMesh(renderMesh5); obj5.Name = "orange bones (looping idle/walk, interactive attack + parametric neck rotation)"; obj5.Pos = new Vector3(12f, 0f, 0f); obj5.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); obj5.MainColor = Color4.DarkOrange; main3dScene.AddObject(obj5); renderMesh5NeckJoint = new SSPolarJoint(); renderMesh5NeckJoint.positionOffset = new Vector3(0f, 0.75f, 0f); renderMesh5.addCustomizedJoint("UpperNek", renderMesh5NeckJoint); #endif } } #endif #if true // bob mesh test { var bobMeshes = SSAssetManager.GetInstance <SSSkeletalMeshMD5[]>( "./bob_lamp/", "bob_lamp_update.md5mesh"); var bobAnim = SSAssetManager.GetInstance <SSSkeletalAnimationMD5>( "./bob_lamp/", "bob_lamp_update.md5anim"); var bobRender = new SSSkeletalRenderMesh(bobMeshes); bobRender.playAnimationLoop(bobAnim, 0f); bobRender.alphaBlendingEnabled = true; bobRender.timeScale = 0.5f; var bobObj = new SSObjectMesh(bobRender); bobObj.Name = "Bob"; bobObj.Pos = new Vector3(10f, 0f, 10f); bobObj.Orient(Quaternion.FromAxisAngle(Vector3.UnitX, -(float)Math.PI / 2f)); alpha3dScene.AddObject(bobObj); } #endif }
public void preRenderUpdate(float timeElapsed) { bool visible = (targetObj != null); _outline.renderState.visible = visible; _labelBelow.renderState.visible = visible; _labelAbove.renderState.visible = visible; if (!visible) { return; } RectangleF clientRect = OpenTKHelper.GetClientRect(); var targetRc = _targetObj3dScene.renderConfig; Matrix4 targetViewProj = targetRc.invCameraViewMatrix * targetRc.projectionMatrix; // outline Quaternion viewRotOnly = targetRc.invCameraViewMatrix.ExtractRotation(); Quaternion viewRotInverted = viewRotOnly.Inverted(); Vector3 viewRight = Vector3.Transform(Vector3.UnitX, viewRotInverted).Normalized(); Vector3 viewUp = Vector3.Transform(Vector3.UnitY, viewRotInverted).Normalized(); Vector2 targetScreenPos = OpenTKHelper.WorldToScreen(targetObj.Pos, ref targetViewProj, ref clientRect); targetScreenPos.X = (float)Math.Round(targetScreenPos.X); // fixes off-by-one pixel jitter targetScreenPos.Y = (float)Math.Round(targetScreenPos.Y); // animate outline line stipple _outline.enableLineStipple = this.isSelected; if (_outline.enableLineStipple) { ushort stipplePattern = _outline.lineStipplePattern; _stippleTimeAccumulator += timeElapsed; while (_stippleTimeAccumulator >= stippleStepInterval) { ushort firstBit = (ushort)((uint)stipplePattern & 0x1); stipplePattern >>= 1; stipplePattern |= (ushort)((uint)firstBit << 15); _outline.lineStipplePattern = stipplePattern; _stippleTimeAccumulator -= stippleStepInterval; } } float outlineHalfWidth; float outlineHalfHeight; if (fixedSizeTargets) { outlineHalfWidth = outlineMinPixelSz; outlineHalfHeight = outlineMinPixelSz; } else { // assumes target is a convential SSObject without billboarding, match scale to screen, etc. var size = targetObj.worldBoundingSphereRadius; Vector3 targetRightMost = targetObj.Pos + viewRight * size; Vector3 targetTopMost = targetObj.Pos + viewUp * size; Vector2 screenRightMostPt = OpenTKHelper.WorldToScreen(targetRightMost, ref targetViewProj, ref clientRect); Vector2 screenTopMostPt = OpenTKHelper.WorldToScreen(targetTopMost, ref targetViewProj, ref clientRect); outlineHalfWidth = 2f * (screenRightMostPt.X - targetScreenPos.X); outlineHalfWidth = Math.Max(outlineHalfWidth, outlineMinPixelSz); outlineHalfHeight = 2f * (targetScreenPos.Y - screenTopMostPt.Y); outlineHalfHeight = Math.Max(outlineHalfHeight, outlineMinPixelSz); } Vector3 targetViewPos = Vector3.Transform(targetObj.Pos, targetRc.invCameraViewMatrix); _targetViewDepth = targetViewPos.Z; bool targetIsInFront = _targetViewDepth < 0f; float lineWidth = targetIsInFront ? outlineWidthWhenInFront : outlinelineWidthWhenBehind; bool above, below, left, right; if (targetIsInFront) { left = targetScreenPos.X + outlineHalfWidth < 0f; right = !left && targetScreenPos.X - outlineHalfWidth > clientRect.Width; above = targetScreenPos.Y + outlineHalfHeight < 0f; below = !above && targetScreenPos.Y + outlineHalfHeight > clientRect.Height; } else // target is behind { float halfScrWidth = clientRect.Width / 2f; float halfScrHeight = clientRect.Height / 2f; float quartScrWidth = halfScrWidth / 2f; float quartScrHeight = halfScrHeight / 2f; right = targetScreenPos.X < quartScrWidth; left = !right && targetScreenPos.X > halfScrWidth + quartScrWidth; below = targetScreenPos.Y < quartScrHeight; above = !below && targetScreenPos.Y > halfScrHeight + quartScrHeight; } int orientIdx = (above ? 1 : 0) + (below ? 2 : 0) + (left ? 4 : 0) + (right ? 8 : 0); bool inTheCenter = (orientIdx == 0); if (!inTheCenter) { outlineHalfWidth = outlineMinPixelSz; outlineHalfHeight = outlineMinPixelSz; if (left) { targetScreenPos.X = outlineHalfWidth; } else if (right) { targetScreenPos.X = clientRect.Width - outlineHalfWidth - lineWidth * 2f; } if (above) { targetScreenPos.Y = outlineHalfHeight + _labelAbove.getGdiSize.Height; } else if (below) { targetScreenPos.Y = clientRect.Height - outlineHalfHeight - _labelBelow.getGdiSize.Height; } } _outline.Mesh = inTheCenter ? (targetIsInFront ? hudRectLinesMesh : hudCircleMesh) : hudTriMesh; _outline.Scale = new Vector3(outlineHalfWidth, outlineHalfHeight, 1f); _outline.Orient(outlineOrients [orientIdx]); _outline.Pos = new Vector3(targetScreenPos.X, targetScreenPos.Y, +1f); // labels _labelBelow.Label = fetchTextBelow(targetObj); var labelBelowPos = targetScreenPos; if (left) { labelBelowPos.X = 0f; } else if (right) { labelBelowPos.X = clientRect.Width - _labelBelow.getGdiSize.Width - 10f; } else { labelBelowPos.X -= _labelBelow.getGdiSize.Width / 2f; } labelBelowPos.Y += outlineHalfHeight; if ((left || right) && !below) { labelBelowPos.Y += outlineHalfHeight; } _labelBelow.Pos = new Vector3(labelBelowPos.X, labelBelowPos.Y, 0f); _labelAbove.Label = fetchTextAbove(targetObj); var labelAbovePos = targetScreenPos; if (left) { labelAbovePos.X = 0f; } else if (right) { labelAbovePos.X = clientRect.Width - _labelAbove.getGdiSize.Width - 10f; } else { labelAbovePos.X -= _labelAbove.getGdiSize.Width / 2f; } if ((left || right) && !above) { labelAbovePos.Y -= outlineHalfHeight; } labelAbovePos.Y -= (outlineHalfHeight + _labelAbove.getGdiSize.Height); _labelAbove.Pos = new Vector3(labelAbovePos.X, labelAbovePos.Y, 0f); Color4 color = fetchColor(targetObj); _outline.MainColor = color; _labelBelow.MainColor = color; _labelAbove.MainColor = color; _outlineScreenRect = new Rectangle( (int)(targetScreenPos.X - outlineHalfWidth), (int)(targetScreenPos.Y - outlineHalfHeight), (int)(outlineHalfWidth * 2f), (int)(outlineHalfHeight * 2f) ); }