/// <summary> /// Generates a single drawcall that renders a fullscreen quad using the specified material. /// Assumes that the <see cref="DrawDevice"/> is set up to render in screen space. /// </summary> /// <param name="material"></param> /// <param name="resizeMode"></param> public void AddFullscreenQuad(BatchInfo material, TargetResize resizeMode) { Texture tex = material.MainTexture.Res; Vector2 uvRatio = tex != null ? tex.UVRatio : Vector2.One; Point2 inputSize = tex != null ? tex.ContentSize : Point2.Zero; // Fit the input material rect to the output size according to rendering step config Vector2 targetSize = resizeMode.Apply(inputSize, this.TargetSize); Rect targetRect = Rect.Align( Alignment.Center, this.TargetSize.X * 0.5f, this.TargetSize.Y * 0.5f, targetSize.X, targetSize.Y); // Fit the target rect to actual pixel coordinates to avoid unnecessary filtering offsets targetRect.X = (int)targetRect.X; targetRect.Y = (int)targetRect.Y; targetRect.W = MathF.Ceiling(targetRect.W); targetRect.H = MathF.Ceiling(targetRect.H); VertexC1P3T2[] vertices = new VertexC1P3T2[4]; vertices[0].Pos = new Vector3(targetRect.LeftX, targetRect.TopY, 0.0f); vertices[1].Pos = new Vector3(targetRect.RightX, targetRect.TopY, 0.0f); vertices[2].Pos = new Vector3(targetRect.RightX, targetRect.BottomY, 0.0f); vertices[3].Pos = new Vector3(targetRect.LeftX, targetRect.BottomY, 0.0f); vertices[0].TexCoord = new Vector2(0.0f, 0.0f); vertices[1].TexCoord = new Vector2(uvRatio.X, 0.0f); vertices[2].TexCoord = new Vector2(uvRatio.X, uvRatio.Y); vertices[3].TexCoord = new Vector2(0.0f, uvRatio.Y); vertices[0].Color = ColorRgba.White; vertices[1].Color = ColorRgba.White; vertices[2].Color = ColorRgba.White; vertices[3].Color = ColorRgba.White; this.AddVertices(material, VertexMode.Quads, vertices); }
private void RenderSinglePass(Rect viewportRect, Pass p) { this.drawDevice.VisibilityMask = this.visibilityMask & p.VisibilityMask; this.drawDevice.RenderMode = p.MatrixMode; this.drawDevice.Target = p.Output; this.drawDevice.ViewportRect = p.Output.IsAvailable ? new Rect(p.Output.Res.Width, p.Output.Res.Height) : viewportRect; if (p.Input == null) { // Render Scene this.drawDevice.PrepareForDrawcalls(); try { this.CollectDrawcalls(); p.NotifyCollectDrawcalls(this.drawDevice); } catch (Exception e) { Log.Core.WriteError("There was an error while {0} was collecting drawcalls: {1}", this.ToString(), Log.Exception(e)); } this.drawDevice.Render(p.ClearFlags, p.ClearColor, p.ClearDepth); } else { Profile.TimePostProcessing.BeginMeasure(); this.drawDevice.PrepareForDrawcalls(); Texture mainTex = p.Input.MainTexture.Res; Vector2 uvRatio = mainTex != null ? mainTex.UVRatio : Vector2.One; Vector2 inputSize = mainTex != null ? new Vector2(mainTex.PixelWidth, mainTex.PixelHeight) : Vector2.One; Rect targetRect; if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor && !this.drawDevice.Target.IsAvailable) targetRect = Rect.Align(Alignment.Center, this.drawDevice.TargetSize.X * 0.5f, this.drawDevice.TargetSize.Y * 0.5f, inputSize.X, inputSize.Y); else targetRect = new Rect(this.drawDevice.TargetSize); IDrawDevice device = this.drawDevice; { VertexC1P3T2[] vertices = new VertexC1P3T2[4]; vertices[0].Pos = new Vector3(targetRect.LeftX, targetRect.TopY, 0.0f); vertices[1].Pos = new Vector3(targetRect.RightX, targetRect.TopY, 0.0f); vertices[2].Pos = new Vector3(targetRect.RightX, targetRect.BottomY, 0.0f); vertices[3].Pos = new Vector3(targetRect.LeftX, targetRect.BottomY, 0.0f); vertices[0].TexCoord = new Vector2(0.0f, 0.0f); vertices[1].TexCoord = new Vector2(uvRatio.X, 0.0f); vertices[2].TexCoord = new Vector2(uvRatio.X, uvRatio.Y); vertices[3].TexCoord = new Vector2(0.0f, uvRatio.Y); vertices[0].Color = ColorRgba.White; vertices[1].Color = ColorRgba.White; vertices[2].Color = ColorRgba.White; vertices[3].Color = ColorRgba.White; device.AddVertices(p.Input, VertexMode.Quads, vertices); } this.drawDevice.Render(p.ClearFlags, p.ClearColor, p.ClearDepth); Profile.TimePostProcessing.EndMeasure(); } }
/// <summary> /// Emits sets of vertices for glyphs and icons based on this formatted text. To render it, use each set of vertices combined with /// the corresponding Fonts <see cref="Material"/>. /// </summary> /// <param name="vertText">One set of vertices for each Font that is available to this FormattedText.</param> /// <param name="vertIcons">A set of icon vertices.</param> /// <returns> /// Returns an array of vertex counts for each emitted vertex array. /// Index 0 represents the number of emitted icon vertices, Index n represents the number of vertices emitted using Font n - 1. /// </returns> public int[] EmitVertices(ref VertexC1P3T2[][] vertText, ref VertexC1P3T2[] vertIcons) { this.ValidateVertexCache(); // Allocate memory if (vertIcons == null || vertIcons.Length < this.vertCountCache[0]) vertIcons = new VertexC1P3T2[this.vertCountCache[0]]; if (vertText == null || vertText.Length != this.vertTextCache.Length) vertText = new VertexC1P3T2[this.vertTextCache.Length][]; for (int i = 0; i < this.vertTextCache.Length; i++) { if (vertText[i] == null || vertText[i].Length < this.vertCountCache[i + 1]) vertText[i] = new VertexC1P3T2[this.vertCountCache[i + 1]]; } // Copy actual data int[] vertLen = new int[this.vertCountCache.Length]; Array.Copy(this.vertCountCache, vertLen, this.vertCountCache.Length); Array.Copy(this.vertIconsCache, vertIcons, vertLen[0]); for (int i = 0; i < this.vertTextCache.Length; i++) Array.Copy(this.vertTextCache[i], vertText[i], vertLen[i + 1]); return vertLen; }
/// <summary> /// Emits sets of vertices for glyphs and icons based on this formatted text. To render it, use each set of vertices combined with /// the corresponding Fonts <see cref="Material"/>. /// </summary> /// <param name="vertText">One set of vertices for each Font that is available to this ForattedText.</param> /// <param name="vertIcons">A set of icon vertices.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="z">An Z-Offset applied to the position of each emitted vertex.</param> /// <param name="clr">The color value that is applied to each emitted vertex.</param> /// <param name="xDot">Dot product base for the transformed vertices.</param> /// <param name="yDot">Dot product base for the transformed vertices.</param> /// <returns> /// Returns an array of vertex counts for each emitted vertex array. /// Index 0 represents the number of emitted icon vertices, Index n represents the number of vertices emitted using Font n - 1. /// </returns> public int[] EmitVertices(ref VertexC1P3T2[][] vertText, ref VertexC1P3T2[] vertIcons, float x, float y, float z, ColorRgba clr, Vector2 xDot, Vector2 yDot) { int[] vertLen = this.EmitVertices(ref vertText, ref vertIcons); Vector3 offset = new Vector3(x, y, z); if (clr == ColorRgba.White) { for (int i = 0; i < vertText.Length; i++) { for (int j = 0; j < vertLen[i + 1]; j++) { MathF.TransformDotVec(ref vertText[i][j].Pos, ref xDot, ref yDot); Vector3.Add(ref vertText[i][j].Pos, ref offset, out vertText[i][j].Pos); } } for (int i = 0; i < vertLen[0]; i++) { MathF.TransformDotVec(ref vertIcons[i].Pos, ref xDot, ref yDot); Vector3.Add(ref vertIcons[i].Pos, ref offset, out vertIcons[i].Pos); } } else { for (int i = 0; i < vertText.Length; i++) { for (int j = 0; j < vertLen[i + 1]; j++) { MathF.TransformDotVec(ref vertText[i][j].Pos, ref xDot, ref yDot); Vector3.Add(ref vertText[i][j].Pos, ref offset, out vertText[i][j].Pos); ColorRgba.Multiply(ref vertText[i][j].Color, ref clr, out vertText[i][j].Color); } } for (int i = 0; i < vertLen[0]; i++) { MathF.TransformDotVec(ref vertIcons[i].Pos, ref xDot, ref yDot); Vector3.Add(ref vertIcons[i].Pos, ref offset, out vertIcons[i].Pos); ColorRgba.Multiply(ref vertIcons[i].Color, ref clr, out vertIcons[i].Color); } } return vertLen; }
/// <summary> /// Emits sets of vertices for glyphs and icons based on this formatted text. To render it, use each set of vertices combined with /// the corresponding Fonts <see cref="Material"/>. /// </summary> /// <param name="vertText">One set of vertices for each Font that is available to this ForattedText.</param> /// <param name="vertIcons">A set of icon vertices.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="z">An Z-Offset applied to the position of each emitted vertex.</param> /// <param name="clr">The color value that is applied to each emitted vertex.</param> /// <param name="angle">An angle by which the text is rotated (before applying the offset).</param> /// <param name="scale">A factor by which the text is scaled (before applying the offset).</param> /// <returns> /// Returns an array of vertex counts for each emitted vertex array. /// Index 0 represents the number of emitted icon vertices, Index n represents the number of vertices emitted using Font n - 1. /// </returns> public int[] EmitVertices(ref VertexC1P3T2[][] vertText, ref VertexC1P3T2[] vertIcons, float x, float y, float z, ColorRgba clr, float angle = 0.0f, float scale = 1.0f) { Vector2 xDot, yDot; MathF.GetTransformDotVec(angle, scale, out xDot, out yDot); return this.EmitVertices(ref vertText, ref vertIcons, x, y, z, clr, xDot, yDot); }
/// <summary> /// Emits sets of vertices for glyphs and icons based on this formatted text. To render it, use each set of vertices combined with /// the corresponding Fonts <see cref="Material"/>. /// </summary> /// <param name="vertText">One set of vertices for each Font that is available to this ForattedText.</param> /// <param name="vertIcons">A set of icon vertices.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="z">An Z-Offset applied to the position of each emitted vertex.</param> /// <returns> /// Returns an array of vertex counts for each emitted vertex array. /// Index 0 represents the number of emitted icon vertices, Index n represents the number of vertices emitted using Font n - 1. /// </returns> public int[] EmitVertices(ref VertexC1P3T2[][] vertText, ref VertexC1P3T2[] vertIcons, float x, float y, float z = 0.0f) { return this.EmitVertices(ref vertText, ref vertIcons, x, y, z, ColorRgba.White); }
protected void PrepareVertices(ref VertexC1P3T2[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect) { Vector3 posTemp = this.gameobj.Transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(this.GameObj.Transform.Angle, scaleTemp, out xDot, out yDot); Rect rectTemp = this.rect.Transformed(this.gameobj.Transform.Scale, this.gameobj.Transform.Scale); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); float left = uvRect.X; float right = uvRect.RightX; float top = uvRect.Y; float bottom = uvRect.BottomY; if ((this.flipMode & FlipMode.Horizontal) != FlipMode.None) MathF.Swap(ref left, ref right); if ((this.flipMode & FlipMode.Vertical) != FlipMode.None) MathF.Swap(ref top, ref bottom); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T2[4]; vertices[0].Pos.X = posTemp.X + edge1.X; vertices[0].Pos.Y = posTemp.Y + edge1.Y; vertices[0].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[0].TexCoord.X = left; vertices[0].TexCoord.Y = top; vertices[0].Color = mainClr; vertices[1].Pos.X = posTemp.X + edge2.X; vertices[1].Pos.Y = posTemp.Y + edge2.Y; vertices[1].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[1].TexCoord.X = left; vertices[1].TexCoord.Y = bottom; vertices[1].Color = mainClr; vertices[2].Pos.X = posTemp.X + edge3.X; vertices[2].Pos.Y = posTemp.Y + edge3.Y; vertices[2].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[2].TexCoord.X = right; vertices[2].TexCoord.Y = bottom; vertices[2].Color = mainClr; vertices[3].Pos.X = posTemp.X + edge4.X; vertices[3].Pos.Y = posTemp.Y + edge4.Y; vertices[3].Pos.Z = posTemp.Z + this.VertexZOffset; vertices[3].TexCoord.X = right; vertices[3].TexCoord.Y = top; vertices[3].Color = mainClr; if (this.pixelGrid) { vertices[0].Pos.X = MathF.Round(vertices[0].Pos.X); vertices[1].Pos.X = MathF.Round(vertices[1].Pos.X); vertices[2].Pos.X = MathF.Round(vertices[2].Pos.X); vertices[3].Pos.X = MathF.Round(vertices[3].Pos.X); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { vertices[0].Pos.X += 0.5f; vertices[1].Pos.X += 0.5f; vertices[2].Pos.X += 0.5f; vertices[3].Pos.X += 0.5f; } vertices[0].Pos.Y = MathF.Round(vertices[0].Pos.Y); vertices[1].Pos.Y = MathF.Round(vertices[1].Pos.Y); vertices[2].Pos.Y = MathF.Round(vertices[2].Pos.Y); vertices[3].Pos.Y = MathF.Round(vertices[3].Pos.Y); if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { vertices[0].Pos.Y += 0.5f; vertices[1].Pos.Y += 0.5f; vertices[2].Pos.Y += 0.5f; vertices[3].Pos.Y += 0.5f; } } }
protected void PrepareVertices(ref VertexC1P3T2[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect) { Vector3 posTemp = this.gameobj.Transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(this.GameObj.Transform.Angle, scaleTemp, out xDot, out yDot); Rect rectTemp = this.rect.Transform(this.gameobj.Transform.Scale, this.gameobj.Transform.Scale); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T2[4]; vertices[0].SetVertex(posTemp.X + edge1.X, posTemp.Y + edge1.Y, posTemp.Z + this.VertexZOffset, uvRect.X, uvRect.Y, mainClr); vertices[1].SetVertex(posTemp.X + edge2.X, posTemp.Y + edge2.Y, posTemp.Z + this.VertexZOffset, uvRect.X, uvRect.MaximumY, mainClr); vertices[2].SetVertex(posTemp.X + edge3.X, posTemp.Y + edge3.Y, posTemp.Z + this.VertexZOffset, uvRect.MaximumX, uvRect.MaximumY, mainClr); vertices[3].SetVertex(posTemp.X + edge4.X, posTemp.Y + edge4.Y, posTemp.Z + this.VertexZOffset, uvRect.MaximumX, uvRect.Y, mainClr); if (this.pixelGrid) { vertices[0].Pos.X = MathF.Round(vertices[0].Pos.X); vertices[1].Pos.X = MathF.Round(vertices[1].Pos.X); vertices[2].Pos.X = MathF.Round(vertices[2].Pos.X); vertices[3].Pos.X = MathF.Round(vertices[3].Pos.X); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { vertices[0].Pos.X += 0.5f; vertices[1].Pos.X += 0.5f; vertices[2].Pos.X += 0.5f; vertices[3].Pos.X += 0.5f; } vertices[0].Pos.Y = MathF.Round(vertices[0].Pos.Y); vertices[1].Pos.Y = MathF.Round(vertices[1].Pos.Y); vertices[2].Pos.Y = MathF.Round(vertices[2].Pos.Y); vertices[3].Pos.Y = MathF.Round(vertices[3].Pos.Y); if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { vertices[0].Pos.Y += 0.5f; vertices[1].Pos.Y += 0.5f; vertices[2].Pos.Y += 0.5f; vertices[3].Pos.Y += 0.5f; } } }
protected internal override void OnCollectWorldOverlayDrawcalls(Canvas canvas) { base.OnCollectWorldOverlayDrawcalls(canvas); List<RigidBody> visibleColliders = this.QueryVisibleColliders().ToList(); RigidBody selectedBody = this.QuerySelectedCollider(); canvas.State.TextFont = Font.GenericMonospace10; canvas.State.TextInvariantScale = true; canvas.State.ZOffset = -0.5f; Font textFont = canvas.State.TextFont.Res; // Draw Shape layer foreach (RigidBody body in visibleColliders) { if (!body.Shapes.Any()) continue; float colliderAlpha = body == selectedBody ? 1.0f : (selectedBody != null ? 0.25f : 0.5f); float maxDensity = body.Shapes.Max(s => s.Density); float minDensity = body.Shapes.Min(s => s.Density); float avgDensity = (maxDensity + minDensity) * 0.5f; Vector3 objPos = body.GameObj.Transform.Pos; float objAngle = body.GameObj.Transform.Angle; float objScale = body.GameObj.Transform.Scale; int index = 0; foreach (ShapeInfo shape in body.Shapes) { CircleShapeInfo circle = shape as CircleShapeInfo; PolyShapeInfo poly = shape as PolyShapeInfo; ChainShapeInfo chain = shape as ChainShapeInfo; LoopShapeInfo loop = shape as LoopShapeInfo; ObjectEditorCamViewState editorState = this.View.ActiveState as ObjectEditorCamViewState; float shapeAlpha = colliderAlpha * (selectedBody == null || editorState == null || editorState.SelectedObjects.Any(sel => sel.ActualObject == shape) ? 1.0f : 0.5f); float densityRelative = MathF.Abs(maxDensity - minDensity) < 0.01f ? 1.0f : shape.Density / avgDensity; ColorRgba clr = shape.IsSensor ? this.ShapeSensorColor : this.ShapeColor; ColorRgba fontClr = this.FgColor; Vector2 center = Vector2.Zero; if (!body.IsAwake) clr = clr.ToHsva().WithSaturation(0.0f).ToRgba(); if (!shape.IsValid) clr = this.ShapeErrorColor; bool fillShape = (poly != null || circle != null); Vector2[] shapeVertices = null; if (poly != null) shapeVertices = poly .Vertices; else if (loop != null) shapeVertices = loop .Vertices; else if (chain != null) shapeVertices = chain.Vertices; if (circle != null) { Vector2 circlePos = circle.Position * objScale; MathF.TransformCoord(ref circlePos.X, ref circlePos.Y, objAngle); if (fillShape) { canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha))); canvas.FillCircle( objPos.X + circlePos.X, objPos.Y + circlePos.Y, objPos.Z, circle.Radius * objScale); } canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, clr.WithAlpha(shapeAlpha))); canvas.DrawCircle( objPos.X + circlePos.X, objPos.Y + circlePos.Y, objPos.Z, circle.Radius * objScale); center = circlePos; } else if (shapeVertices != null) { ColorRgba vertexFillColor = canvas.State.ColorTint * clr.WithAlpha((0.25f + densityRelative * 0.25f) * shapeAlpha); ColorRgba vertexOutlineColor = canvas.State.ColorTint * clr; // Prepare vertices to submit. We can't use higher-level canvas functionality // here, because we want direct control over the vertex mode. float viewSpaceScale = objScale; Vector3 viewSpacePos = objPos; canvas.DrawDevice.PreprocessCoords(ref viewSpacePos, ref viewSpaceScale); VertexC1P3T2[] drawVertices = new VertexC1P3T2[shapeVertices.Length]; for (int i = 0; i < drawVertices.Length; i++) { drawVertices[i].Pos.X = shapeVertices[i].X * viewSpaceScale + viewSpacePos.X; drawVertices[i].Pos.Y = shapeVertices[i].Y * viewSpaceScale + viewSpacePos.Y; drawVertices[i].Pos.Z = viewSpacePos.Z; drawVertices[i].Color = vertexOutlineColor; MathF.TransformCoord(ref drawVertices[i].Pos.X, ref drawVertices[i].Pos.Y, objAngle); } // Calculate the center coordinate for (int i = 0; i < drawVertices.Length; i++) center += shapeVertices[i]; center /= shapeVertices.Length; MathF.TransformCoord(ref center.X, ref center.Y, objAngle, objScale); // Make sure to render using an alpha material canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White)); // Fill the shape if (fillShape) { VertexC1P3T2[] fillVertices = drawVertices.Clone() as VertexC1P3T2[]; for (int i = 0; i < fillVertices.Length; i++) fillVertices[i].Color = vertexFillColor; canvas.DrawVertices(fillVertices, VertexMode.TriangleFan); } // Draw the outline canvas.DrawVertices(drawVertices, shape is ChainShapeInfo ? VertexMode.LineStrip : VertexMode.LineLoop); } // Draw shape index if (body == selectedBody) { string indexText = index.ToString(); Vector2 textSize = textFont.MeasureText(indexText); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, fontClr.WithAlpha((shapeAlpha + 1.0f) * 0.5f))); canvas.DrawText(indexText, objPos.X + center.X, objPos.Y + center.Y, objPos.Z); } index++; } // Draw center of mass if (body.BodyType == BodyType.Dynamic) { Vector2 localMassCenter = body.LocalMassCenter; MathF.TransformCoord(ref localMassCenter.X, ref localMassCenter.Y, objAngle, objScale); canvas.State.SetMaterial(new BatchInfo(DrawTechnique.Alpha, this.MassCenterColor.WithAlpha(colliderAlpha))); canvas.DrawLine( objPos.X + localMassCenter.X - 5.0f, objPos.Y + localMassCenter.Y, objPos.Z, objPos.X + localMassCenter.X + 5.0f, objPos.Y + localMassCenter.Y, objPos.Z); canvas.DrawLine( objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y - 5.0f, objPos.Z, objPos.X + localMassCenter.X, objPos.Y + localMassCenter.Y + 5.0f, objPos.Z); } } }
/// <summary> /// Emits a set of vertices based on a text. To render this text, simply use that set of vertices combined with /// the Fonts <see cref="Material"/>. /// </summary> /// <param name="text">The text to render.</param> /// <param name="vertices">The set of vertices that is emitted. You can re-use the same array each frame.</param> /// <returns>The number of emitted vertices. This values isn't necessarily equal to the emitted arrays length.</returns> public int EmitTextVertices(string text, ref VertexC1P3T2[] vertices) { int len = text.Length * 4; if (vertices == null || vertices.Length < len) vertices = new VertexC1P3T2[len]; float curOffset = 0.0f; GlyphData glyphData; Rect uvRect; float glyphXOff; float glyphXAdv; for (int i = 0; i < text.Length; i++) { this.ProcessTextAdv(text, i, out glyphData, out uvRect, out glyphXAdv, out glyphXOff); Vector2 glyphPos; glyphPos.X = MathF.Round(curOffset + glyphXOff); glyphPos.Y = MathF.Round(0.0f); vertices[i * 4 + 0].Pos.X = glyphPos.X; vertices[i * 4 + 0].Pos.Y = glyphPos.Y; vertices[i * 4 + 0].Pos.Z = 0.0f; vertices[i * 4 + 0].TexCoord = uvRect.TopLeft; vertices[i * 4 + 0].Color = ColorRgba.White; vertices[i * 4 + 1].Pos.X = glyphPos.X + glyphData.width; vertices[i * 4 + 1].Pos.Y = glyphPos.Y; vertices[i * 4 + 1].Pos.Z = 0.0f; vertices[i * 4 + 1].TexCoord = uvRect.TopRight; vertices[i * 4 + 1].Color = ColorRgba.White; vertices[i * 4 + 2].Pos.X = glyphPos.X + glyphData.width; vertices[i * 4 + 2].Pos.Y = glyphPos.Y + glyphData.height; vertices[i * 4 + 2].Pos.Z = 0.0f; vertices[i * 4 + 2].TexCoord = uvRect.BottomRight; vertices[i * 4 + 2].Color = ColorRgba.White; vertices[i * 4 + 3].Pos.X = glyphPos.X; vertices[i * 4 + 3].Pos.Y = glyphPos.Y + glyphData.height; vertices[i * 4 + 3].Pos.Z = 0.0f; vertices[i * 4 + 3].TexCoord = uvRect.BottomLeft; vertices[i * 4 + 3].Color = ColorRgba.White; curOffset += glyphXAdv; } return len; }
/// <summary> /// Emits a set of vertices based on a text. To render this text, simply use that set of vertices combined with /// the Fonts <see cref="Material"/>. /// </summary> /// <param name="text">The text to render.</param> /// <param name="vertices">The set of vertices that is emitted. You can re-use the same array each frame.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="clr">The color value that is applied to each emitted vertex.</param> /// <returns>The number of emitted vertices. This values isn't necessarily equal to the emitted arrays length.</returns> public int EmitTextVertices(string text, ref VertexC1P3T2[] vertices, float x, float y, ColorRgba clr) { int len = this.EmitTextVertices(text, ref vertices); Vector3 offset = new Vector3(x, y, 0); for (int i = 0; i < len; i++) { Vector3.Add(ref vertices[i].Pos, ref offset, out vertices[i].Pos); vertices[i].Color = clr; } return len; }
/// <summary> /// Emits a set of vertices based on a text. To render this text, simply use that set of vertices combined with /// the Fonts <see cref="Material"/>. /// </summary> /// <param name="text">The text to render.</param> /// <param name="vertices">The set of vertices that is emitted. You can re-use the same array each frame.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="z">An Z-Offset applied to the position of each emitted vertex.</param> /// <param name="clr">The color value that is applied to each emitted vertex.</param> /// <param name="angle">An angle by which the text is rotated (before applying the offset).</param> /// <param name="scale">A factor by which the text is scaled (before applying the offset).</param> /// <returns>The number of emitted vertices. This values isn't necessarily equal to the emitted arrays length.</returns> public int EmitTextVertices(string text, ref VertexC1P3T2[] vertices, float x, float y, float z, ColorRgba clr, float angle = 0.0f, float scale = 1.0f) { int len = this.EmitTextVertices(text, ref vertices); Vector3 offset = new Vector3(x, y, z); Vector2 xDot, yDot; MathF.GetTransformDotVec(angle, scale, out xDot, out yDot); for (int i = 0; i < len; i++) { MathF.TransformDotVec(ref vertices[i].Pos, ref xDot, ref yDot); Vector3.Add(ref vertices[i].Pos, ref offset, out vertices[i].Pos); vertices[i].Color = clr; } return len; }
/// <summary> /// Emits a set of vertices based on a text. To render this text, simply use that set of vertices combined with /// the Fonts <see cref="Material"/>. /// </summary> /// <param name="text">The text to render.</param> /// <param name="vertices">The set of vertices that is emitted. You can re-use the same array each frame.</param> /// <param name="x">An X-Offset applied to the position of each emitted vertex.</param> /// <param name="y">An Y-Offset applied to the position of each emitted vertex.</param> /// <param name="z">An Z-Offset applied to the position of each emitted vertex.</param> /// <returns>The number of emitted vertices. This values isn't necessarily equal to the emitted arrays length.</returns> public int EmitTextVertices(string text, ref VertexC1P3T2[] vertices, float x, float y, float z = 0.0f) { return this.EmitTextVertices(text, ref vertices, x, y, z, ColorRgba.White); }
public void Draw( IDrawDevice device ) { if( GameObj == null || !_loaded || Layers == null || Layers.Count == 0 ) return; Vector3 tempPos = GameObj.Transform.Pos; float tempScale = 1f; device.PreprocessCoords( ref tempPos, ref tempScale ); int halfMapW = W / 2; int halfMapH = H / 2; for (var i = Layers.Values.GetEnumerator(); i.MoveNext();) { var layer = i.Current; if (!layer.Visible) continue; for (int y = 0; y < H; y++) { for (int x = 0; x < W; x++) { // Is renderable tile available? int gid = layer.GetTile(x, y); if (gid <= 0) continue; // Get the correct tileset for this GID var tileset = FindTilesetByGID(gid); if (tileset == null) continue; // Remove tileset's FirstGID from the tile ID // so we get the correct position in the image. int tileX = (gid - tileset.FirstGID) % tileset.W; int tileY = (gid - tileset.FirstGID) / tileset.W; // Let 'em float... float tx = (float)tileX; float ty = (float)tileY; float tw = (float)TileW; float th = (float)TileH; float twp = (float)tileset.WPixel; float thp = (float)tileset.HPixel; var vertices = new VertexC1P3T2[4]; // Get tileset main color and set layer's opacity on it var color = tileset.Image.Res.MainColor.WithAlpha( layer.Opacity ); var uvRatio = tileset.Image.Res.MainTexture.Res.UVRatio; // Texture coordinates var uvRect = new Rect( uvRatio.X * (tx * tw) / twp, uvRatio.Y * (ty * th) / thp, uvRatio.X * tw / twp, uvRatio.Y * th / thp ); // Position float posX = tempPos.X + ((float)x - (float)halfMapW) * (float)TileW; float posY = tempPos.Y + ((float)y - (float)halfMapH) * (float)TileH; // Bottom-left vertices[0] = new VertexC1P3T2(); vertices[0].Pos.X = (posX - tw / 2) * tempScale; vertices[0].Pos.Y = (posY + th / 2) * tempScale; vertices[0].Pos.Z = tempPos.Z; vertices[0].TexCoord.X = uvRect.LeftX; vertices[0].TexCoord.Y = uvRect.BottomY; vertices[0].Color = color; // Top-left vertices[1] = new VertexC1P3T2(); vertices[1].Pos.X = (posX - tw / 2) * tempScale; vertices[1].Pos.Y = (posY - th / 2) * tempScale; vertices[1].Pos.Z = tempPos.Z; vertices[1].TexCoord.X = uvRect.LeftX; vertices[1].TexCoord.Y = uvRect.TopY; vertices[1].Color = color; // Top-right vertices[2] = new VertexC1P3T2(); vertices[2].Pos.X = (posX + tw / 2) * tempScale; vertices[2].Pos.Y = (posY - th / 2) * tempScale; vertices[2].Pos.Z = tempPos.Z; vertices[2].TexCoord.X = uvRect.RightX; vertices[2].TexCoord.Y = uvRect.TopY; vertices[2].Color = color; // Bottom-right vertices[3] = new VertexC1P3T2(); vertices[3].Pos.X = (posX + tw / 2) * tempScale; vertices[3].Pos.Y = (posY + th / 2) * tempScale; vertices[3].Pos.Z = tempPos.Z; vertices[3].TexCoord.X = uvRect.RightX; vertices[3].TexCoord.Y = uvRect.BottomY; vertices[3].Color = color; device.AddVertices(tileset.Image, VertexMode.Quads, vertices); } } } }
private void PrepareVertices(ref VertexC1P3T2[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect) { Transform transform = this.GameObj.Transform; Vector3 posTemp = transform.Pos; float scaleTemp = transform.Scale; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(transform.Angle, scaleTemp, out xDot, out yDot); Vector2 edge1 = this.rect.TopLeft; Vector2 edge2 = this.rect.BottomLeft; Vector2 edge3 = this.rect.BottomRight; Vector2 edge4 = this.rect.TopRight; MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); MathF.TransformDotVec(ref edge2, ref xDot, ref yDot); MathF.TransformDotVec(ref edge3, ref xDot, ref yDot); MathF.TransformDotVec(ref edge4, ref xDot, ref yDot); float uvLeft = uvRect.X; float uvRight = uvRect.RightX; float uvTop = uvRect.Y; float uvBottom = uvRect.BottomY; if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T2[4]; vertices[0].Pos.X = posTemp.X + edge1.X; vertices[0].Pos.Y = posTemp.Y + edge1.Y - this.height; vertices[0].Pos.Z = posTemp.Z; vertices[0].TexCoord.X = uvLeft; vertices[0].TexCoord.Y = uvTop; vertices[0].Color = mainClr; vertices[1].Pos.X = posTemp.X + edge2.X; vertices[1].Pos.Y = posTemp.Y + edge2.Y - this.height; vertices[1].Pos.Z = posTemp.Z; vertices[1].TexCoord.X = uvLeft; vertices[1].TexCoord.Y = uvBottom; vertices[1].Color = mainClr; vertices[2].Pos.X = posTemp.X + edge3.X; vertices[2].Pos.Y = posTemp.Y + edge3.Y - this.height; vertices[2].Pos.Z = posTemp.Z; vertices[2].TexCoord.X = uvRight; vertices[2].TexCoord.Y = uvBottom; vertices[2].Color = mainClr; vertices[3].Pos.X = posTemp.X + edge4.X; vertices[3].Pos.Y = posTemp.Y + edge4.Y - this.height; vertices[3].Pos.Z = posTemp.Z; vertices[3].TexCoord.X = uvRight; vertices[3].TexCoord.Y = uvTop; vertices[3].Color = mainClr; // Apply depth offsets float depthPerUnit = -this.depthScale; if (this.isVertical) { // Vertical actors share the same depth offset on all four vertices float baseDepthOffset = this.offset + transform.Pos.Y * depthPerUnit; vertices[0].Pos.Z += baseDepthOffset; vertices[1].Pos.Z += baseDepthOffset; vertices[2].Pos.Z += baseDepthOffset; vertices[3].Pos.Z += baseDepthOffset; } else { // Flat actors need to apply depth individually per vertex float worldBaseY = transform.Pos.Y; vertices[0].Pos.Z += this.offset + (worldBaseY + edge1.Y * transform.Scale / scaleTemp + this.height) * depthPerUnit; vertices[1].Pos.Z += this.offset + (worldBaseY + edge2.Y * transform.Scale / scaleTemp + this.height) * depthPerUnit; vertices[2].Pos.Z += this.offset + (worldBaseY + edge3.Y * transform.Scale / scaleTemp + this.height) * depthPerUnit; vertices[3].Pos.Z += this.offset + (worldBaseY + edge4.Y * transform.Scale / scaleTemp + this.height) * depthPerUnit; } }