public void PrepareCache(MyVoxelVertex[] vertices, int vertexCount, MyVoxelTriangle[] triangles, int triangleCount) { lock (m_syncRoot) { if (vertexCount == 0) { VoxelVerticesCount = 0; VoxelTrianglesCount = 0; m_octree = null; VoxelVertices = null; return; } MyCommonDebugUtils.AssertDebug(vertexCount <= Int16.MaxValue); MyRender.GetRenderProfiler().StartProfilingBlock("build octree"); if (m_octree == null) { m_octree = new MyOctree(); } m_octree.Init(ref vertices, ref vertexCount, ref triangles, ref triangleCount, out VoxelTriangles); MyRender.GetRenderProfiler().EndProfilingBlock(); // copy voxel vertices VoxelVertices = new MyVoxelVertex[vertexCount]; for (int i = 0; i < vertexCount; i++) { VoxelVertices[i] = vertices[i]; } // set size only after the arrays are fully allocated VoxelVerticesCount = vertexCount; VoxelTrianglesCount = triangleCount; } }
/// <summary> /// Renders the shadow map using the orthographic camera created in /// CalculateFrustum. /// </summary> /// <param name="modelList">The list of models to be rendered</param> protected void RenderShadowMap(int splitIndex) { PrepareViewportForCascade(splitIndex); // Set up the effect MyEffectShadowMap shadowMapEffect = MyRender.GetEffect(MyEffects.ShadowMap) as Effects.MyEffectShadowMap; shadowMapEffect.SetDitheringTexture((SharpDX.Direct3D9.Texture)MyTextureManager.GetTexture <MyTexture2D>(@"Textures\Models\Dither.png")); shadowMapEffect.SetHalfPixel(MyShadowRenderer.NumSplits * MyRender.GetShadowCascadeSize(), MyRender.GetShadowCascadeSize()); // Clear shadow map shadowMapEffect.SetTechnique(MyEffectShadowMap.ShadowTechnique.Clear); MyRender.GetFullscreenQuad().Draw(shadowMapEffect); shadowMapEffect.SetViewProjMatrix((Matrix)m_lightCameras[splitIndex].ViewProjMatrixAtZero); MyRender.GetRenderProfiler().StartProfilingBlock("draw elements"); // Draw the models DrawElements(m_lightCameras[splitIndex].CastingRenderElements, shadowMapEffect, true, m_lightCameras[splitIndex].WorldMatrix.Translation, splitIndex, true); m_lightCameras[splitIndex].CastingRenderElements.Clear(); MyRender.GetRenderProfiler().EndProfilingBlock(); }
private void UpdateOcclusion(float querySize) { MyRender.GetRenderProfiler().StartProfilingBlock("update occ 1"); UpdateGpuOcclusion(querySize); MyRender.GetRenderProfiler().EndProfilingBlock(); }
public void WaitUntilPrepareForDrawCompleted() { MyRender.GetRenderProfiler().StartProfilingBlock("WaitUntilPrepareForDrawCompleted"); m_prepareForDrawTask.Wait(); MyRender.GetRenderProfiler().EndProfilingBlock(); }
// Blends-out triangles affected by explosion (radius + some safe delta). Triangles there have zero alpha are flaged to not-draw at all. public static void HideTrianglesAfterExplosion(MyVoxelMap voxelMap, ref BoundingSphere explosionSphere) { MyRender.GetRenderProfiler().StartProfilingBlock("MyDecals::HideTrianglesAfterExplosion"); MyMwcVector3Int renderCellCoord = voxelMap.GetVoxelRenderCellCoordinateFromMeters(ref explosionSphere.Center); m_decalsForVoxels.HideTrianglesAfterExplosion(voxelMap.VoxelMapId, ref renderCellCoord, ref explosionSphere); MyRender.GetRenderProfiler().EndProfilingBlock(); }
protected override bool BeginDraw() { MyRender.GetRenderProfiler().StartProfilingBlock("BeginDraw"); bool ret = base.BeginDraw(); MyRender.GetRenderProfiler().EndProfilingBlock(); return(ret); }
public static void LoadData() { MyRender.GetRenderProfiler().StartProfilingBlock("MyLights.LoadData"); MyRender.Log.WriteLine("MyLights.LoadData() - START"); MyRender.Log.IncreaseIndent(); MyRender.Log.DecreaseIndent(); MyRender.Log.WriteLine("MyLights.LoadData() - END"); MyRender.GetRenderProfiler().EndProfilingBlock(); }
public static void LoadData() { MyRender.GetRenderProfiler().StartProfilingBlock("MyParticlesDustField.LoadData"); MyMwcLog.WriteLine("MyParticlesDustField.LoadContent() - START"); MyMwcLog.IncreaseIndent(); MyMwcLog.DecreaseIndent(); MyMwcLog.WriteLine("MyParticlesDustField.LoadContent() - END"); MyRender.GetRenderProfiler().EndProfilingBlock(); }
private void IssueOcclusionQuery(MyOcclusionQuery query, bool depthTest) { MyRender.GetRenderProfiler().StartProfilingBlock("Issue query"); BlendState previousBlendState = BlendState.Current;; MyStateObjects.DisabledColorChannels_BlendState.Apply(); RasterizerState.CullNone.Apply(); DepthStencilState.None.Apply(); query.Begin(); //generate and draw bounding box of our renderCell in occlusion query MyDebugDraw.DrawOcclusionBoundingBox(m_occlusionBox, 1.0f, depthTest); previousBlendState.Apply(); query.End(); MyRender.GetRenderProfiler().EndProfilingBlock(); }
public void UpdateFace(Vector3 position, int faceIndex) { // SetRenderSetup(); CubeMapFace face = (CubeMapFace)faceIndex; // New setup m_setup.CameraPosition = position; m_setup.AspectRatio = 1.0f; m_setup.Viewport = new Viewport(0, 0, (int)m_environmentRT.GetLevelDescription(0).Width, (int)m_environmentRT.GetLevelDescription(0).Width); m_setup.ViewMatrix = CreateViewMatrix(face, position); m_setup.Fov = MathHelper.PiOver2; m_setup.ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(m_setup.Fov.Value, m_setup.AspectRatio.Value, NearClip, m_setup.LodTransitionBackgroundEnd.Value); m_setup.DepthToAlpha = true; MyRender.GetRenderProfiler().StartProfilingBlock("Draw environmental maps"); MyRender.PushRenderSetupAndApply(m_setup, ref m_backup); MyRender.Draw(false); MyRender.GetRenderProfiler().EndProfilingBlock(); Surface cubeSurface = m_environmentRT.GetCubeMapSurface(face, 0); MyMinerGame.Static.GraphicsDevice.SetRenderTarget(0, cubeSurface); var screenEffect = MyRender.GetEffect(MyEffects.Screenshot) as MyEffectScreenshot; screenEffect.SetTechnique(MyEffectScreenshot.ScreenshotTechniqueEnum.Default); screenEffect.SetSourceTexture(m_fullSizeRT); screenEffect.SetScale(new Vector2(m_environmentRT.GetLevelDescription(0).Width / (float)m_fullSizeRT.GetLevelDescription(0).Width * 0.968f, 0.982f * m_environmentRT.GetLevelDescription(0).Width / (float)m_fullSizeRT.GetLevelDescription(0).Height)); MyGuiManager.GetFullscreenQuad().Draw(screenEffect); screenEffect.SetScale(new Vector2(1, 1)); cubeSurface.Dispose(); MyRender.PopRenderSetupAndRevert(m_backup); }
public void IssueOcclusionQueries() { if (!EnableLightGlares) { return; } System.Diagnostics.Debug.Assert(QuerySize > 0); Vector3D position = this.Position; Vector3D cameraToLight = MyRenderCamera.Position - position; var distance = cameraToLight.Length(); const float maxDistance = MyRenderConstants.MAX_GPU_OCCLUSION_QUERY_DISTANCE; bool canBeDiscardedIfTooFar = Type != MyGlareTypeEnum.Distant; if (canBeDiscardedIfTooFar && distance > maxDistance) { return; } if (UseOcclusionQuery) { //float querySizeMultiplier = distance < maxDistance ? 1 : distance / maxDistance; float querySizeMultiplier = 0.2f; bool isFar = distance > maxDistance; // Occlusion is calculated only when closer than 200m, further visibility is handled by depth test if (!isFar) { MyRender.GetRenderProfiler().StartProfilingBlock("Light glare update occlusion"); UpdateOcclusion(querySizeMultiplier * QuerySize); MyRender.GetRenderProfiler().EndProfilingBlock(); } } }
protected override void EndDraw() { MyRender.GetRenderProfiler().StartProfilingBlock("EndDraw"); base.EndDraw(); MyRender.GetRenderProfiler().EndProfilingBlock(); }
/// <summary> /// Updates resource. /// </summary> public override void UpdateBeforeSimulation() { try { MyRender.GetRenderProfiler().StartProfilingBlock("MyMissile.UpdateBeforeSimulation"); //Large ship weapons wont make bots curious if ((!(OwnerEntity is MyLargeShipMissileLauncherBarrel)) && MyMwcUtils.HasValidLength(this.WorldMatrix.Translation - m_previousPosition)) { MyLine line = new MyLine(this.WorldMatrix.Translation, m_previousPosition); MyDangerZones.Instance.Notify(line, OwnerEntity); } if (m_isExploded) { // Create explosion MyExplosion newExplosion = MyExplosions.AddExplosion(); if (newExplosion != null) { float radius = m_ammoProperties.ExplosionRadius; // Explicitly on Marek's request (ticket 4740) bool amplifyRadius = m_collidedEntity != null?MyFactions.GetFactionsRelation(m_collidedEntity.Faction, Faction) != MyFactionRelationEnum.Friend : false; if (amplifyRadius) { radius *= 2; } BoundingSphere explosionSphere = new BoundingSphere(m_collisionPoint.HasValue ? m_collisionPoint.Value : GetPosition(), radius); // Call main explosion starter MyExplosionInfo info = new MyExplosionInfo() { PlayerDamage = m_ammoProperties.HealthDamage, Damage = m_ammoProperties.ShipDamage, EmpDamage = m_ammoProperties.EMPDamage, ExplosionType = m_explosionType, ExplosionSphere = explosionSphere, LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN, ExplosionForceDirection = MyExplosionForceDirection.EXPLOSION, GroupMask = Physics.GroupMask, CascadeLevel = CascadedExplosionLevel, HitEntity = m_collidedEntity, ParticleScale = 1.5f, OwnerEntity = this.OwnerEntity, Direction = WorldMatrix.Forward, VoxelExplosionCenter = explosionSphere.Center + m_ammoProperties.ExplosionRadius * WorldMatrix.Forward * 0.5f, ExplosionFlags = MyExplosionFlags.AFFECT_VOXELS | MyExplosionFlags.APPLY_FORCE_AND_DAMAGE | MyExplosionFlags.CREATE_DEBRIS | MyExplosionFlags.CREATE_DECALS | MyExplosionFlags.CREATE_PARTICLE_EFFECT, VoxelCutoutScale = amplifyRadius ? 0.5f : 1.0f, PlaySound = true, }; newExplosion.Start(ref info); } if (m_collidedEntity != null && !m_collidedEntity.IsExploded()) { m_collidedEntity.Physics.AddForce( MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, WorldMatrix.Forward * MyMissileConstants.HIT_STRENGTH_IMPULSE, GetPosition() + MyMwcUtils.GetRandomVector3Normalized() * 2, MyMissileConstants.HIT_STRENGTH_IMPULSE * MyMwcUtils.GetRandomVector3Normalized()); m_collidedEntity.OnClose -= m_collidedEntity_OnClose; } MarkForClose(); return; } bool firstTargetting = m_elapsedMiliseconds == 0; base.UpdateBeforeSimulation(); m_missileTargetUpdate += MyConstants.PHYSICS_STEP_SIZE_IN_MILLISECONDS; if (m_missileTargetUpdate >= MyGuidedMissileConstants.MISSILE_TARGET_UPDATE_INTERVAL_IN_MS || firstTargetting) { m_missileTargetUpdate = 0; switch (m_missileType) { case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Radar_Detection: { MySmallShip targetShip = m_targetEntity as MySmallShip; if (targetShip != null && targetShip.IsRadarJammed()) { m_targetEntity = null; } } break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Engine_Detection: { m_targetEntities.Clear(); Matrix proj = Matrix.CreateOrthographic(MyGuidedMissileConstants.ENGINE_GUIDED_MISSILE_RADIUS, MyGuidedMissileConstants.ENGINE_GUIDED_MISSILE_RADIUS, 0, 1000); Matrix view = Matrix.CreateLookAt(GetPosition(), GetPosition() + WorldMatrix.Forward, WorldMatrix.Up); m_visualFrustum.Matrix = view * proj; MyEntities.GetAllIntersectionWithBoundingFrustum(ref m_visualFrustum, m_targetEntities); if (m_targetEntities.Contains(m_targetEntity)) { break; } MyEntity target = null; float closestToMissileDirection = float.MaxValue; foreach (MyEntity entity in m_targetEntities) { if (CanTarget(entity)) { MySmallShip targetShip = entity as MySmallShip; if (targetShip != null) { if ((targetShip.IsEngineTurnedOff())) { continue; } } Vector3 targetPos = entity.GetPosition(); Vector3 missilePos = this.GetPosition(); Vector3 missilePosEnd = this.GetPosition() + this.WorldMatrix.Forward * 10000; Vector3 closestPos = MyUtils.GetClosestPointOnLine(ref missilePos, ref missilePosEnd, ref targetPos); float distance = Vector3.Distance(closestPos, targetPos); if (distance < closestToMissileDirection) { closestToMissileDirection = distance; target = entity; } } } UpdateTarget(target); } break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Visual_Detection: { Matrix projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(MyGuidedMissileConstants.VISUAL_GUIDED_MISSILE_FOV), 1, 10, MyGuidedMissileConstants.VISUAL_GUIDED_MISSILE_RANGE); m_visualFrustum.Matrix = Matrix.Invert(WorldMatrix) * projectionMatrix; m_targetEntities.Clear(); MyEntities.GetAllIntersectionWithBoundingFrustum(ref m_visualFrustum, m_targetEntities); int testsLimit = 8; if (m_targetEntities.Contains(m_targetEntity)) { break; } MyEntity target = null; //looks better if missile gets "lost" float closestToMissileDirection = float.MaxValue; foreach (MyEntity entity in m_targetEntities) { if (!CanTarget(entity)) { continue; } if (testsLimit-- == 0) { break; } if (MyEnemyTargeting.CanSee(this, entity) == null) { Vector3 targetPos = entity.GetPosition(); Vector3 missilePos = this.GetPosition(); Vector3 missilePosEnd = this.GetPosition() + this.WorldMatrix.Forward * 10000; Vector3 closestPos = MyUtils.GetClosestPointOnLine(ref missilePos, ref missilePosEnd, ref targetPos); float distance = Vector3.Distance(closestPos, targetPos); if (distance < closestToMissileDirection) { closestToMissileDirection = distance; target = entity; } } } UpdateTarget(target); } break; } } if ((m_initTime - m_elapsedMiliseconds) > 0) { //simulating missile launch and engine ignition MyEntity owner = OwnerEntity; if (owner != null) { Vector3 transformedInitDir = Vector3.TransformNormal(m_initDir, owner.WorldMatrix); // Vector3 initialVelocity = Vector3.Zero; if (owner.Physics != null) { initialVelocity = owner.Physics.LinearVelocity; } Physics.LinearVelocity = transformedInitDir * m_ammoProperties.InitialSpeed + initialVelocity; } } else { // This will help blend "initial velocity" and "thrust velocity" so at the beginning missile is powered by initiatal velocity only, but later float velocityBlend = MathHelper.Clamp((float)(m_elapsedMiliseconds - m_initTime) / m_blendVelocities, 0, 1); if (velocityBlend == 1.0f) { m_actualSpeed = m_ammoProperties.DesiredSpeed; } else { float initialSpeed = 0.0f; MyEntity owner = OwnerEntity; if (owner != null) { if (owner.Physics != null) { initialSpeed = owner.Physics.LinearVelocity.Length(); } } m_actualSpeed = velocityBlend * m_ammoProperties.DesiredSpeed + ((1.0f - velocityBlend) * (m_ammoProperties.InitialSpeed + initialSpeed)); if (m_missileType != MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_Basic && m_smokeEffect == null) { // if (MyCamera.GetDistanceWithFOV(GetPosition()) < 150) { /* * MyParticleEffect startEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_MissileStart); * startEffect.WorldMatrix = WorldMatrix; */ m_smokeEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_Missile); m_smokeEffect.WorldMatrix = WorldMatrix; m_smokeEffect.AutoDelete = false; } } } m_desiredVelocity = GetDesiredVelocity(m_targetEntity); Physics.LinearVelocity = m_desiredVelocity * m_actualSpeed * 1.0f; } Physics.AngularVelocity = Vector3.Zero; if ((m_elapsedMiliseconds > m_missileTimeout) || (Vector3.Distance(GetPosition(), m_origin) >= m_maxTrajectory)) { Explode(); return; } if (m_smokeEffect != null) { Matrix smokeMatrix = Matrix.CreateWorld(WorldMatrix.Translation - 0.5f * WorldMatrix.Forward, WorldMatrix.Forward, WorldMatrix.Up); m_smokeEffect.WorldMatrix = smokeMatrix; } if (m_targetEntity != null) { if (m_targetEntity.Physics != null) { m_targetVelocity = m_targetEntity.Physics.LinearVelocity; } else { m_targetVelocity = Vector3.Zero; } } } finally { MyRender.GetRenderProfiler().EndProfilingBlock(); } }
// Allows the game to run logic such as updating the world, checking for collisions, gathering input, and playing audio. protected override void Update(GameTime gameTime) { if (m_debugFont == null) { return; } // Apply video mode changes. MyVideoModeManager.ApplyChanges(); // Update times in static member variables UpdateTimes(gameTime); //if (MyMinerGame.IsDeviceResetted) // MyVideoModeManager.UpdateAfterDeviceReset(); MyRender.GetRenderProfiler().StartProfilingBlock("Particles wait"); MyParticlesManager.WaitUntilUpdateCompleted(); MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Receive Multiplayer Messages"); MyMultiplayerPeers.Static.Update(); MyRender.GetRenderProfiler().EndProfilingBlock(); int updateBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("Update", ref updateBlock); if (MyMwcFinalBuildConstants.EnableLoggingInDrawAndUpdateAndGuiLoops == true) { MyMwcLog.WriteLine("MyMinerGame.Update() - START"); MyMwcLog.IncreaseIndent(); MyMwcLog.WriteLine("Update - gameTime.ElapsedGameTime: " + gameTime.ElapsedGameTime.ToString()); MyMwcLog.WriteLine("Update - gameTime.TotalGameTime: " + gameTime.TotalGameTime.ToString()); MyMwcLog.WriteLine("Max Garbage Generation: " + GC.MaxGeneration.ToString()); for (int i = 0; i <= GC.MaxGeneration; ++i) { MyMwcLog.WriteLine("Generation " + i.ToString() + ": " + GC.CollectionCount(i).ToString() + " collections"); } MyMwcLog.WriteLine("Total Memory: " + MyValueFormatter.GetFormatedLong(GC.GetTotalMemory(false)) + " bytes"); } // Inform us if there were some garbage collection if (MyMwcFinalBuildConstants.EnableLoggingGarbageCollectionCalls) { int newGc = MyGarbageCollectionManager.GetGarbageCollectionsCountFromLastCall(); if (newGc > 0) { MyMwcLog.WriteLine("####### Garbage collections from the last call: " + newGc + " #######"); } } int updateManagersBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("UpdateManagers", ref updateManagersBlock); MyRender.GetRenderProfiler().EndProfilingBlock(updateManagersBlock); // Now I think that it's better if HandleInput is called after Update, because then input methods // such as Shot() have up-to-date values such as position, forward vector, etc int guiManagerBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("GuiManager", ref guiManagerBlock); MyGuiManager.Update(); MyRender.GetRenderProfiler().EndProfilingBlock(guiManagerBlock); //After guimanager update because of object world matrices updates of objects MyParticlesManager.Update(); int inputBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("Input", ref inputBlock); MyGuiManager.HandleInput(); MyRender.GetRenderProfiler().EndProfilingBlock(inputBlock); int serverUpdateBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("MyClientServer.Update", ref serverUpdateBlock); //MyClientServer.Update(); ti MyRender.GetRenderProfiler().EndProfilingBlock(serverUpdateBlock); if (MyMwcFinalBuildConstants.SimulateSlowUpdate) { System.Threading.Thread.Sleep(7); } int audioUpdateBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("MyAudio.Update", ref audioUpdateBlock); MyAudio.Update(); MyDialogues.Update(); MyRender.GetRenderProfiler().EndProfilingBlock(audioUpdateBlock); int othersBlock = -1; MyRender.GetRenderProfiler().StartProfilingBlock("Others", ref othersBlock); if (MyMwcFinalBuildConstants.EnableLoggingInDrawAndUpdateAndGuiLoops == true) { if (MyMwcLog.IsIndentKeyIncreased()) { MyMwcLog.DecreaseIndent(); } MyMwcLog.WriteLine("MyMinerGame.Update() - END"); } ProcessInvoke(); if (OnGameUpdate != null) { OnGameUpdate(gameTime); } base.Update(gameTime); MyRender.GetRenderProfiler().EndProfilingBlock(othersBlock); MyRender.GetRenderProfiler().EndProfilingBlock(updateBlock); }
public override void UpdateBeforeSimulation() { try { MyRender.GetRenderProfiler().StartProfilingBlock("MyCannonShot.UpdateBeforeSimulation"); if (this.WorldMatrix.Translation != m_previousPosition) { MyLine line = new MyLine(this.WorldMatrix.Translation, m_previousPosition); MyDangerZones.Instance.Notify(line, OwnerEntity); } // Kill this missile if (m_isExploded && !m_wasPenetration) { // Create explosion MyExplosion newExplosion = MyExplosions.AddExplosion(); if (newExplosion != null) { float radius = MyMwcUtils.GetRandomFloat(m_ammoProperties.ExplosionRadius - 2, m_ammoProperties.ExplosionRadius + 2); BoundingSphere explosionSphere = new BoundingSphere((m_collisionPoint.HasValue ? m_collisionPoint.Value : GetPosition()), radius); MyExplosionInfo info = new MyExplosionInfo(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, explosionSphere, m_explosionType, true) { GroupMask = Physics.GroupMask, CascadeLevel = CascadedExplosionLevel, HitEntity = m_collidedEntity, OwnerEntity = this.OwnerEntity, Direction = WorldMatrix.Forward, ParticleScale = 1.5f, VoxelExplosionCenter = explosionSphere.Center + radius * WorldMatrix.Forward * 0.6f, }; info.CreateParticleEffect = !m_hasExplosion; newExplosion.Start(ref info); } if (m_collidedEntity != null && !m_collidedEntity.IsExploded()) { m_collidedEntity.Physics.AddForce( MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, WorldMatrix.Forward * MyMissileConstants.HIT_STRENGTH_IMPULSE, GetPosition() + MyMwcUtils.GetRandomVector3Normalized() * 2, MyMissileConstants.HIT_STRENGTH_IMPULSE * MyMwcUtils.GetRandomVector3Normalized()); } MarkForClose(); return; } base.UpdateBeforeSimulation(); // Chech timeout and max distance if ((m_elapsedMiliseconds > MyCannonConstants.SHOT_TIMEOUT) || (Vector3.Distance(this.WorldMatrix.Translation, m_origin) >= m_ammoProperties.MaxTrajectory)) { MarkForClose(); return; } Matrix orientation = GetWorldRotation(); // Update thruster cue/sound MyAudio.UpdateCuePosition(m_thrusterCue, this.WorldMatrix.Translation, orientation.Forward, orientation.Up, this.Physics.LinearVelocity); Vector3 pos = this.WorldMatrix.Translation; if (m_penetratedVoxelMap == null) { if (m_smokeEffect != null) { m_smokeEffect.WorldMatrix = WorldMatrix; } } /* * if (m_wasPenetration) * { * // Create explosion * MyExplosion newExplosion = MyExplosions.AddExplosion(); * if (newExplosion != null) * { * float radius = MyMwcUtils.GetRandomFloat(1, 2); * float particleScale = 2.2f; // must be large enough to cover the hole * newExplosion.StartWithPositionOffset(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, m_explosionType, m_penetrationOrigin - WorldMatrix.Forward * 2, radius, MyExplosionsConstants.EXPLOSION_LIFESPAN, CascadedExplosionLevel, particleScale: particleScale, hitEntity: m_collidedEntity, ownerEntity: m_ownerEntity); * } * m_wasPenetration = false; * m_hasExplosion = true; * } */ if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Proximity_Explosive) { // Look for small ships in shots's proximity BoundingSphere boundingSphere = new BoundingSphere(GetPosition(), MyCannonShotConstants.PROXIMITY_DETECTION_RADIUS); BoundingBox boundingBox = new BoundingBox(); BoundingBox.CreateFromSphere(ref boundingSphere, out boundingBox); var elements = MyEntities.GetElementsInBox(ref boundingBox); for (int i = 0; i < elements.Count; i++) { var rigidBody = (MyPhysicsBody)elements[i].GetRigidBody().m_UserData; var entity = rigidBody.Entity; if (!(entity is MinerWars.AppCode.Game.Entities.MySmallShip)) { continue; } if (entity == OwnerEntity) { continue; } if (entity == this) { continue; } Explode(entity); break; } elements.Clear(); } /* * if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster) * { * m_cuttingSphere.Center = GetPosition(); * * // We found voxel so lets make tunel into it * MyPhysObjectBase collisionResult = MyEntities.GetIntersectionWithSphere(ref m_cuttingSphere, this, (MySmallShip)Parent); * if (collisionResult is MyVoxelMap) * { * MyVoxelMap voxelMap = collisionResult as MyVoxelMap; * if (m_penetratedVoxelMap == null) * { * m_penetratedVoxelMap = voxelMap; * m_penetrationOrigin = GetPosition(); * } * * Game.Voxels.MyVoxelGenerator.CutOutSphereFast(voxelMap, m_cuttingSphere); * } * } */ /* * if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster) * { * if (m_penetratedVoxelMap != null) * { * //MyCannonShotConstants.BUSTER_PENETRATION_LENGTH * float busterPenetrationLength = m_ammoProperties.ExplosionRadius * 0.75f; * if (Vector3.Distance(m_penetrationOrigin, GetPosition()) >= busterPenetrationLength) * { * m_collisionPoint = GetPosition(); //We want to explode inside voxel, not on collision point * Explode(m_penetratedVoxelMap); * } * } * } */ } finally { MyRender.GetRenderProfiler().EndProfilingBlock(); } }
public bool Update() { if (!Enabled) { return(AutoDelete); //efect is not enabled at all and must be deleted } System.Diagnostics.Debug.Assert(WorldMatrix != MyUtils.ZeroMatrix, "Effect world matrix was not set!"); if (!m_isPreloading && !m_wasPreloaded && m_preload > 0) { m_isPreloading = true; // TODO: Optimize (preload causes lags, depending on preload size, it's from 0 ms to 85 ms) //while (m_elapsedTime < m_preload) //{ // Update(); //} m_isPreloading = false; m_wasPreloaded = true; } MyRender.GetRenderProfiler().StartProfilingBlock("ParticleEffect-Update"); if (!m_isPreloading && IsInFrustum) { MyPerformanceCounter.PerCameraDraw.ParticleEffectsDrawn++; } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("ParticleEffect-UpdateGen"); m_elapsedTime += MyConstants.PHYSICS_STEP_SIZE_IN_SECONDS; m_distance = MyCamera.GetDistanceWithFOV(WorldMatrix.Translation) / (UserScale * 1000.0f); m_particlesCount = 0; m_birthRate = 0; m_AABB = m_AABB.CreateInvalid(); if (CalculateDeltaMatrix) { DeltaMatrix = Matrix.Invert(m_lastWorldMatrix) * m_worldMatrix; } if (RenderCounter == 0 || ((MyRender.RenderCounter - RenderCounter) < FRAMES_TO_SKIP)) //more than FRAMES_TO_SKIP frames consider effect as invisible { foreach (MyParticleGeneration generation in m_generations) { generation.EffectMatrix = WorldMatrix; generation.Update(); m_particlesCount += generation.GetParticlesCount(); m_birthRate += generation.GetBirthRate(); BoundingBox bbox = generation.GetAABB(); m_AABB = m_AABB.Include(ref bbox); } m_lastWorldMatrix = m_worldMatrix; if (m_particlesCount > 0) { m_hasShownSomething = true; } IsInFrustum = MyCamera.IsInFrustum(ref m_AABB); } MyRender.GetRenderProfiler().EndProfilingBlock(); if (((m_particlesCount == 0 && HasShownSomething()) || (m_particlesCount == 0 && m_birthRate == 0.0f)) && AutoDelete && !m_isPreloading) { //Effect was played and has to be deleted return(true); } if (!m_isPreloading && OnUpdate != null) { OnUpdate(this, null); } return(false); }
// This method doesn't really draw. It just creates billboards that are later drawn in MyParticles.Draw() public static void Draw() { if (!MySector.ParticleDustProperties.Enabled) { return; } if (MinerWars.AppCode.Game.Render.MyRenderConstants.RenderQualityProfile.ForwardRender) { return; } // if (MyRender.CurrentRenderSetup.CallerID.Value != MyRenderCallerEnum.Main) // return; if ((int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf == 0) { return; } MyRender.GetRenderProfiler().StartProfilingBlock("Dust changed"); if ((m_lastDustBillboardRadius != MySector.ParticleDustProperties.DustBillboardRadius) || m_lastDustFieldCountInDirectionHalf != (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf) { m_lastDustBillboardRadius = MySector.ParticleDustProperties.DustBillboardRadius; m_lastDustFieldCountInDirectionHalf = (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf; m_distanceBetweenHalf = MySector.ParticleDustProperties.DistanceBetween / 2.0f; m_dustFieldCountInDirection = (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf * 2 + 1; // Bounding frustum is based on camer's bounding frustun, but far plane isn't in such distance, because then bounding box is too large // IMPORTANT: Near plane can't be 0.001 or something small like that. Because than bounding box is weird. m_helperProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MyCamera.FieldOfView, MyCamera.ForwardAspectRatio, MyCamera.NEAR_PLANE_DISTANCE, Math.Max(MySector.ParticleDustProperties.DistanceBetween * MySector.ParticleDustProperties.DustFieldCountInDirectionHalf, MyCamera.NEAR_PLANE_DISTANCE + 0.01f)); m_helperBoundingFrustum = new BoundingFrustum(Matrix.Identity); // Fill 3D array with random values from interval <0..1> m_random = new float[m_dustFieldCountInDirection][][]; for (int x = 0; x < m_random.Length; x++) { m_random[x] = new float[m_dustFieldCountInDirection][]; for (int y = 0; y < m_random.Length; y++) { m_random[x][y] = new float[m_dustFieldCountInDirection]; for (int z = 0; z < m_random.Length; z++) { m_random[x][y][z] = MyMwcUtils.GetRandomFloat(0, 1); } } } } MyRender.GetRenderProfiler().StartNextBlock("computations"); // If sun wind is active, we make particle dust more transparent float alphaBecauseSunWind = (MySunWind.IsActive == true) ? MySunWind.GetParticleDustFieldAlpha() : 1; Vector3 center = MyCamera.Position; //Vector3 center = MySession.PlayerShip.GetPosition(); MyMwcVector3Int cameraCoord = GetMetersToDustFieldCoord(ref center); MyMwcVector3Int minCoord = new MyMwcVector3Int(cameraCoord.X - (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf, cameraCoord.Y - (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf, cameraCoord.Z - (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf); MyMwcVector3Int maxCoord = new MyMwcVector3Int(cameraCoord.X + (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf, cameraCoord.Y + (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf, cameraCoord.Z + (int)MySector.ParticleDustProperties.DustFieldCountInDirectionHalf); // Update helper frustum and then its bounding box // Bounding frustum is based on camer's bounding frustun, but far plane isn't in such distance, because then bounding box is too large m_helperBoundingFrustum.Matrix = MyCamera.ViewMatrix * m_helperProjectionMatrix; BoundingBox helperBoundingBox = BoundingBoxHelper.InitialBox; //BoundingBoxHelper.AddFrustum(ref m_helperBoundingFrustum, ref helperBoundingBox); BoundingBoxHelper.AddSphere(new BoundingSphere(MyCamera.Position, 1000), ref helperBoundingBox); MyMwcVector3Int frustumBoundingBoxMinCoord = GetMetersToDustFieldCoord(ref helperBoundingBox.Min); MyMwcVector3Int frustumBoundingBoxMaxCoord = GetMetersToDustFieldCoord(ref helperBoundingBox.Max); //MyMwcVector3Int frustumBoundingBoxMinCoord = GetMetersToDustFieldCoord(ref MyCamera.BoundingBox.Min); //MyMwcVector3Int frustumBoundingBoxMaxCoord = GetMetersToDustFieldCoord(ref MyCamera.BoundingBox.Max); // This is fix for particles that will be near the frustum boundary (or on its other side, but still should be visible) // Think about it like this: particle is defined by its center, but it overlaps spherical area, so we are interested // in particles that are outisde of the frustum (but near it) frustumBoundingBoxMinCoord.X--; frustumBoundingBoxMinCoord.Y--; frustumBoundingBoxMinCoord.Z--; frustumBoundingBoxMaxCoord.X++; frustumBoundingBoxMaxCoord.Y++; frustumBoundingBoxMaxCoord.Z++; // Fix min/max coordinates, so only billboards in frustum are traversed and drawn if (minCoord.X < frustumBoundingBoxMinCoord.X) { minCoord.X = frustumBoundingBoxMinCoord.X; } if (minCoord.Y < frustumBoundingBoxMinCoord.Y) { minCoord.Y = frustumBoundingBoxMinCoord.Y; } if (minCoord.Z < frustumBoundingBoxMinCoord.Z) { minCoord.Z = frustumBoundingBoxMinCoord.Z; } if (maxCoord.X > frustumBoundingBoxMaxCoord.X) { maxCoord.X = frustumBoundingBoxMaxCoord.X; } if (maxCoord.Y > frustumBoundingBoxMaxCoord.Y) { maxCoord.Y = frustumBoundingBoxMaxCoord.Y; } if (maxCoord.Z > frustumBoundingBoxMaxCoord.Z) { maxCoord.Z = frustumBoundingBoxMaxCoord.Z; } Matrix rotationMatrix = Matrix.CreateRotationY(animXSpeed); animXSpeed += MySector.ParticleDustProperties.AnimSpeed; MyRender.GetRenderProfiler().StartNextBlock("for for for + draw"); MyMwcVector3Int tempCoord; for (tempCoord.X = minCoord.X; tempCoord.X <= maxCoord.X; tempCoord.X++) { for (tempCoord.Y = minCoord.Y; tempCoord.Y <= maxCoord.Y; tempCoord.Y++) { for (tempCoord.Z = minCoord.Z; tempCoord.Z <= maxCoord.Z; tempCoord.Z++) { // Position of this particle Vector3 position; position.X = tempCoord.X * MySector.ParticleDustProperties.DistanceBetween; position.Y = tempCoord.Y * MySector.ParticleDustProperties.DistanceBetween; position.Z = tempCoord.Z * MySector.ParticleDustProperties.DistanceBetween; // Get pseudo-random number. It's randomness is based on 3D position, so values don't change between draw calls. float pseudoRandomVariationMod = m_random[Math.Abs(tempCoord.X) % m_random.Length][Math.Abs(tempCoord.Y) % m_random.Length][Math.Abs(tempCoord.Z) % m_random.Length]; // Alter position by randomness position.X += MathHelper.Lerp(-m_distanceBetweenHalf, +m_distanceBetweenHalf, pseudoRandomVariationMod); position.Y += MathHelper.Lerp(-m_distanceBetweenHalf, +m_distanceBetweenHalf, pseudoRandomVariationMod); position.Z += MathHelper.Lerp(-m_distanceBetweenHalf, +m_distanceBetweenHalf, pseudoRandomVariationMod); // Distance to particle float distance; Vector3.Distance(ref center, ref position, out distance); Vector3 delta = position - MyCamera.Position; // delta = Vector3.Transform(delta, rotationMatrix); position = MyCamera.Position + delta; // Pseudo-random color and alpha float pseudoRandomColor = MathHelper.Lerp(0.1f, 0.2f, pseudoRandomVariationMod); //MathHelper.Lerp(0.2f, 0.3f, pseudoRandomVariationMod); //float pseudoRandomAlpha = 0.5f; //0.4f; // 0.2f;// MathHelper.Lerp(0.2f, 0.3f, pseudoRandomVariationMod); // Dust color var sectorDustColor = CustomColor.HasValue ? CustomColor.Value : MySector.ParticleDustProperties.Color; //if (MyGuiScreenGamePlay.Static.ResultDustColor != Vector4.Zero) //{ // sectorDustColor = MyGuiScreenGamePlay.Static.ResultDustColor; //} Vector4 color = sectorDustColor.ToVector4(); /* * Vector4 color = new Vector4( * pseudoRandomColor * sectorDustColor.X, * pseudoRandomColor * sectorDustColor.Y, * pseudoRandomColor * sectorDustColor.Z, * sectorDustColor.W); */ //color = Vector4.One; new Vector4(0.0f, 0.0f, 0.0f, 1.0f); //color = new Vector4(MinerWars.AppCode.Game.World.MySector.FogProperties.FogColor.X, MinerWars.AppCode.Game.World.MySector.FogProperties.FogColor.Y, MinerWars.AppCode.Game.World.MySector.FogProperties.FogColor.Z, 1); // Color+Alpha based on distance to camera (we use pre-multiplied alpha) float maxDistance = MySector.ParticleDustProperties.DustFieldCountInDirectionHalf * MySector.ParticleDustProperties.DistanceBetween; float DistanceAlpha1 = 0.7f * maxDistance; float DistanceAlpha2 = 0.85f * maxDistance; float DistanceAlpha3 = 1.0f * maxDistance; if (distance < DistanceAlpha1) { color *= 0; } else if ((distance >= DistanceAlpha1) && (distance < DistanceAlpha2)) { color *= MathHelper.Clamp((distance - DistanceAlpha1) / (DistanceAlpha2 - DistanceAlpha1), 0, 1); } else if ((distance >= DistanceAlpha2) && (distance < DistanceAlpha3)) { color *= 1 - MathHelper.Clamp((distance - DistanceAlpha2) / (DistanceAlpha3 - DistanceAlpha2), 0, 1); } else { color *= 0; } // Sun wind influence color *= alphaBecauseSunWind; // Do not draw totaly transparent particles if ((color.X <= 0) && (color.Y <= 0) && (color.Z <= 0) && (color.W <= 0)) { continue; } //if (color.W <= 0) continue; // Radius //float radius = DUST_BILLBOARD_RADIUS; //float radius = MathHelper.Lerp(1, 30, pseudoRandomVariationMod); float radius = MySector.ParticleDustProperties.DustBillboardRadius;// MathHelper.Lerp(100, 200, pseudoRandomVariationMod); // Angle - see comments, I tried to do some rotation based on time //angle += pseudoRandomVariationMod * ((MyMinerGame.TotalGamePlayTimeInMilliseconds % 10000.0f) / 1000.0f); //angle += pseudoRandomVariationMod * (MyMinerGame.TotalGamePlayTimeInMilliseconds / 10000.0f); float angle = pseudoRandomVariationMod + animXSpeed; color *= 2; //color = Vector4.One; //MyTransparentGeometry.AddPointBillboard(MyTransparentMaterialEnum.Stardust, color, position, radius, angle); MyTransparentGeometry.AddPointBillboard(MySector.ParticleDustProperties.Texture, color, position, radius, angle, 0, false, false, true); } } } MyRender.GetRenderProfiler().EndProfilingBlock(); }
void PrepareCascadesForDraw() { if (MyRender.Sun.Direction == Vector3.Zero) { return; } MyRender.GetRenderProfiler().StartProfilingBlock("UpdateFrustums"); UpdateFrustums(); MyRender.GetRenderProfiler().EndProfilingBlock(); // Set casting shadows geometry MyRender.GetRenderProfiler().StartProfilingBlock("update entities"); int frustumIndex = 0; foreach (MyOrthographicCamera lightCamera in m_lightCameras) { if (m_skip[frustumIndex]) { frustumIndex++; continue; } m_renderElementsForShadows.Clear(); m_transparentRenderElementsForShadows.Clear(); m_castingRenderObjectsUnique.Clear(); MyRender.GetRenderProfiler().StartProfilingBlock("OverlapAllBoundingBox"); var castersBox = lightCamera.BoundingBox; //Cannot use unscaled - incorrect result because of different cascade viewport size var castersFrustum = lightCamera.BoundingFrustum; //Cannot use unscaled - incorrect result because of different cascade viewport size int occludedItemsStats = 0; //always 0 for shadows //MyRender.PrepareEntitiesForDraw(ref castersBox, (MyOcclusionQueryID)(frustumIndex + 1), m_castingRenderObjects, m_occlusionQueriesLists[frustumIndex], ref MyPerformanceCounter.PerCameraDrawWrite.ShadowEntitiesOccluded[frustumIndex]); MyRender.PrepareEntitiesForDraw(ref castersFrustum, lightCamera.Position, (MyOcclusionQueryID)(frustumIndex + 1), m_castingRenderObjects, null, m_castingCullObjects, m_castingManualCullObjects, null, ref occludedItemsStats); MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("m_castingRenderObjects"); int c = 0; int skipped = 0; while (c < m_castingRenderObjects.Count) { MyRenderObject renderObject = (MyRenderObject)m_castingRenderObjects[c]; if (RespectCastShadowsFlags) { // System.Diagnostics.Debug.Assert(!(entity is MyDummyPoint) && !(entity is AppCode.Game.Entities.WayPoints.MyWayPoint)); if ((renderObject.ShadowCastUpdateInterval > 0) && ((MyRender.RenderCounter % renderObject.ShadowCastUpdateInterval) == 0)) { renderObject.NeedsResolveCastShadow = true; //We have to leave last value, because true when not casting shadow make radiation to ship // renderObject.CastShadow = true; } if (renderObject.NeedsResolveCastShadow) { //Resolve raycast to sun if (renderObject.CastShadowJob == null) { renderObject.CastShadowJob = new MyCastShadowJob(renderObject); renderObject.CastShadowTask = ParallelTasks.Parallel.Start(renderObject.CastShadowJob); } else if (renderObject.CastShadowTask.IsComplete) { renderObject.CastShadows = renderObject.CastShadowJob.VisibleFromSun; renderObject.CastShadowTask = new ParallelTasks.Task(); renderObject.CastShadowJob = null; renderObject.NeedsResolveCastShadow = false; if (renderObject.CastShadows == false) { HiddenResolvedObjects++; } } } if (!renderObject.NeedsResolveCastShadow && !renderObject.CastShadows) { if (renderObject is MyRenderVoxelCell) { } m_castingRenderObjects.RemoveAtFast(c); skipped++; continue; } } else { renderObject.NeedsResolveCastShadow = true; } if (!m_castingRenderObjectsUnique.Contains(renderObject)) { m_castingRenderObjectsUnique.Add(renderObject); if (frustumIndex < MyRenderConstants.RenderQualityProfile.ShadowCascadeLODTreshold) { renderObject.GetRenderElementsForShadowmap(MyLodTypeEnum.LOD0, m_renderElementsForShadows, m_transparentRenderElementsForShadows); } else { renderObject.GetRenderElementsForShadowmap(MyLodTypeEnum.LOD1, m_renderElementsForShadows, m_transparentRenderElementsForShadows); } } c++; } MyRender.GetRenderProfiler().EndProfilingBlock(); //Sorting VBs to minimize VB switches m_renderElementsForShadows.Sort(m_shadowElementsComparer); lightCamera.CastingRenderElements = m_renderElementsForShadows; MyPerformanceCounter.PerCameraDrawWrite.RenderElementsInShadows += m_renderElementsForShadows.Count; frustumIndex++; } MyRender.GetRenderProfiler().EndProfilingBlock(); }
/// <summary> /// Renders a list of models to the shadow map, and returns a surface /// containing the shadow occlusion factor /// </summary> public void Render() { if (MyRender.Sun.Direction == Vector3.Zero) { return; } MyRender.GetRenderProfiler().StartProfilingBlock("MyShadowRenderer::Render"); if (MultiThreaded) { WaitUntilPrepareForDrawCompleted(); } else { //PrepareFrame(); PrepareCascadesForDraw(); } IssueQueriesForCascades(); MyRender.GetRenderProfiler().StartProfilingBlock("Set & Clear RT"); // Set our targets MyRender.SetRenderTarget(MyRender.GetRenderTarget(m_shadowRenderTarget), MyRender.GetRenderTarget(m_shadowDepthTarget)); MyRender.GraphicsDevice.Clear(ClearFlags.ZBuffer, new ColorBGRA(0.0f), 1.0f, 0); DepthStencilState.Default.Apply(); RasterizerState.CullNone.Apply(); //RasterizerState.CullCounterClockwise.Apply(); BlendState.Opaque.Apply(); MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Render 4 ShadowMaps"); // Render our scene geometry to each split of the cascade for (int i = 0; i < NumSplits; i++) { if (m_skip[i]) { continue; } if (!m_visibility[i]) { continue; } RenderShadowMap(i); //IssueQueriesForShadowMap(i); } //Restore viewport MyRenderCamera.UpdateCamera(); MyRender.SetDeviceViewport(MyRenderCamera.Viewport); MyRender.GetRenderProfiler().EndProfilingBlock(); // MyGuiManager.TakeScreenshot(); MyRender.TakeScreenshot("ShadowMap", MyRender.GetRenderTarget(m_shadowRenderTarget), MyEffectScreenshot.ScreenshotTechniqueEnum.Color); // Texture.ToFile(MyRender.GetRenderTarget(m_shadowRenderTarget), "c:\\test.dds", ImageFileFormat.Dds); MyRender.GetRenderProfiler().EndProfilingBlock(); }
/// <summary> /// Starts the explosion. /// </summary> /// <param name="damage"></param> /// <param name="type"></param> /// <param name="explosionSphere"></param> /// <param name="lifespanInMiliseconds"></param> /// <param name="explosionForceDirection"></param> /// <param name="groupMask"></param> /// <param name="createExplosionDebris"></param> /// <param name="cascadeLevel"></param> /// <param name="hitEntity"></param> /// <param name="particleScale"></param> /// <param name="ownerEntity"></param> /// <param name="affectVoxels"></param> /// <param name="applyForceAndDamage"></param> /// <param name="createDecals"></param> /// <param name="direction">If applicable, gives the direction of the explosion, e.g. when it was caused by a missile (with its moving direction).</param> public void Start(ref MyExplosionInfo explosionInfo) { //MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius <= MyExplosionsConstants.EXPLOSION_RADIUS_MAX); MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius > 0); MyRender.GetRenderProfiler().StartProfilingBlock("MyExplosion.Start"); m_explosionSphere = explosionInfo.ExplosionSphere; m_elapsedMiliseconds = 0; m_lifespanInMiliseconds = explosionInfo.LifespanMiliseconds; if (explosionInfo.PlaySound) { MyRender.GetRenderProfiler().StartProfilingBlock("Sound"); // Play explosion sound if (m_explosionCue != null && m_explosionCue.Value.IsPlaying) { m_explosionCue.Value.Stop(SharpDX.XACT3.StopFlags.Immediate); } m_explosionCue = MyAudio.AddCue3D(GetCueEnumByExplosionType(explosionInfo.ExplosionType), m_explosionSphere.Center, Vector3.Zero, Vector3.Zero, Vector3.Zero); MyRender.GetRenderProfiler().EndProfilingBlock(); } MyRender.GetRenderProfiler().StartProfilingBlock("Light"); // Light of explosion /* * m_light = MyLights.AddLight(); * if (m_light != null) * { * m_light.Start(MyLight.LightTypeEnum.PointLight, m_explosionSphere.Center, MyExplosionsConstants.EXPLOSION_LIGHT_COLOR, 1, Math.Min(m_explosionSphere.Radius * 8.0f, MyLightsConstants.MAX_POINTLIGHT_RADIUS)); * m_light.Intensity = 2.0f; * } */ MyRender.GetRenderProfiler().EndProfilingBlock(); // close explosion check bool close = IsExplosionClose(explosionInfo.ExplosionSphere); MyParticleEffectsIDEnum newParticlesType; switch (explosionInfo.ExplosionType) { case MyExplosionTypeEnum.SMALL_SHIP_EXPLOSION: // Create metal debris objects thrown from the explosion // This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris) // Throw a lot of debrises, more than only if some metalic object is hit (because this is destruction of a ship) //MyPhysObjectExplosionDebrises.CreateExplosionDebris(m_explosionSphere.Center, 1); newParticlesType = MyParticleEffectsIDEnum.Explosion_Smallship; break; case MyExplosionTypeEnum.MISSILE_EXPLOSION: newParticlesType = // ? MyParticleEffectsIDEnum.Explosion_Missile_Close MyParticleEffectsIDEnum.Explosion_Missile; break; case MyExplosionTypeEnum.BOMB_EXPLOSION: case MyExplosionTypeEnum.GRAVITY_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Bomb; break; case MyExplosionTypeEnum.AMMO_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Ammo; break; case MyExplosionTypeEnum.BLASTER_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Blaster; break; case MyExplosionTypeEnum.BIOCHEM_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_BioChem; break; case MyExplosionTypeEnum.EMP_EXPLOSION: case MyExplosionTypeEnum.FLASH_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_EMP; break; case MyExplosionTypeEnum.METEOR_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Meteor; break; case MyExplosionTypeEnum.NUCLEAR_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Nuclear; break; case MyExplosionTypeEnum.PLASMA_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Plasma; break; case MyExplosionTypeEnum.SMALL_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_SmallPrefab; break; case MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Huge; break; case MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Large; break; case MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Medium; break; case MyExplosionTypeEnum.ASTEROID_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Asteroid; break; default: throw new System.NotImplementedException(); break; } if (explosionInfo.Damage > 0) { MyRender.GetRenderProfiler().StartProfilingBlock("Voxel or collision"); // If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc MyVoxelMap voxelMap = explosionInfo.AffectVoxels && explosionInfo.EmpDamage == 0 ? MyVoxelMaps.GetOverlappingWithSphere(ref m_explosionSphere) : null; if (voxelMap != null) { // Dirty explosion with a lot of dust MyMwcVoxelMaterialsEnum?voxelMaterial = null; float voxelContentRemovedInPercent = 0; bool createDebris = true; // We want to create debris if (explosionInfo.HitEntity != null) // but not when we hit prefab { createDebris &= explosionInfo.HitEntity is MyVoxelMap; } //cut off BoundingSphere voxelExpSphere = new BoundingSphere(explosionInfo.VoxelExplosionCenter, m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale); if (MyVoxelGenerator.CutOutSphereFast(voxelMap, voxelExpSphere, out voxelContentRemovedInPercent, out voxelMaterial, (explosionInfo.OwnerEntity is MySmallShip && explosionInfo.OwnerEntity == Managers.Session.MySession.PlayerShip), MyFakes.VOXELS_REMOVE_RATIO)) { if (explosionInfo.HitEntity is MyVoxelMap) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } createDebris = false; // and no debris when voxel is indestructible } // Only if at least something was removed from voxel map // If voxelContentRemovedInPercent is more than zero than also voxelMaterial shouldn't be null, but I rather check both of them. if ((voxelContentRemovedInPercent > 0) && (voxelMaterial != null)) { //remove decals MyDecals.HideTrianglesAfterExplosion(voxelMap, ref voxelExpSphere); MyRender.GetRenderProfiler().StartProfilingBlock("CreateDebris"); if (explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris) && MyRenderConstants.RenderQualityProfile.ExplosionDebrisCountMultiplier > 0) { // Create debris rocks thrown from the explosion // This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris) MyExplosionDebrisVoxel.CreateExplosionDebris(ref voxelExpSphere, voxelContentRemovedInPercent, voxelMaterial.Value, explosionInfo.GroupMask, voxelMap); } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("CreateParticleEffect"); MyParticleEffect explosionEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialExplosion_Destructible); explosionEffect.WorldMatrix = Matrix.CreateTranslation(voxelExpSphere.Center); explosionEffect.UserRadiusMultiplier = voxelExpSphere.Radius; MyRender.GetRenderProfiler().EndProfilingBlock(); } } MyRender.GetRenderProfiler().EndProfilingBlock(); } if (explosionInfo.Damage > 0) { // Create dirt decals in player's cockpit glass MyRender.GetRenderProfiler().StartProfilingBlock("Cockpit Decals"); CreateDirtDecalOnCockpitGlass(ref m_explosionSphere); MyRender.GetRenderProfiler().EndProfilingBlock(); } if (DEBUG_EXPLOSIONS) { MyRender.GetRenderProfiler().EndProfilingBlock(); return; } if (explosionInfo.Damage > 0) { BoundingSphere influenceExplosionSphere = m_explosionSphere; influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_RADIUS_MULTPLIER_FOR_IMPULSE; for (int i = 0; i < explosionInfo.CascadeLevel; i++) { influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_CASCADE_FALLOFF; } // Throws surrounding objects away from centre of the explosion. if (explosionInfo.ApplyForceAndDamage) { if (explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION || explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION || explosionInfo.ExplosionType == MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION) { DisableContainedDummyParticles(ref explosionInfo); } explosionInfo.StrengthImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * m_explosionSphere.Radius / 20; explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE; explosionInfo.HitEntity = explosionInfo.HitEntity != null?explosionInfo.HitEntity.GetBaseEntity() : null; MyRender.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage"); MyEntities.ApplyExplosionForceAndDamage(ref explosionInfo); MyRender.GetRenderProfiler().EndProfilingBlock(); } // Look for objects in explosion radius BoundingBox boundingBox; BoundingBox.CreateFromSphere(ref influenceExplosionSphere, out boundingBox); //if (explosionInfo.CreateDecals && explosionInfo.Direction.HasValue && explosionInfo.EmpDamage == 0) //{ // CreateDecals(explosionInfo.Direction.Value); //} } if (explosionInfo.CreateParticleEffect) { MyRender.GetRenderProfiler().StartProfilingBlock("Particles"); if (explosionInfo.CustomEffect != null) { if (explosionInfo.CustomEffect.ParticleID == 0) { explosionInfo.CustomEffect.ParticleID = (int)newParticlesType; } //Reload effect explosionInfo.CustomEffect.Enabled = false; explosionInfo.CustomEffect.Enabled = true; } else { // Explosion particles GenerateExplosionParticles(newParticlesType, m_explosionSphere, explosionInfo.ParticleScale); } MyRender.GetRenderProfiler().EndProfilingBlock(); } MyRender.GetRenderProfiler().EndProfilingBlock(); /* * // When MyAmmoBase entity is closed to explosion it will explode * if (entity is MyAmmoBase) * { * (entity as MyAmmoBase).ExplodeCascade(cascadeLevel + 1); * } */ // Smut decals - must be called after the explosion, after voxels are cutted out /*if ((intersection.PhysObject is MyVoxelMap) == false) * { * if (intersection.PhysObject is MyCockpitGlass) * { * // Change phys object so rest of the code will think we hit the parent * // Same fix is in projectile too - because cockpit glass is only helper object, we don't use it for real rendering and stuff * // And if not changed, it can make problem in "phys object decals" * intersection.PhysObject = intersection.PhysObject.Parent; * } * * // Create explosion smut decal on model we hit by this missile * MyDecals.Add( * MyDecalTexturesEnum.ExplosionSmut, * MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.7f, m_explosionSphere.Radius * 1.3f), * MyMwcUtils.GetRandomRadian(), * GetSmutDecalRandomColor(), * true, * ref intersection); * } * else * { * // Creating explosion smut decal on voxel is more complicated than on voxel. We will project few lines * // from explosion epicentrum to the surounding world (random directions) and place decal where intersection detected. * //if (knownMissileDirection != null) * //{ * // MyLine linePrologned = new MyLine(knownIntersection.Value.IntersectionPointInObjectSpace, * // knownIntersection.Value.IntersectionPointInObjectSpace + knownMissileDirection.Value * MyExplosionsConstants.EXPLOSION_RANDOM_RADIUS_MAX * 2, * // true); * // MyLineTriangleIntersectionResult intersectionForSmut = knownIntersection.Value.VoxelMap.GetIntersectionWithLine(ref linePrologned); * // if (intersectionForSmut.Found == true) * // { * // MyDecals.Add( * // MyDecalTexturesEnum.ExplosionSmut, * // MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.5f, m_explosionSphere.Radius * 1.0f), * // MyMwcUtils.GetRandomRadian(), * // GetSmutDecalRandomColor(), * // false, * // ref intersectionForSmut); * // } * //} * }*/ // Generate dust particles that will stay in place of the explosion //doesnt look good in final //GenerateStatisDustParticles(m_explosionSphere); }
private void CreateDecals(Vector3 direction) { MyRender.GetRenderProfiler().StartProfilingBlock("Collisions"); MyRender.GetRenderProfiler().StartProfilingBlock("Raycast"); var intersectionEndPoint = m_explosionSphere.Center + 1.5f * m_explosionSphere.Radius * direction; var intersectionStartPoint = m_explosionSphere.Center - 1.5f * m_explosionSphere.Radius * direction; var line = new MyLine(intersectionStartPoint, intersectionEndPoint); var result = MyEntities.GetIntersectionWithLine(ref line, null, null, true, true, false, false, true, AppCode.Physics.Collisions.IntersectionFlags.ALL_TRIANGLES, true); MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("Add decal"); if (result.HasValue) { MyIntersectionResultLineTriangleEx intersection = result.Value; var radius = m_explosionSphere.Radius * (result.Value.Entity is MyVoxelMap ? 1.0f : MyMwcUtils.GetRandomFloat(0.4f, 0.6f)); MyDecals.Add( MyDecalTexturesEnum.ExplosionSmut, radius, MyMwcUtils.GetRandomRadian(), GetSmutDecalRandomColor(), true, ref intersection, 0, 0, MyDecalsConstants.DECAL_OFFSET_BY_NORMAL_FOR_SMUT_DECALS); } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().EndProfilingBlock(); //var elements = MyEntities.GetElementsInBox(ref boundingBox); //foreach (MyRBElement element in elements) //{ // var rigidBody = (MyPhysicsBody)element.GetRigidBody().m_UserData; // var entity = rigidBody.Entity; // if (entity is MyExplosionDebrisBase || entity is MyPrefabContainer) // continue; // // Making interesection of line from the explosion center to every object closed to explosion // // and placing smut decals // // FIX : when hitting another samll boat explosion and entity position are equal !!! // //if (m_explosionSphere.Center == entity.GetPosition()) // // continue; // // FIX : when hitting another samll boat explosion and direction is < Epsilon !!! // if ((entity.GetPosition() - m_explosionSphere.Center).LengthSquared() < // 2 * MyMwcMathConstants.EPSILON_SQUARED) // continue; // MyRender.GetRenderProfiler().StartProfilingBlock("Line intersection"); // MyIntersectionResultLineTriangleEx? intersection = null; // if (direction.HasValue) // { // var intersectionEndPoint = m_explosionSphere.Center + 1.5f * m_explosionSphere.Radius * direction.Value; // var intersectionStartPoint = m_explosionSphere.Center - 1.5f * m_explosionSphere.Radius * direction.Value; // MyLine intersectionLine = new MyLine(intersectionStartPoint, intersectionEndPoint, true); // entity.GetIntersectionWithLine(ref intersectionLine, out intersection); // } // else if (intersection == null && entity is MyVoxelMap) // { // // fall back if we dont have direction // var intersectionEndPoint = entity.GetPosition(); // MyLine intersectionLine = new MyLine(m_explosionSphere.Center, intersectionEndPoint, true); // entity.GetIntersectionWithLine(ref intersectionLine, out intersection); // } // MyRender.GetRenderProfiler().EndProfilingBlock(); // if (intersection == null) // continue; // MyIntersectionResultLineTriangleEx intersectionValue = intersection.Value; // if (entity is MyVoxelMap) // { // MyRender.GetRenderProfiler().StartProfilingBlock("Decals"); // MyDecals.Add( // MyDecalTexturesEnum.ExplosionSmut, // m_explosionSphere.Radius, // MyMwcUtils.GetRandomRadian(), // GetSmutDecalRandomColor(), // true, // ref intersectionValue, // 0, // 0, MyDecalsConstants.DECAL_OFFSET_BY_NORMAL_FOR_SMUT_DECALS); // MyRender.GetRenderProfiler().EndProfilingBlock(); // } // else if (((entity is MySmallShip) == false) && // ((entity is MySmallDebris) == false) // && ((entity is MyAmmoBase) == false)) // { // // Create explosion smut decal on model we hit by this missile // MyDecals.Add( // MyDecalTexturesEnum.ExplosionSmut, // MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.4f, m_explosionSphere.Radius * 0.6f), // MyMwcUtils.GetRandomRadian(), // GetSmutDecalRandomColor(), // true, // ref intersectionValue, // 0, // 0, MyDecalsConstants.DECAL_OFFSET_BY_NORMAL); // } //} //elements.Clear(); }
public void IssueQueriesForCascades() { MyRender.GetRenderProfiler().StartProfilingBlock("MyShadowRenderer::IssueQueriesForCascades"); bool useOccQueries = MyRender.EnableHWOcclusionQueriesForShadows && MyRender.CurrentRenderSetup.EnableOcclusionQueries; if (!useOccQueries) { for (int i = 0; i < NumSplits; i++) { m_visibility[i] = true; } MyRender.GetRenderProfiler().EndProfilingBlock(); return; } /* * Device device = MyRender.GraphicsDevice; * BlendState oldBlendState = BlendState.Current; * MyStateObjects.DisabledColorChannels_BlendState.Apply(); * * //generate and draw bounding box of our renderCell in occlusion query * //device.BlendState = MyStateObjects.DisabledColorChannels_BlendState; * MyRender.SetRenderTarget(MyRender.GetRenderTarget(MyRenderTargets.Auxiliary0), null); * * Vector3 campos = MyRenderCamera.Position; * * RasterizerState.CullNone.Apply(); * * if (MyRenderConstants.RenderQualityProfile.ForwardRender) * DepthStencilState.DepthRead.Apply(); * else * DepthStencilState.None.Apply(); * * for (int i = 1; i < NumSplits; i++) * { * if (m_interleave[i]) continue; * * MyPerformanceCounter.PerCameraDrawWrite.QueriesCount++; * * var queryIssue = m_cascadeQueries[i]; * * if (queryIssue.OcclusionQueryIssued) * { * if (queryIssue.OcclusionQuery.IsComplete) * { * m_visibility[i] = queryIssue.OcclusionQuery.PixelCount > 0; * queryIssue.OcclusionQueryIssued = false; * } * continue; * } * * queryIssue.OcclusionQueryIssued = true; * * if (queryIssue.OcclusionQuery == null) * queryIssue.OcclusionQuery = new MyOcclusionQuery(device); * * cameraFrustum.Matrix = m_lightCameras[i].CameraSubfrustum; * * cameraFrustum.GetCorners(frustum); * * var tmp = frustum[3]; * frustum[3] = frustum[2]; * frustum[2] = tmp; * * queryIssue.OcclusionQuery.Begin(); * MySimpleObjectDraw.OcclusionPlaneDraw(frustum); * queryIssue.OcclusionQuery.End(); * } * * oldBlendState.Apply(); */ MyRender.GetRenderProfiler().EndProfilingBlock(); }