public static bool AddAttachedQuad(string material, ref MyQuadD quad, Vector4 color, ref Vector3D vctPos, int renderObjectID) { Debug.Assert(material != null); if (!IsEnabled) { return(false); } MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return(false); } CreateBillboard(billboard, ref quad, material, ref color, ref vctPos); billboard.ParentID = renderObjectID; billboard.BlendType = MyBillboard.BlenType.Standard; VRageRender.MyRenderProxy.AddBillboard(billboard); return(true); }
public static bool AddQuad(string material, ref MyQuadD quad, ref Color color, ref Vector3D vctPos, int priority = 0, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return(false); } MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return(false); } billboard.Priority = priority; CreateBillboard(billboard, ref quad, material, ref color, ref vctPos, false, false, false, customViewProjection); VRageRender.MyRenderProxy.AddBillboard(billboard); return(true); }
private static void AddBillboard(ref QuadBoard qb, ref MyQuadD quad) { MyTransparentGeometry.AddTriangleBillboard ( quad.Point0, quad.Point1, quad.Point2, Vector3.Zero, Vector3.Zero, Vector3.Zero, qb.texCoords.Min, (qb.texCoords.Min + new Vector2(0f, qb.texCoords.Size.Y)), qb.texCoords.Max, qb.textureID, 0, Vector3D.Zero, qb.bbColor, BlendTypeEnum.PostPP ); MyTransparentGeometry.AddTriangleBillboard ( quad.Point0, quad.Point2, quad.Point3, Vector3.Zero, Vector3.Zero, Vector3.Zero, qb.texCoords.Min, qb.texCoords.Max, (qb.texCoords.Min + new Vector2(qb.texCoords.Size.X, 0f)), qb.textureID, 0, Vector3D.Zero, qb.bbColor, BlendTypeEnum.PostPP ); }
internal static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Color color, ref Vector3D origin, float softParticleDistanceScale = 1.0f, string blendMaterial = "Test", float textureBlendRatio = 0, Vector2 uvOffset = new Vector2(), bool near = false, bool lowres = false, float reflectivity = 0) { Debug.Assert(material != null); Debug.Assert(blendMaterial != null); if (string.IsNullOrEmpty(material) || !MyTransparentMaterials.ContainsMaterial(material)) { material = "ErrorMaterial"; color = Vector4.One; } billboard.Material = material; billboard.BlendMaterial = blendMaterial; billboard.BlendTextureRatio = textureBlendRatio; quad.Point0.AssertIsValid(); quad.Point1.AssertIsValid(); quad.Point2.AssertIsValid(); quad.Point3.AssertIsValid(); // Billboard vertexes billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; billboard.UVOffset = uvOffset; billboard.UVSize = Vector2.One; // Distance for sorting // IMPORTANT: Must be calculated before we do color and alpha misting, because we need distance there billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyRender11.Environment.Matrices.CameraPosition, origin); // Color billboard.Color = color; billboard.Reflectivity = reflectivity; billboard.ColorIntensity = 1; billboard.Near = near; billboard.Lowres = lowres; billboard.ParentID = -1; // Alpha depends on distance to camera. Very close bilboards are more transparent, so player won't see billboard errors or rotating billboards var mat = MyTransparentMaterials.GetMaterial(billboard.Material); if (mat.AlphaMistingEnable) { billboard.Color *= MathHelper.Clamp(((float)Math.Sqrt(billboard.DistanceSquared) - mat.AlphaMistingStart) / (mat.AlphaMistingEnd - mat.AlphaMistingStart), 0, 1); } billboard.Color *= mat.Color; billboard.SoftParticleDistanceScale = softParticleDistanceScale; billboard.ContainedBillboards.Clear(); }
public static void GetPolyLineQuad(out MyQuadD retQuad, ref MyPolyLineD polyLine, Vector3D cameraPosition) { Vector3D cameraToPoint = MyUtils.Normalize(cameraPosition - polyLine.Point0); Vector3D sideVector = GetVector3Scaled(Vector3D.Cross(polyLine.LineDirectionNormalized, cameraToPoint), polyLine.Thickness); retQuad.Point0 = polyLine.Point0 - sideVector; retQuad.Point1 = polyLine.Point1 - sideVector; retQuad.Point2 = polyLine.Point1 + sideVector; retQuad.Point3 = polyLine.Point0 + sideVector; }
/// <summary> /// Generate oriented quad by matrix /// </summary> public static void GenerateQuad(out MyQuadD quad, ref Vector3D position, float width, float height, ref MatrixD matrix) { Vector3 billboardAxisX = matrix.Left * width; Vector3 billboardAxisY = matrix.Up * height; // Coordinates of four points of a billboard's quad quad.Point0 = position + billboardAxisX + billboardAxisY; quad.Point1 = position + billboardAxisX - billboardAxisY; quad.Point2 = position - billboardAxisX - billboardAxisY; quad.Point3 = position - billboardAxisX + billboardAxisY; }
/// <summary> /// This billboard isn't facing the camera. It's always oriented in specified direction. May be used as thrusts, or inner light of reflector. /// </summary> public static void GetBillboardQuadOriented(out MyQuadD quad, ref Vector3D position, float width, float height, ref Vector3 leftVector, ref Vector3 upVector) { Vector3D billboardAxisX = leftVector * width; Vector3D billboardAxisY = upVector * height; // Coordinates of four points of a billboard's quad quad.Point0 = position + billboardAxisX + billboardAxisY; quad.Point1 = position + billboardAxisX - billboardAxisY; quad.Point2 = position - billboardAxisX - billboardAxisY; quad.Point3 = position - billboardAxisX + billboardAxisY; }
// This method is like a constructor (which we can't use because billboards are allocated from a pool). // It starts/initializes a billboard. Refs used only for optimalization public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Vector4 color, ref Vector3D origin, Vector2 uvOffset, int customViewProjection = -1, float reflectivity = 0) { System.Diagnostics.Debug.Assert(material != null); if (string.IsNullOrEmpty(material) || !MyTransparentMaterials.ContainsMaterial(material)) { material = "ErrorMaterial"; color = Vector4.One; } billboard.Material = material; MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); // Billboard vertices billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; billboard.UVOffset = uvOffset; billboard.UVSize = Vector2.One; // Distance for sorting // IMPORTANT: Must be calculated before we do color and alpha misting, because we need distance there Vector3D cameraPosition = customViewProjection == -1 ? MyTransparentGeometry.Camera.Translation : VRageRender.MyRenderProxy.BillboardsViewProjectionWrite[customViewProjection].CameraPosition; billboard.DistanceSquared = (float)Vector3D.DistanceSquared(cameraPosition, origin); // Color billboard.Color = color; billboard.ColorIntensity = 1; billboard.Reflectivity = reflectivity; billboard.CustomViewProjection = customViewProjection; billboard.ParentID = -1; billboard.SoftParticleDistanceScale = 1; // Alpha depends on distance to camera. Very close bilboards are more transparent, so player won't see billboard errors or rotating billboards var mat = MyTransparentMaterials.GetMaterial(billboard.Material); if (mat.AlphaMistingEnable) { billboard.Color *= MathHelper.Clamp(((float)Math.Sqrt(billboard.DistanceSquared) - mat.AlphaMistingStart) / (mat.AlphaMistingEnd - mat.AlphaMistingStart), 0, 1); } billboard.Color *= mat.Color; }
private void DrawDebugBox() { MyQuadD myQuadD = new MyQuadD { Point0 = new Vector3D(), Point1 = new Vector3D(), Point2 = new Vector3D(), Point3 = new Vector3D() }; //MySimpleObjectDraw.DrawTransparentBox(); //MyTransparentGeometry //MyTransparentGeometry //MySimpleObjectDraw.DrawAttachedTransparentBox(); //MyEntities. //public static void DrawAttachedTransparentBox(ref MatrixD worldMatrix, ref BoundingBoxD localbox, ref Color color, uint renderObjectID, ref MatrixD worldToLocal, MySimpleObjectRasterizer rasterization, int wireDivideRatio, float lineWidth = 1f, MyStringId? faceMaterial = null, MyStringId? lineMaterial = null, bool onlyFrontFaces = false) }
// Calculates coordinates for quad that lies on line defined by two points and is always facing the camera. It thickness is defined in metres. // It is used for drawing bullet lines, debris flying from explosions, anything that isn't quad but is line. // IMPORTANT: Parameter 'polyLine' is refed only for performance. Don't change it inside the method. public static void GetPolyLineQuad(out MyQuadD retQuad, ref MyPolyLineD polyLine) { Vector3D toCamera = MyRenderCamera.Position - polyLine.Point0; Vector3D cameraToPoint; if (!MyUtils.HasValidLength(toCamera)) { // When camera at point, choose random direction cameraToPoint = Vector3D.Forward; } else { cameraToPoint = MyUtils.Normalize(toCamera); } Vector3D sideVector = MyUtils.GetVector3Scaled(Vector3D.Cross((Vector3D)polyLine.LineDirectionNormalized, cameraToPoint), polyLine.Thickness); retQuad.Point0 = polyLine.Point0 - sideVector; retQuad.Point1 = polyLine.Point1 - sideVector; retQuad.Point2 = polyLine.Point1 + sideVector; retQuad.Point3 = polyLine.Point0 + sideVector; }
/// <summary> /// Adds a list of textured quads in one batch using QuadBoard data /// </summary> public static void AddQuads(IReadOnlyList <QuadBoardData> quads, MatrixD[] matrixRef = null) { var bbPool = instance.bbPoolBack; var bbDataBack = instance.triangleList; var bbBuf = instance.bbBuf; var matList = instance.matrixBuf; var matTable = instance.matrixTable; // Find matrix index in table or add it int matrixID = -1; if (matrixRef != null && !matTable.TryGetValue(matrixRef, out matrixID)) { matrixID = matList.Count; matList.Add(matrixRef[0]); matTable.Add(matrixRef, matrixID); } int triangleCount = quads.Count * 2, bbRemaining = bbPool.Count - bbDataBack.Count, bbToAdd = Math.Max(triangleCount - bbRemaining, 0); instance.AddNewBB(bbToAdd); for (int i = bbDataBack.Count; i < triangleCount + bbDataBack.Count; i++) { bbBuf.Add(bbPool[i]); } MyTransparentGeometry.AddBillboards(bbBuf, false); bbBuf.Clear(); bbDataBack.EnsureCapacity(bbDataBack.Count + triangleCount); for (int i = 0; i < quads.Count; i++) { QuadBoardData quadBoard = quads[i]; MyQuadD quad = quadBoard.positions; BoundedQuadMaterial mat = quadBoard.material; var bbL = new TriangleBillboardData { Item1 = BlendTypeEnum.PostPP, Item2 = new Vector2I(bbDataBack.Count, matrixID), Item3 = mat.textureID, Item4 = mat.bbColor, Item5 = new MyTuple <Vector2, Vector2, Vector2> ( mat.texBounds.Min, mat.texBounds.Min + new Vector2(0f, mat.texBounds.Size.Y), mat.texBounds.Max ), Item6 = new MyTuple <Vector3D, Vector3D, Vector3D> ( quad.Point0, quad.Point1, quad.Point2 ), }; var bbR = new TriangleBillboardData { Item1 = BlendTypeEnum.PostPP, Item2 = new Vector2I(bbDataBack.Count + 1, matrixID), Item3 = mat.textureID, Item4 = mat.bbColor, Item5 = new MyTuple <Vector2, Vector2, Vector2> ( mat.texBounds.Min, mat.texBounds.Max, mat.texBounds.Min + new Vector2(mat.texBounds.Size.X, 0f) ), Item6 = new MyTuple <Vector3D, Vector3D, Vector3D> ( quad.Point0, quad.Point2, quad.Point3 ), }; bbDataBack.Add(bbL); bbDataBack.Add(bbR); } }
public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Vector4 color, ref Vector3D origin, int customViewProjection = -1, float reflection = 0) { CreateBillboard(billboard, ref quad, material, ref color, ref origin, Vector2.Zero, customViewProjection, reflection); }
/// <summary> /// Draws a billboard in world space using the quad specified. /// </summary> public void Draw(ref MyQuadD quad) { BillBoardUtils.AddQuad(ref materialData, ref quad); }
/// <summary> /// Draws a billboard in world space using the quad specified. /// </summary> public void Draw(ref MyQuadD quad) { AddBillboard(ref this, ref quad); }
// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(VRageRender.MyBillboard billboard) { MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, m_actualPosition); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 0.1f) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = m_generation.GetEffect().LowRes || VRageRender.MyRenderConstants.RenderQualityProfile.LowResParticles; billboard.CustomViewProjection = -1; billboard.ParentID = -1; float alpha = 1; if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); GetBillboardQuadRotated(billboard, ref m_actualPosition, actualRadius, m_actualAngle); MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyUtils.GetRandomVector3Normalized(); } MyQuadD quad = new MyQuadD(); MyPolyLineD polyLine = new MyPolyLineD(); polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); if (m_actualAngle > 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(MathHelper.ToRadians(m_actualAngle))); } polyLine.Point0 = m_actualPosition; polyLine.Point1.X = m_actualPosition.X + polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = m_actualPosition.Y + polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = m_actualPosition.Z + polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out quad, ref polyLine, camPos); if (this.m_generation.AlphaAnisotropic) { float angle = 1 - Math.Abs(Vector3.Dot(MyUtils.Normalize(MyTransparentGeometry.Camera.Forward), polyLine.LineDirectionNormalized)); float alphaCone = (float)Math.Pow(angle, 0.5f); alpha = alphaCone; } billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; //if (this.m_generation.AlphaAnisotropic) /* { //Trails are anisotropic by default (nobody wants them to see ugly) * Vector3 lineDir = Vector3.Normalize(Quad.Point1 - Quad.Point0); * float angle = 1 - Math.Abs(Vector3.Dot(MyMwcUtils.Normalize(MyCamera.ForwardVector), lineDir)); * float alphaCone = (float)Math.Pow(angle, 0.3f); * alpha = alphaCone; * }*/ } else { throw new NotSupportedException(Type + " is not supported particle type"); } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color; Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); var material1 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); var material2 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); billboard.Material = material1.Name; billboard.BlendMaterial = material2.Name; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Color color, ref Vector3D origin, Vector2 uvOffset, bool colorize = false, bool near = false, bool lowres = false, int customViewProjection = -1, float reflection = 0) { CreateBillboard(billboard, ref quad, material, "Test", 0, ref color, ref origin, uvOffset, colorize, near, lowres, customViewProjection, reflection); }
public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, string blendMaterial, float textureBlendRatio, ref Color color, ref Vector3D origin, bool colorize = false, bool near = false, bool lowres = false, int customViewProjection = -1, float reflection = 0) { CreateBillboard(billboard, ref quad, material, blendMaterial, textureBlendRatio, ref color, ref origin, Vector2.Zero, colorize, near, lowres, customViewProjection, reflection); }
/// <summary> /// Queues a quad billboard for rendering /// </summary> public static void AddQuad(ref BoundedQuadMaterial mat, ref MyQuadD quad, MatrixD[] matrixRef = null) { var bbPool = instance.bbPoolBack; var bbDataBack = instance.triangleList; int indexL = bbDataBack.Count, indexR = bbDataBack.Count + 1; var matList = instance.matrixBuf; var matTable = instance.matrixTable; // Find matrix index in table or add it int matrixID = -1; if (matrixRef != null && !matTable.TryGetValue(matrixRef, out matrixID)) { matrixID = matList.Count; matList.Add(matrixRef[0]); matTable.Add(matrixRef, matrixID); } var bbL = new TriangleBillboardData { Item1 = BlendTypeEnum.PostPP, Item2 = new Vector2I(indexL, matrixID), Item3 = mat.textureID, Item4 = mat.bbColor, Item5 = new MyTuple <Vector2, Vector2, Vector2> ( mat.texBounds.Min, mat.texBounds.Min + new Vector2(0f, mat.texBounds.Size.Y), mat.texBounds.Max ), Item6 = new MyTuple <Vector3D, Vector3D, Vector3D> ( quad.Point0, quad.Point1, quad.Point2 ), }; var bbR = new TriangleBillboardData { Item1 = BlendTypeEnum.PostPP, Item2 = new Vector2I(indexR, matrixID), Item3 = mat.textureID, Item4 = mat.bbColor, Item5 = new MyTuple <Vector2, Vector2, Vector2> ( mat.texBounds.Min, mat.texBounds.Max, mat.texBounds.Min + new Vector2(mat.texBounds.Size.X, 0f) ), Item6 = new MyTuple <Vector3D, Vector3D, Vector3D> ( quad.Point0, quad.Point2, quad.Point3 ), }; bbDataBack.Add(bbL); bbDataBack.Add(bbR); if (indexR >= bbPool.Count) { instance.AddNewBB(indexR - (bbPool.Count - 1)); } MyTransparentGeometry.AddBillboard(bbPool[indexL], false); MyTransparentGeometry.AddBillboard(bbPool[indexR], false); }
public static void DrawTransparentCylinder(ref MatrixD worldMatrix, float radius1, float radius2, float length, Vector4 lineColor, Vector4 faceColor, int wireDivideRatio, float thickness, MyStringId?lineMaterial = null, MyStringId?faceMaterial = null) { Vector3D centerTop = Vector3D.Transform(new Vector3D(0, length / 2f, 0), ref worldMatrix); Vector3D centerBottom = Vector3D.Transform(new Vector3D(0, -length / 2f, 0), ref worldMatrix); Vector3D upDir = Vector3D.TransformNormal(new Vector3D(0, 1, 0), ref worldMatrix); upDir.Normalize(); Vector3D currTop = Vector3D.Zero; Vector3D currBottom = Vector3D.Zero; Vector3D prevTop = Vector3D.Zero; Vector3D prevBottom = Vector3D.Zero; float num = 360f / wireDivideRatio; for (int i = 0; i <= wireDivideRatio; i++) { float degrees = i * num; currTop.X = (float)(radius1 * Math.Cos(MathHelper.ToRadians(degrees))); currTop.Y = length / 2f; currTop.Z = (float)(radius1 * Math.Sin(MathHelper.ToRadians(degrees))); currBottom.X = (float)(radius2 * Math.Cos(MathHelper.ToRadians(degrees))); currBottom.Y = -length / 2f; currBottom.Z = (float)(radius2 * Math.Sin(MathHelper.ToRadians(degrees))); currTop = Vector3D.Transform(currTop, worldMatrix); currBottom = Vector3D.Transform(currBottom, worldMatrix); if (lineMaterial.HasValue) { MySimpleObjectDraw.DrawLine(currBottom, currTop, lineMaterial, ref lineColor, thickness); } if (i > 0) { if (lineMaterial.HasValue) { MySimpleObjectDraw.DrawLine(prevBottom, currBottom, lineMaterial, ref lineColor, thickness); MySimpleObjectDraw.DrawLine(prevTop, currTop, lineMaterial, ref lineColor, thickness); } if (faceMaterial.HasValue) { var quad = new MyQuadD() { Point0 = prevTop, Point1 = currTop, Point2 = currBottom, Point3 = prevBottom }; MyTransparentGeometry.AddQuad(faceMaterial.Value, ref quad, faceColor, ref currTop); MyTransparentGeometry.AddTriangleBillboard(centerTop, currTop, prevTop, upDir, upDir, upDir, Vector2.Zero, Vector2.Zero, Vector2.Zero, faceMaterial.Value, 0, currTop, faceColor); MyTransparentGeometry.AddTriangleBillboard(centerBottom, currBottom, prevBottom, -upDir, -upDir, -upDir, Vector2.Zero, Vector2.Zero, Vector2.Zero, faceMaterial.Value, 0, currBottom, faceColor); } } prevBottom = currBottom; prevTop = currTop; } }
void DrawSymmetry() { if (!Main.LocalToolHandler.SymmetryInputAvailable || !MyAPIGateway.CubeBuilder.UseSymmetry || Main.LocalToolHandler.AimedBlock == null) { return; } IMyCubeGrid selectedGrid = Main.LocalToolHandler.AimedBlock.CubeGrid; if (!selectedGrid.XSymmetryPlane.HasValue && !selectedGrid.YSymmetryPlane.HasValue && !selectedGrid.ZSymmetryPlane.HasValue) { return; } MatrixD matrix = selectedGrid.WorldMatrix; MyQuadD quad = new MyQuadD(); float gridSizeHalf = selectedGrid.GridSize * 0.5f; Vector3D gridSize = (Vector3I.One + (selectedGrid.Max - selectedGrid.Min)) * gridSizeHalf; if (selectedGrid.XSymmetryPlane.HasValue) { Vector3D center = matrix.Translation + matrix.Right * ((selectedGrid.XSymmetryPlane.Value.X * selectedGrid.GridSize) - (selectedGrid.XSymmetryOdd ? gridSizeHalf : 0)); Vector3D minY = matrix.Up * ((selectedGrid.Min.Y - 1.5f) * selectedGrid.GridSize); Vector3D maxY = matrix.Up * ((selectedGrid.Max.Y + 1.5f) * selectedGrid.GridSize); Vector3D minZ = matrix.Backward * ((selectedGrid.Min.Z - 1.5f) * selectedGrid.GridSize); Vector3D maxZ = matrix.Backward * ((selectedGrid.Max.Z + 1.5f) * selectedGrid.GridSize); quad.Point0 = center + maxY + maxZ; quad.Point1 = center + maxY + minZ; quad.Point2 = center + minY + minZ; quad.Point3 = center + minY + maxZ; MyTransparentGeometry.AddQuad(SYMMETRY_PLANES_MATERIAL, ref quad, Color.Red * SYMMETRY_PLANES_ALPHA, ref center, blendType: SYMMETRY_PLANES_BLENDTYPE); } if (selectedGrid.YSymmetryPlane.HasValue) { Vector3D center = matrix.Translation + matrix.Up * ((selectedGrid.YSymmetryPlane.Value.Y * selectedGrid.GridSize) - (selectedGrid.YSymmetryOdd ? gridSizeHalf : 0)); Vector3D minZ = matrix.Backward * ((selectedGrid.Min.Z - 1.5f) * selectedGrid.GridSize); Vector3D maxZ = matrix.Backward * ((selectedGrid.Max.Z + 1.5f) * selectedGrid.GridSize); Vector3D minX = matrix.Right * ((selectedGrid.Min.X - 1.5f) * selectedGrid.GridSize); Vector3D maxX = matrix.Right * ((selectedGrid.Max.X + 1.5f) * selectedGrid.GridSize); quad.Point0 = center + maxZ + maxX; quad.Point1 = center + maxZ + minX; quad.Point2 = center + minZ + minX; quad.Point3 = center + minZ + maxX; MyTransparentGeometry.AddQuad(SYMMETRY_PLANES_MATERIAL, ref quad, Color.Green * SYMMETRY_PLANES_ALPHA, ref center, blendType: SYMMETRY_PLANES_BLENDTYPE); } if (selectedGrid.ZSymmetryPlane.HasValue) { Vector3D center = matrix.Translation + matrix.Backward * ((selectedGrid.ZSymmetryPlane.Value.Z * selectedGrid.GridSize) + (selectedGrid.ZSymmetryOdd ? gridSizeHalf : 0)); Vector3D minY = matrix.Up * ((selectedGrid.Min.Y - 1.5f) * selectedGrid.GridSize); Vector3D maxY = matrix.Up * ((selectedGrid.Max.Y + 1.5f) * selectedGrid.GridSize); Vector3D minX = matrix.Right * ((selectedGrid.Min.X - 1.5f) * selectedGrid.GridSize); Vector3D maxX = matrix.Right * ((selectedGrid.Max.X + 1.5f) * selectedGrid.GridSize); quad.Point0 = center + maxY + maxX; quad.Point1 = center + maxY + minX; quad.Point2 = center + minY + minX; quad.Point3 = center + minY + maxX; MyTransparentGeometry.AddQuad(SYMMETRY_PLANES_MATERIAL, ref quad, Color.Blue * SYMMETRY_PLANES_ALPHA, ref center, blendType: SYMMETRY_PLANES_BLENDTYPE); } }
public void Draw(bool closestToCamera) { if (face.water == null || face.water.planet == null) { return; } //if (WaterUtils.IsUnderGround(face.water.planet, face.position + (Vector3D.Normalize(position + ((-face.axisA + -face.axisB) * radius) - face.position) * face.water.currentRadius), radius)) //return; if (children != null) { foreach (var child in children) { child.Draw(closestToCamera); } } else { Vector3D normal1 = Vector3D.Normalize(position + ((-face.axisA + -face.axisB) * radius) - face.position); Vector3D normal2 = Vector3D.Normalize(position + ((face.axisA + face.axisB) * radius) - face.position); Vector3D normal3 = Vector3D.Normalize(position + ((-face.axisA + face.axisB) * radius) - face.position); Vector3D normal4 = Vector3D.Normalize(position + ((face.axisA + -face.axisB) * radius) - face.position); Vector3D corner1 = face.water.GetClosestSurfacePoint(face.position + (normal1 * face.water.currentRadius)); float distToCamera = Vector3.RectangularDistance(corner1, WaterMod.Session.CameraPosition); if (distToCamera > 100) { if (closestToCamera && (distToCamera > WaterMod.Session.DistanceToHorizon + (radius * 6))) { return; } if (Vector3.Dot((corner1 - WaterMod.Session.CameraPosition), WaterMod.Session.CameraRotation) < WaterData.DotMaxFOV) { return; } } Vector3D corner2 = face.water.GetClosestSurfacePoint(face.position + (normal2 * face.water.currentRadius)); Vector3D corner3 = face.water.GetClosestSurfacePoint(face.position + (normal3 * face.water.currentRadius)); Vector3D corner4 = face.water.GetClosestSurfacePoint(face.position + (normal4 * face.water.currentRadius)); Vector3D average = ((corner1 + corner2 + corner3 + corner4) / 4.0); if (face.water.planet != null) { MyPlanet planet = face.water.planet; if (WaterUtils.GetAltitude(planet, average) < -radius * 2 && (planet.GetMaterialAt(ref average) != null && planet.GetMaterialAt(ref corner1) != null && planet.GetMaterialAt(ref corner2) != null && planet.GetMaterialAt(ref corner3) != null && planet.GetMaterialAt(ref corner4) != null)) { return; } } Vector4 WaterColor = WaterData.WaterColor; Vector4 WaterFadeColor = WaterData.WaterFadeColor; Vector4 WhiteColor = Vector4.One; float dot = face.water.lit ? MyMath.Clamp(Vector3.Dot(normal1, WaterMod.Session.SunDirection) + 0.22f, 0.22f, 1f) : 1; if (face.water.lit) { WaterColor *= dot; WaterColor.W = WaterData.WaterColor.W; WaterFadeColor *= dot; WaterFadeColor.W = WaterData.WaterFadeColor.W; WhiteColor = new Vector4(dot, dot, dot, 1); } MyQuadD quad = new MyQuadD() { Point0 = corner1, Point1 = corner3, Point2 = corner2, Point3 = corner4 }; if (!WaterMod.Session.CameraUnderwater && closestToCamera) { if (face.water.enableFoam && radius < 128 * WaterMod.Settings.Quality) { Vector3D noisePosition = (average + (Vector3D.One * face.water.waveTimer)) * face.water.waveScale; float intensity = (float)MyMath.Clamp((face.water.noise.GetNoise(noisePosition.X, noisePosition.Y, noisePosition.Z) / 0.25f), 0, 1); if (intensity > 0.1f) { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref WaterData.FoamMaterials[textureId], ref quad, WhiteColor * intensity)); } if (intensity < 0.9f) { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref WaterData.FoamLightMaterials[textureId], ref quad, WhiteColor * (1f - (intensity * intensity)))); } } } if (face.water.transparent) { if (closestToCamera) { if (WaterMod.Session.CameraUnderwater) { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, WaterColor * 0.5f)); } else { if (detailLevel > 4) { int count = (int)Math.Max(Math.Min(Math.Ceiling((detailLevel - 2) * WaterMod.Settings.Quality), 8), 3); Vector3D layerSeperation = -normal1 * (1.0f / count) * 20f; for (int i = 0; i < count; i++) { if (i == count - 1) { quad.Point0 += layerSeperation; quad.Point1 += layerSeperation; quad.Point2 += layerSeperation; quad.Point3 += layerSeperation; WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WhiteColor)); } else { if (i == 0) { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WaterColor)); } else { quad.Point0 += layerSeperation; quad.Point1 += layerSeperation; quad.Point2 += layerSeperation; quad.Point3 += layerSeperation; WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WaterFadeColor)); } } } } else { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WhiteColor)); } } } else { if (WaterMod.Session.CameraUnderwater) { return; } else { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WaterColor)); Vector3D offset = normal1 * 100; quad.Point0 += offset; quad.Point1 += offset; quad.Point2 += offset; quad.Point3 += offset; WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WhiteColor)); } } } else { WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WhiteColor)); if (!WaterMod.Session.CameraUnderwater) { Vector3D Seperator = normal1 * face.water.waveHeight; quad.Point0 -= Seperator; quad.Point1 -= Seperator; quad.Point2 -= Seperator; quad.Point3 -= Seperator; WaterMod.Static.QuadBillboards.Push(new WaterMod.QuadBillboard(ref face.water.textureId, ref quad, ref WhiteColor)); } } } }
/// <summary> /// Draws a billboard in world space using the quad specified. /// </summary> public void Draw(ref MyQuadD quad) { minBoard.Draw(ref quad); }
// Return quad whos face is always looking to the camera. This is the real billboard, with perspective distortions! // Billboard's orientation is calculated by projecting unit sphere's north pole to billboard's plane. From this we can get up/right vectors. // Idea is this: if camera is in the middle of unit sphere and billboard is touching this sphere at some place (still unit sphere), we // know billboard's plan is perpendicular to the sphere, so if we want billboard's orientation to be like earth's latitude and Colatitude, // we need to find billboard's up vector in the direction. This is when projection cames into place. // Notice that we don't need camera left/up vector. We only need camera position. Because it's about the sphere around the player. Not camera orientation. // IMPORTANT: One problem of this approach is that if billboard is right above the player, its orientation will swing. Thats because we are projecting // Rotation is around vector pointing from camera position to center of the billboard. // the point, but it ends right in the billboard's centre. // So we not use this for particles. We use it only for background sphere (starts, galaxies) prerender. // Return false if billboard wasn't for any reason created (e.g. too close to the camera) public static bool GetBillboardQuadAdvancedRotated(out MyQuadD quad, Vector3D position, float radiusX, float radiusY, float angle, Vector3D cameraPosition) { // Optimized: Vector3 dirVector = MyMwcUtils.Normalize(position - cameraPosition); Vector3D dirVector; dirVector.X = (position.X - cameraPosition.X); dirVector.Y = (position.Y - cameraPosition.Y); dirVector.Z = (position.Z - cameraPosition.Z); // If distance to camera is really small don't draw it. if (dirVector.LengthSquared() <= MyMathConstants.EPSILON) { // Some empty quad quad = new MyQuadD(); return(false); } dirVector = MyUtils.Normalize(dirVector); Vector3D projectedPoint; // Project Up onto plane defined by origin and dirVector Vector3D.Reject(ref Vector3D.Up, ref dirVector, out projectedPoint); Vector3D upVector; if (projectedPoint.LengthSquared() <= MyMathConstants.EPSILON_SQUARED) { // If projected point equals to zero, we know billboard is exactly above or bottom of camera // and we can't calculate proper orientation. So we just select some direction. Good thing we // know is that billboard's plan ix XY, so we can choose any point on this plane upVector = Vector3D.Forward; } else { // Optimized: upVector = MyMwcUtils.Normalize(projectedPoint); MyUtils.Normalize(ref projectedPoint, out upVector); } // Optimized: Vector3 leftVector = MyMwcUtils.Normalize(Vector3.Cross(upVector, dirVector)); Vector3D leftVector; Vector3D.Cross(ref upVector, ref dirVector, out leftVector); leftVector = MyUtils.Normalize(leftVector); // Two main vectors of a billboard rotated around the view axis/vector float angleCos = (float)Math.Cos(angle); float angleSin = (float)Math.Sin(angle); Vector3D billboardAxisX; billboardAxisX.X = (radiusX * angleCos) * leftVector.X + (radiusY * angleSin) * upVector.X; billboardAxisX.Y = (radiusX * angleCos) * leftVector.Y + (radiusY * angleSin) * upVector.Y; billboardAxisX.Z = (radiusX * angleCos) * leftVector.Z + (radiusY * angleSin) * upVector.Z; Vector3D billboardAxisY; billboardAxisY.X = (-radiusX * angleSin) * leftVector.X + (radiusY * angleCos) * upVector.X; billboardAxisY.Y = (-radiusX * angleSin) * leftVector.Y + (radiusY * angleCos) * upVector.Y; billboardAxisY.Z = (-radiusX * angleSin) * leftVector.Z + (radiusY * angleCos) * upVector.Z; // Coordinates of four points of a billboard's quad quad.Point0.X = position.X + billboardAxisX.X + billboardAxisY.X; quad.Point0.Y = position.Y + billboardAxisX.Y + billboardAxisY.Y; quad.Point0.Z = position.Z + billboardAxisX.Z + billboardAxisY.Z; quad.Point1.X = position.X - billboardAxisX.X + billboardAxisY.X; quad.Point1.Y = position.Y - billboardAxisX.Y + billboardAxisY.Y; quad.Point1.Z = position.Z - billboardAxisX.Z + billboardAxisY.Z; quad.Point2.X = position.X - billboardAxisX.X - billboardAxisY.X; quad.Point2.Y = position.Y - billboardAxisX.Y - billboardAxisY.Y; quad.Point2.Z = position.Z - billboardAxisX.Z - billboardAxisY.Z; quad.Point3.X = position.X + billboardAxisX.X - billboardAxisY.X; quad.Point3.Y = position.Y + billboardAxisX.Y - billboardAxisY.Y; quad.Point3.Z = position.Z + billboardAxisX.Z - billboardAxisY.Z; return(true); }
public static bool GetBillboardQuadAdvancedRotated(out MyQuadD quad, Vector3D position, float radius, float angle, Vector3D cameraPosition) { return(GetBillboardQuadAdvancedRotated(out quad, position, radius, radius, angle, cameraPosition)); }
// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(VRageRender.MyBillboard billboard) { if (Pivot != null) { if (PivotRotation != null) { Matrix pivotRotationTransform = Matrix.CreateRotationX(MathHelper.ToRadians(m_actualPivotRotation.X) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationY(MathHelper.ToRadians(m_actualPivotRotation.Y) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationZ(MathHelper.ToRadians(m_actualPivotRotation.Z) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_actualPivot = Vector3.TransformNormal(m_actualPivot, pivotRotationTransform); } m_actualPivot = Vector3D.TransformNormal(m_actualPivot, m_generation.GetEffect().WorldMatrix); } var actualPosition = m_actualPosition + m_actualPivot; MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, actualPosition); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 0.1f) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); float actualAlphaCutout = 0; if (AlphaCutout != null) { MyTransparentGeometry.StartParticleProfilingBlock("AlphaCutout calculation"); AlphaCutout.GetInterpolatedValue <float>(m_normalizedTime, out actualAlphaCutout); MyTransparentGeometry.EndParticleProfilingBlock(); } billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = m_generation.GetEffect().LowRes || VRageRender.MyRenderConstants.RenderQualityProfile.LowResParticles; billboard.CustomViewProjection = -1; billboard.ParentID = -1; billboard.AlphaCutout = actualAlphaCutout; billboard.UVOffset = Vector2.Zero; billboard.UVSize = Vector2.One; float alpha = 1; Matrix transform = Matrix.Identity; Vector3 normal = Vector3.Forward; Vector3 actualVelocity = (Vector3)(m_actualPosition - m_previousPosition); float radiusBySpeed = m_generation.RadiusBySpeed; if (radiusBySpeed > 0) { float actualSpeed = actualVelocity.Length(); actualRadius = Math.Max(actualRadius, actualRadius * m_generation.RadiusBySpeed * actualSpeed); } if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); Vector2 actualRadiusV2 = new Vector2(actualRadius, actualRadius); if (Thickness > 0) { actualRadiusV2.Y = Thickness; } if (m_generation.RotationReference == MyRotationReference.Camera) { transform = Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, MyTransparentGeometry.Camera.Left, MyTransparentGeometry.Camera.Up); } else if (m_generation.RotationReference == MyRotationReference.Local) { transform = Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, m_generation.GetEffect().WorldMatrix.Left, m_generation.GetEffect().WorldMatrix.Up); } else if (m_generation.RotationReference == MyRotationReference.Velocity) { if (actualVelocity.LengthSquared() < 0.00001f) { return(false); } Matrix velocityRef = Matrix.CreateFromDir(Vector3.Normalize(actualVelocity)); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.VelocityAndCamera) { if (actualVelocity.LengthSquared() < 0.0001f) { return(false); } Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 velocityDir = Vector3.Normalize(actualVelocity); Vector3 sideVector = Vector3.Cross(cameraToPoint, velocityDir); Vector3 upVector = Vector3.Cross(sideVector, velocityDir); Matrix velocityRef = Matrix.CreateWorld(m_actualPosition, velocityDir, upVector); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.LocalAndCamera) { Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 localDir = m_generation.GetEffect().WorldMatrix.Forward; Vector3 sideVector = Vector3.Cross(cameraToPoint, localDir); Vector3 upVector = Vector3.Cross(sideVector, localDir); Matrix velocityRef = Matrix.CreateWorld(m_actualPosition, localDir, upVector); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else { System.Diagnostics.Debug.Fail("Unknown RotationReference enum"); } MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyUtils.GetRandomVector3Normalized(); } MyQuadD quad = new MyQuadD(); MyPolyLineD polyLine = new MyPolyLineD(); //polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); if (actualVelocity.LengthSquared() > 0) { polyLine.LineDirectionNormalized = MyUtils.Normalize(actualVelocity); } else { polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); } if (m_actualAngle.Z != 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(m_actualAngle.Z)); } polyLine.Point0 = actualPosition; polyLine.Point1.X = actualPosition.X - polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = actualPosition.Y - polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = actualPosition.Z - polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle.LengthSquared() > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out quad, ref polyLine, camPos); transform.Forward = polyLine.LineDirectionNormalized; billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; } else { throw new NotSupportedException(Type + " is not supported particle type"); } if (this.m_generation.AlphaAnisotropic) { normal = Vector3.Normalize(Vector3.Cross(billboard.Position0 - billboard.Position1, billboard.Position0 - billboard.Position2)); Vector3 forward = (billboard.Position0 + billboard.Position1 + billboard.Position2 + billboard.Position3) / 4 - MyTransparentGeometry.Camera.Translation; //Vector3 forward = MyTransparentGeometry.Camera.Forward; float angle = Math.Abs(Vector3.Dot(MyUtils.Normalize(forward), normal)); float alphaCone = 1 - (float)Math.Pow(1 - angle, 4); alpha = alphaCone; } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color = Vector4.One; if (Color.GetKeysCount() > 0) { Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); } if (m_arrayIndex != -1) { Vector3 arraySize = m_generation.ArraySize; if (arraySize.X > 0 && arraySize.Y > 0) { int arrayOffset = m_generation.ArrayOffset; int arrayModulo = m_generation.ArrayModulo == 0 ? (int)arraySize.X * (int)arraySize.Y : m_generation.ArrayModulo; m_arrayIndex = m_arrayIndex % arrayModulo + arrayOffset; float xDiv = 1.0f / arraySize.X; float yDiv = 1.0f / arraySize.Y; int xIndex = m_arrayIndex % (int)arraySize.X; int yIndex = m_arrayIndex / (int)arraySize.X; billboard.UVOffset = new Vector2(xDiv * xIndex, yDiv * yIndex); billboard.UVSize = new Vector2(xDiv, yDiv); } } var material1 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); var material2 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); if (material1 != null) { billboard.Material = material1.Name; } billboard.BlendMaterial = material2.Name; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; billboard.ColorIntensity = ColorIntensity; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
public static void DrawTransparentCylinder(ref MatrixD worldMatrix, float radiusBase, float radiusTop, float length, int wireDivideRatio, Vector4 faceColor, Vector4 lineColor, MyStringId?faceMaterial = null, MyStringId?lineMaterial = null, float lineThickness = 0.01f, BlendTypeEnum lineBlendType = BlendTypeEnum.Standard, BlendTypeEnum faceBlendType = BlendTypeEnum.Standard, bool capEnds = true) { Vector3D dir = worldMatrix.Forward; Vector3D centerBottom = worldMatrix.Translation; Vector3D centerTop = worldMatrix.Translation + dir * length; Vector3D currBottom = Vector3D.Zero; Vector3D currTop = Vector3D.Zero; Vector3D prevBottom = Vector3D.Zero; Vector3D prevTop = Vector3D.Zero; float stepDeg = 360f / wireDivideRatio; for (int i = 0; i <= wireDivideRatio; i++) { float angle = MathHelper.ToRadians(i * stepDeg); currBottom.X = radiusBase * Math.Cos(angle); currBottom.Y = radiusBase * Math.Sin(angle); currBottom.Z = 0; currBottom = Vector3D.Transform(currBottom, worldMatrix); currTop.X = radiusTop * Math.Cos(angle); currTop.Y = radiusTop * Math.Sin(angle); currTop.Z = -length; currTop = Vector3D.Transform(currTop, worldMatrix); if (lineMaterial.HasValue) { MyTransparentGeometry.AddLineBillboard(lineMaterial.Value, lineColor, currBottom, (currTop - currBottom), 1f, lineThickness, lineBlendType); } if (i > 0) { if (lineMaterial.HasValue) { MyTransparentGeometry.AddLineBillboard(lineMaterial.Value, lineColor, prevBottom, (currBottom - prevBottom), 1f, lineThickness, lineBlendType); MyTransparentGeometry.AddLineBillboard(lineMaterial.Value, lineColor, prevTop, (currTop - prevTop), 1f, lineThickness, lineBlendType); } if (faceMaterial.HasValue) { var quad = new MyQuadD() { Point0 = prevTop, Point1 = currTop, Point2 = currBottom, Point3 = prevBottom }; MyTransparentGeometry.AddQuad(faceMaterial.Value, ref quad, faceColor, ref currTop, blendType: faceBlendType); if (capEnds) { var color = faceColor.ToLinearRGB(); // HACK keeping color consistent with AddQuad() and AddLineBillboard() MyTransparentGeometry.AddTriangleBillboard(centerTop, currTop, prevTop, dir, dir, dir, Vector2.Zero, Vector2.Zero, Vector2.Zero, faceMaterial.Value, 0, currTop, color, faceBlendType); MyTransparentGeometry.AddTriangleBillboard(centerBottom, currBottom, prevBottom, -dir, -dir, -dir, Vector2.Zero, Vector2.Zero, Vector2.Zero, faceMaterial.Value, 0, currBottom, color, faceBlendType); } } } prevBottom = currBottom; prevTop = currTop; } }