public int CalcPriority(IDrawDevice device) { if (!this.IsDirectional) { float uniformScale = this.GameObj.Transform.Scale; Vector3 pos = this.GameObj.Transform.Pos; float scale = 1.0f; device.PreprocessCoords(ref pos, ref scale); float planarDist = (this.GameObj.Transform.Pos.Xy - device.RefCoord.Xy).Length; float rangeFactor = 1.0f / (this.range * uniformScale); float distFactor = (MathF.Min(scale, 1.0f) * planarDist); float spotFactor; if (this.dir != Vector3.Zero) { spotFactor = 0.5f * (1.0f + Vector3.Dot((device.RefCoord - this.GameObj.Transform.Pos).Normalized, this.dir)); } else { spotFactor = 1.0f; } return(MathF.RoundToInt(1000000.0f * spotFactor * distFactor * MathF.Pow(rangeFactor, 1.5f) * MathF.Pow(1.0f / this.intensity, 0.5f))); } else { return(MathF.RoundToInt(100.0f * MathF.Pow(1.0f / this.intensity, 0.5f))); } }
public override void Draw(IDrawDevice device) { // Perform Camera space transformation Vector3 posBefore = this.GameObj.Transform.Pos; Vector3 posTemp = posBefore; float scaleTemp = 1.0f; device.PreprocessCoords(this, ref posTemp, ref scaleTemp); // Draw debug text VertexC1P3T2[] textVertices; textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Position (world): {0:0}, {1:0}, {2:0}", posBefore.X, posBefore.Y, posBefore.Z), ref textVertices, posTemp.X, posTemp.Y, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Position (cam): {0:0}, {1:0}, {2:0}", posTemp.X, posTemp.Y, posTemp.Z), ref textVertices, posTemp.X, posTemp.Y + 10, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Scale: {0:F}", scaleTemp), ref textVertices, posTemp.X, posTemp.Y + 20, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); // Draw position indicator device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.Red.WithAlpha(0.25f)), BeginMode.Quads, new VertexP3[] { new VertexP3(posTemp.X - 50.0f * scaleTemp, posTemp.Y - 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X + 50.0f * scaleTemp, posTemp.Y - 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X + 50.0f * scaleTemp, posTemp.Y + 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X - 50.0f * scaleTemp, posTemp.Y + 50.0f * scaleTemp, posTemp.Z) }); }
public override void Draw(IDrawDevice device) { Transform transform = this.GameObj.Transform; Vector3 posTemp = transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(transform.Angle, scaleTemp * transform.Scale, out xDot, out yDot); //MathF.TransformDotVec(ref edge1, ref xDot, ref yDot); this.vertices.Count = this.circleStepCount * 2; VertexC1P3T2[] vertexData = this.vertices.Data; for (int i = 0; i < this.circleStepCount; i++) { float percentage = (float)i / (float)(this.circleStepCount - 1); float angle = MathF.DegToRad(this.angleRangeDegree) * (percentage - 0.5f); Vector2 offsetOuter = Vector2.FromAngleLength(angle, this.outerRadius); Vector2 offsetInner = Vector2.FromAngleLength(angle, this.innerRadius); MathF.TransformDotVec(ref offsetOuter, ref xDot, ref yDot); MathF.TransformDotVec(ref offsetInner, ref xDot, ref yDot); float alpha = 1.0f; if (this.texHAlphaFade > 0.0f) { if (percentage < this.texHAlphaFade) { alpha = MathF.Clamp(percentage / this.texHAlphaFade, 0.0f, 1.0f); } else if (percentage > 1.0f - this.texHAlphaFade) { alpha = MathF.Clamp((1.0f - percentage) / this.texHAlphaFade, 0.0f, 1.0f); } } float horizontalOffsetAnim = ((float)Time.GameTimer.TotalSeconds * this.texHOffsetAnimSpeed) % 1.0f; vertexData[i * 2 + 0].Pos.X = posTemp.X + offsetInner.X; vertexData[i * 2 + 0].Pos.Y = posTemp.Y + offsetInner.Y; vertexData[i * 2 + 0].Pos.Z = posTemp.Z; vertexData[i * 2 + 0].TexCoord.X = percentage + horizontalOffsetAnim; vertexData[i * 2 + 0].TexCoord.Y = 1.0f; vertexData[i * 2 + 0].Color = ColorRgba.White.WithAlpha(alpha); vertexData[i * 2 + 1].Pos.X = posTemp.X + offsetOuter.X; vertexData[i * 2 + 1].Pos.Y = posTemp.Y + offsetOuter.Y; vertexData[i * 2 + 1].Pos.Z = posTemp.Z; vertexData[i * 2 + 1].TexCoord.X = percentage + horizontalOffsetAnim; vertexData[i * 2 + 1].TexCoord.Y = 0.0f; vertexData[i * 2 + 1].Color = ColorRgba.White.WithAlpha(alpha); } device.AddVertices(this.sharedMat, VertexMode.TriangleStrip, vertexData, this.vertices.Count); }
protected void PrepareVertices(ref VertexFormat.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 VertexFormat.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 = uvRect.X; vertices[0].TexCoord.Y = uvRect.Y; 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 = uvRect.X; vertices[1].TexCoord.Y = uvRect.MaxY; 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 = uvRect.MaxX; vertices[2].TexCoord.Y = uvRect.MaxY; 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 = uvRect.MaxX; vertices[3].TexCoord.Y = uvRect.Y; vertices[3].Color = mainClr; }
public override void Draw(IDrawDevice device) { Transform transform = this.GameObj.Transform; Vector3 posTemp = transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(transform.Angle, scaleTemp * transform.Scale, out xDot, out yDot); float angle = endPos.Angle; Vector2 startLeft = Vector2.FromAngleLength(angle - MathF.RadAngle90, this.startWidth * 0.5f); Vector2 startRight = Vector2.FromAngleLength(angle + MathF.RadAngle90, this.startWidth * 0.5f); Vector2 endLeft = this.endPos + Vector2.FromAngleLength(angle - MathF.RadAngle90, this.endWidth * 0.5f); Vector2 endRight = this.endPos + Vector2.FromAngleLength(angle + MathF.RadAngle90, this.endWidth * 0.5f); MathF.TransformDotVec(ref startLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref startRight, ref xDot, ref yDot); MathF.TransformDotVec(ref endLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref endRight, ref xDot, ref yDot); this.vertices[0].Pos.X = posTemp.X + startLeft.X; this.vertices[0].Pos.Y = posTemp.Y + startLeft.Y; this.vertices[0].Pos.Z = posTemp.Z; this.vertices[0].TexCoord.X = 0.0f; this.vertices[0].TexCoord.Y = 0.0f; this.vertices[0].Color = m_colorStart; this.vertices[1].Pos.X = posTemp.X + startRight.X; this.vertices[1].Pos.Y = posTemp.Y + startRight.Y; this.vertices[1].Pos.Z = posTemp.Z; this.vertices[1].TexCoord.X = 0.0f; this.vertices[1].TexCoord.Y = 0.0f; this.vertices[1].Color = m_colorStart; this.vertices[2].Pos.X = posTemp.X + endRight.X; this.vertices[2].Pos.Y = posTemp.Y + endRight.Y; this.vertices[2].Pos.Z = posTemp.Z; this.vertices[2].TexCoord.X = 0.0f; this.vertices[2].TexCoord.Y = 0.0f; this.vertices[2].Color = m_colorEnd; this.vertices[3].Pos.X = posTemp.X + endLeft.X; this.vertices[3].Pos.Y = posTemp.Y + endLeft.Y; this.vertices[3].Pos.Z = posTemp.Z; this.vertices[3].TexCoord.X = 0.0f; this.vertices[3].TexCoord.Y = 0.0f; this.vertices[3].Color = m_colorEnd; device.AddVertices(new BatchInfo(DrawTechnique.Add, ColorRgba.White), VertexMode.Quads, this.vertices); }
private void RenderAttachment(IDrawDevice device, ContentRef <Material> material, float[] boneVertices, GameObject gameObject, ColorRgba color, float[] uvs, float depth) { Vector3 position = gameObject.Transform.Pos; float actualScale = 1f * gameObject.Transform.Scale; device.PreprocessCoords(ref position, ref actualScale); var vertices = _vertexCache.Next(); vertices[0].Pos.X = position.X + boneVertices[RegionAttachment.X1] * actualScale; vertices[0].Pos.Y = position.Y + boneVertices[RegionAttachment.Y1] * actualScale; vertices[1].Pos.X = position.X + boneVertices[RegionAttachment.X2] * actualScale; vertices[1].Pos.Y = position.Y + boneVertices[RegionAttachment.Y2] * actualScale; vertices[2].Pos.X = position.X + boneVertices[RegionAttachment.X3] * actualScale; vertices[2].Pos.Y = position.Y + boneVertices[RegionAttachment.Y3] * actualScale; vertices[3].Pos.X = position.X + boneVertices[RegionAttachment.X4] * actualScale; vertices[3].Pos.Y = position.Y + boneVertices[RegionAttachment.Y4] * actualScale; vertices[0].TexCoord.X = uvs[RegionAttachment.X1]; vertices[0].TexCoord.Y = uvs[RegionAttachment.Y1]; vertices[1].TexCoord.X = uvs[RegionAttachment.X2]; vertices[1].TexCoord.Y = uvs[RegionAttachment.Y2]; vertices[2].TexCoord.X = uvs[RegionAttachment.X3]; vertices[2].TexCoord.Y = uvs[RegionAttachment.Y3]; vertices[3].TexCoord.X = uvs[RegionAttachment.X4]; vertices[3].TexCoord.Y = uvs[RegionAttachment.Y4]; vertices[0].Pos.Z = position.Z + depth; vertices[1].Pos.Z = position.Z + depth; vertices[2].Pos.Z = position.Z + depth; vertices[3].Pos.Z = position.Z + depth; vertices[0].Color = material.Res.MainColor * color; vertices[1].Color = material.Res.MainColor * color; vertices[2].Color = material.Res.MainColor * color; vertices[3].Color = material.Res.MainColor * color; device.AddVertices(material, VertexMode.Quads, vertices); }
void ICmpRenderer.Draw(IDrawDevice device) { if (_inEditor) { if (FXArea != null) { Canvas c = new Canvas(device); FXArea.DrawInEditor(c); } } else { if (_particlesAlive > 0) { Vector3 posTemp = FXArea.GameObj.Transform.Pos; float scaleTemp = 1f; device.PreprocessCoords(ref posTemp, ref scaleTemp); int index = 0; foreach (Particle p in _particles) { if (p.IsAlive) { bool toDraw = DrawParticlesOffScreen || device.IsCoordInView(p.Position); if (toDraw) { p.UpdateVertices(device, posTemp, scaleTemp); Array.Copy(p.Vertices, 0, _particleVertices, index * 4, 4); } index++; } } device.AddVertices(_particleMaterial.Material, VertexMode.Quads, _particleVertices, index * 4); } } }
public override void Draw(IDrawDevice device) { // Perform Camera space transformation Vector3 posBefore = this.GameObj.Transform.Pos; Vector3 posTemp = posBefore; float scaleTemp = 1.0f; device.PreprocessCoords(this, ref posTemp, ref scaleTemp); // Draw debug text VertexC1P3T2[] textVertices; textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Position (world): {0:0}, {1:0}, {2:0}", posBefore.X, posBefore.Y, posBefore.Z), ref textVertices, posTemp.X, posTemp.Y, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Position (cam): {0:0}, {1:0}, {2:0}", posTemp.X, posTemp.Y, posTemp.Z), ref textVertices, posTemp.X, posTemp.Y + 10, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); textVertices = null; Font.GenericMonospace10.Res.EmitTextVertices( string.Format("Scale: {0:F}", scaleTemp), ref textVertices, posTemp.X, posTemp.Y + 20, posTemp.Z); device.AddVertices(Font.GenericMonospace10.Res.Material, BeginMode.Quads, textVertices); // Draw position indicator device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.Red.WithAlpha(0.25f)), BeginMode.Quads, new VertexP3[] { new VertexP3(posTemp.X - 50.0f * scaleTemp, posTemp.Y - 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X + 50.0f * scaleTemp, posTemp.Y - 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X + 50.0f * scaleTemp, posTemp.Y + 50.0f * scaleTemp, posTemp.Z), new VertexP3(posTemp.X - 50.0f * scaleTemp, posTemp.Y + 50.0f * scaleTemp, posTemp.Z) }); }
public void RenderTexturedBackground(IDrawDevice device, ref TileMapLayer layer, int cacheIndex, float x, float y) { if (cachedTexturedBackground == null || cachedTexturedBackgroundAnimated) { RecreateTexturedBackground(ref layer); } // Fit the input material rect to the output size according to rendering step config Vector3 renderPos = new Vector3(device.RefCoord.X - device.TargetSize.X / 2, device.RefCoord.Y - device.TargetSize.Y / 2, layer.Depth); float scale = 1.0f; device.PreprocessCoords(ref renderPos, ref scale); // Fit the target rect to actual pixel coordinates to avoid unnecessary filtering offsets renderPos.X = MathF.Round(renderPos.X); renderPos.Y = MathF.Round(renderPos.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { renderPos.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { //renderPos.Y += 0.5f; // AMD Bugfix? renderPos.Y -= 0.001f; } // Reserve the required space for vertex data in our locally cached buffer VertexC1P3T2[] vertexData; int neededVertices = 4; if (cachedVertices[cacheIndex] == null || cachedVertices[cacheIndex].Length < neededVertices) { cachedVertices[cacheIndex] = vertexData = new VertexC1P3T2[neededVertices]; } else { vertexData = cachedVertices[cacheIndex]; } // Render it as world-space fullscreen quad vertexData[0].Pos = new Vector3(renderPos.X, renderPos.Y, renderPos.Z); vertexData[1].Pos = new Vector3(renderPos.X + device.TargetSize.X, renderPos.Y, renderPos.Z); vertexData[2].Pos = new Vector3(renderPos.X + device.TargetSize.X, renderPos.Y + device.TargetSize.Y, renderPos.Z); vertexData[3].Pos = new Vector3(renderPos.X, renderPos.Y + device.TargetSize.Y, renderPos.Z); vertexData[0].TexCoord = new Vector2(0.0f, 0.0f); vertexData[1].TexCoord = new Vector2(1f, 0.0f); vertexData[2].TexCoord = new Vector2(1f, 1f); vertexData[3].TexCoord = new Vector2(0.0f, 1f); vertexData[0].Color = vertexData[1].Color = vertexData[2].Color = vertexData[3].Color = ColorRgba.White; // Setup custom pixel shader BatchInfo material = new BatchInfo(texturedBackgroundShader, cachedTexturedBackground); material.SetValue("horizonColor", layer.BackgroundColor); material.SetValue("shift", new Vector2(x, y)); device.AddVertices(material, VertexMode.Quads, vertexData); }
public override void Draw(IDrawDevice device) { if (this.camComp.DrawDevice != device) { return; } List <VertexC1P3> vertices = new List <VertexC1P3>((2 * this.layerCount * this.starsPerLayer) * 2); float screenBoundRad = this.camComp.ViewBoundingRadius; float minZDist = this.camComp.NearZ + this.camComp.ParallaxRefDist / 50.0f; float stepTemp = this.TileSize; Vector2 minPos = new Vector2(-screenBoundRad, -screenBoundRad); Vector2 maxPos = new Vector2(screenBoundRad, screenBoundRad); // Iterate over star layers for (int layerIndex = 0; layerIndex < this.layerCount; layerIndex++) { StarLayer layer = this.starLayers[layerIndex]; // Determine the layers Z value & perform layer culling if too near float layerZ = this.layerDepth * ((float)layerIndex / (float)this.layerCount) - this.GameObj.Transform.Pos.Z; if (layerZ < 0.0f) { layerZ += this.layerDepth * (float)(1 + (int)(-layerZ / this.layerDepth)); } layerZ = layerZ % this.layerDepth; if (layerZ <= this.GameObj.Transform.Pos.Z + minZDist) { continue; } // Calculate transform data Vector3 posTemp = this.GameObj.Transform.Pos + Vector3.UnitZ * layerZ; Vector3 posTempTrail = this.GameObj.Transform.Pos + Vector3.UnitZ * (layerZ + this.GameObj.Transform.Vel.Z * this.trailLength); float scaleTemp = 1.0f; float scaleTempTrail = 1.0f; device.PreprocessCoords(this, ref posTemp, ref scaleTemp); device.PreprocessCoords(this, ref posTempTrail, ref scaleTempTrail); posTempTrail += new Vector3(this.GameObj.Transform.Vel.Xy * this.trailLength); // Prepare this layers transformation to calculate a stars trail position. Vector2 starPosTempTrailDotX; Vector2 starPosTempTrailDotY; MathF.GetTransformDotVec(this.GameObj.Transform.AngleVel * this.trailLength, scaleTempTrail, out starPosTempTrailDotX, out starPosTempTrailDotY); // Iterate over stars for (int starIndex = 0; starIndex < layer.stars.Length; starIndex++) { // Since it's an endless starfield, each star may show up on multiple positions at once. It's tiled. StarInfo star = layer.stars[starIndex]; Vector2 starPosBase = star.pos - this.GameObj.Transform.Pos.Xy; // Move the topleft tiling corner to somewhere near the screens top left if (starPosBase.X > minPos.X) { starPosBase.X -= stepTemp * MathF.Ceiling((starPosBase.X - minPos.X) / stepTemp); } else if (starPosBase.X < minPos.X - stepTemp) { starPosBase.X -= stepTemp * MathF.Ceiling((starPosBase.X - minPos.X) / stepTemp); } if (starPosBase.Y > minPos.Y) { starPosBase.Y -= stepTemp * MathF.Ceiling((starPosBase.Y - minPos.Y) / stepTemp); } else if (starPosBase.Y < minPos.Y - stepTemp) { starPosBase.Y -= stepTemp * MathF.Ceiling((starPosBase.Y - minPos.Y) / stepTemp); } // Tiling! Vector2 startPos = starPosBase; while (starPosBase.X <= maxPos.X && starPosBase.Y <= maxPos.Y) { // Determine star pos and perform culling Vector3 starPosTemp = posTemp + new Vector3(starPosBase) * scaleTemp; if (starPosTemp.X > -screenBoundRad && starPosTemp.Y > -screenBoundRad && starPosTemp.X < screenBoundRad && starPosTemp.Y < screenBoundRad) { // Determine trail pos Vector3 starPosTempTrail = posTempTrail + new Vector3(starPosBase); MathF.TransformDotVec(ref starPosTempTrail, ref starPosTempTrailDotX, ref starPosTempTrailDotY); // Calculate length factor for the star's alpha value. Reduce alpha if too small or too big float lenTemp = (starPosTemp - starPosTempTrail).Length; if (lenTemp < 1.0f) { lenTemp = MathF.Max(0.25f, MathF.Sqrt(lenTemp)); } else if (lenTemp > 1.0f) { lenTemp = 1.0f / MathF.Pow(lenTemp, 0.25f); } // Determine the star's alpha value and generate its vertices (star and trail) float alpha = star.brightness * this.brightness * lenTemp * (1.0f - ((layerZ - minZDist) / (this.layerDepth - minZDist))); vertices.Add(new VertexC1P3(starPosTemp, ColorRgba.White.WithAlpha(alpha))); vertices.Add(new VertexC1P3(starPosTempTrail, ColorRgba.White.WithAlpha(alpha * 0.5f))); } // Advance X / Y grid starPosBase.X += stepTemp; if (starPosBase.X > maxPos.X) { starPosBase.X = startPos.X; starPosBase.Y += stepTemp; } } } } // Draw the stars all at once. Since they're not on the same Z layer, this may lead to wronz Z sorting // when interacting with a complex environment that needs Z-Sorting itsself. For this application, it should be sufficient. device.AddVertices(new BatchInfo(DrawTechnique.Add, ColorRgba.White), BeginMode.Lines, vertices.ToArray()); // (Can be fixed by drawing each layer in its own batch because they can be properly Z-sorted by Duality) }
public override void Draw(IDrawDevice device) { if (this.camComp.DrawDevice != device) return; List<VertexC1P3> vertices = new List<VertexC1P3>((2 * this.layerCount * this.starsPerLayer) * 2); float screenBoundRad = this.camComp.ViewBoundingRadius; float minZDist = this.camComp.NearZ + this.camComp.ParallaxRefDist / 50.0f; float stepTemp = this.TileSize; Vector2 minPos = new Vector2(-screenBoundRad, -screenBoundRad); Vector2 maxPos = new Vector2(screenBoundRad, screenBoundRad); // Iterate over star layers for (int layerIndex = 0; layerIndex < this.layerCount; layerIndex++) { StarLayer layer = this.starLayers[layerIndex]; // Determine the layers Z value & perform layer culling if too near float layerZ = this.layerDepth * ((float)layerIndex / (float)this.layerCount) - this.GameObj.Transform.Pos.Z; if (layerZ < 0.0f) layerZ += this.layerDepth * (float)(1 + (int)(-layerZ / this.layerDepth)); layerZ = layerZ % this.layerDepth; if (layerZ <= this.GameObj.Transform.Pos.Z + minZDist) continue; // Calculate transform data Vector3 posTemp = this.GameObj.Transform.Pos + Vector3.UnitZ * layerZ; Vector3 posTempTrail = this.GameObj.Transform.Pos + Vector3.UnitZ * (layerZ + this.GameObj.Transform.Vel.Z * this.trailLength); float scaleTemp = 1.0f; float scaleTempTrail = 1.0f; device.PreprocessCoords(this, ref posTemp, ref scaleTemp); device.PreprocessCoords(this, ref posTempTrail, ref scaleTempTrail); posTempTrail += new Vector3(this.GameObj.Transform.Vel.Xy * this.trailLength); // Prepare this layers transformation to calculate a stars trail position. Vector2 starPosTempTrailDotX; Vector2 starPosTempTrailDotY; MathF.GetTransformDotVec(this.GameObj.Transform.AngleVel * this.trailLength, scaleTempTrail, out starPosTempTrailDotX, out starPosTempTrailDotY); // Iterate over stars for (int starIndex = 0; starIndex < layer.stars.Length; starIndex++) { // Since it's an endless starfield, each star may show up on multiple positions at once. It's tiled. StarInfo star = layer.stars[starIndex]; Vector2 starPosBase = star.pos - this.GameObj.Transform.Pos.Xy; // Move the topleft tiling corner to somewhere near the screens top left if (starPosBase.X > minPos.X) starPosBase.X -= stepTemp * MathF.Ceiling((starPosBase.X - minPos.X) / stepTemp); else if (starPosBase.X < minPos.X - stepTemp) starPosBase.X -= stepTemp * MathF.Ceiling((starPosBase.X - minPos.X) / stepTemp); if (starPosBase.Y > minPos.Y) starPosBase.Y -= stepTemp * MathF.Ceiling((starPosBase.Y - minPos.Y) / stepTemp); else if (starPosBase.Y < minPos.Y - stepTemp) starPosBase.Y -= stepTemp * MathF.Ceiling((starPosBase.Y - minPos.Y) / stepTemp); // Tiling! Vector2 startPos = starPosBase; while (starPosBase.X <= maxPos.X && starPosBase.Y <= maxPos.Y) { // Determine star pos and perform culling Vector3 starPosTemp = posTemp + new Vector3(starPosBase) * scaleTemp; if (starPosTemp.X > -screenBoundRad && starPosTemp.Y > -screenBoundRad && starPosTemp.X < screenBoundRad && starPosTemp.Y < screenBoundRad) { // Determine trail pos Vector3 starPosTempTrail = posTempTrail + new Vector3(starPosBase); MathF.TransformDotVec(ref starPosTempTrail, ref starPosTempTrailDotX, ref starPosTempTrailDotY); // Calculate length factor for the star's alpha value. Reduce alpha if too small or too big float lenTemp = (starPosTemp - starPosTempTrail).Length; if (lenTemp < 1.0f) lenTemp = MathF.Max(0.25f, MathF.Sqrt(lenTemp)); else if (lenTemp > 1.0f) lenTemp = 1.0f / MathF.Pow(lenTemp, 0.25f); // Determine the star's alpha value and generate its vertices (star and trail) float alpha = star.brightness * this.brightness * lenTemp * (1.0f - ((layerZ - minZDist) / (this.layerDepth - minZDist))); vertices.Add(new VertexC1P3(starPosTemp, ColorRgba.White.WithAlpha(alpha))); vertices.Add(new VertexC1P3(starPosTempTrail, ColorRgba.White.WithAlpha(alpha * 0.5f))); } // Advance X / Y grid starPosBase.X += stepTemp; if (starPosBase.X > maxPos.X) { starPosBase.X = startPos.X; starPosBase.Y += stepTemp; } } } } // Draw the stars all at once. Since they're not on the same Z layer, this may lead to wronz Z sorting // when interacting with a complex environment that needs Z-Sorting itsself. For this application, it should be sufficient. device.AddVertices(new BatchInfo(DrawTechnique.Add, ColorRgba.White), BeginMode.Lines, vertices.ToArray()); // (Can be fixed by drawing each layer in its own batch because they can be properly Z-sorted by Duality) }
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; } // Snap to pixel grid { 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; } } }
private void DrawLayer(IDrawDevice device, ref TileMapLayer layer, int cacheIndex) { if (!layer.Visible) { return; } Vector2 viewSize = device.TargetSize; Vector3 viewCenter = device.RefCoord; Point2 tileCount = new Point2(layer.LayoutWidth, layer.Layout.Length / layer.LayoutWidth); Vector2 tileSize = new Vector2(tileset.TileSize, tileset.TileSize); // Update offsets for moving layers if (MathF.Abs(layer.AutoSpeedX) > 0) { layer.OffsetX += layer.AutoSpeedX * Time.TimeMult; if (layer.RepeatX) { if (layer.AutoSpeedX > 0) { while (layer.OffsetX > (tileCount.X * 32)) { layer.OffsetX -= (tileCount.X * 32); } } else { while (layer.OffsetX < 0) { layer.OffsetX += (tileCount.X * 32); } } } } if (MathF.Abs(layer.AutoSpeedY) > 0) { layer.OffsetY += layer.AutoSpeedY * Time.TimeMult; if (layer.RepeatY) { if (layer.AutoSpeedY > 0) { while (layer.OffsetY > (tileCount.Y * 32)) { layer.OffsetY -= (tileCount.Y * 32); } } else { while (layer.OffsetY < 0) { layer.OffsetY += (tileCount.Y * 32); } } } } // Get current layer offsets and speeds float loX = layer.OffsetX; float loY = layer.OffsetY - (layer.UseInherentOffset ? (viewSize.Y - 200) / 2 : 0); // Find out coordinates for a tile from outside the boundaries from topleft corner of the screen float x1 = viewCenter.X - 70 - (viewSize.X * 0.5f); float y1 = viewCenter.Y - 70 - (viewSize.Y * 0.5f); if (layer.BackgroundStyle != BackgroundStyle.Plain && tileCount.Y == 8 && tileCount.X == 8) { const float PerspectiveSpeedX = 0.4f; const float PerspectiveSpeedY = 0.16f; RenderTexturedBackground(device, ref layer, cacheIndex, (x1 * PerspectiveSpeedX + loX), (y1 * PerspectiveSpeedY + loY)); } else { // Figure out the floating point offset from the calculated coordinates and the actual tile // corner coordinates float xt = TranslateCoordinate(x1, layer.SpeedX, loX, false, viewSize.Y, viewSize.X); float yt = TranslateCoordinate(y1, layer.SpeedY, loY, true, viewSize.Y, viewSize.X); float remX = xt % 32f; float remY = yt % 32f; // Calculate the index (on the layer map) of the first tile that needs to be drawn to the // position determined earlier int tileX, tileY, tileAbsX, tileAbsY; // Get the actual tile coords on the layer layout if (xt > 0) { tileAbsX = (int)Math.Floor(xt / 32f); tileX = tileAbsX % tileCount.X; } else { tileAbsX = (int)Math.Ceiling(xt / 32f); tileX = tileAbsX % tileCount.X; while (tileX < 0) { tileX += tileCount.X; } } if (yt > 0) { tileAbsY = (int)Math.Floor(yt / 32f); tileY = tileAbsY % tileCount.Y; } else { tileAbsY = (int)Math.Ceiling(yt / 32f); tileY = tileAbsY % tileCount.Y; while (tileY < 0) { tileY += tileCount.Y; } } // update x1 and y1 with the remainder so that we start at the tile boundary // minus 1 because indices are updated in the beginning of the loops x1 -= remX - 32f; y1 -= remY - 32f; // Save the tile Y at the left border so that we can roll back to it at the start of // every row iteration int tileYs = tileY; // Calculate the last coordinates we want to draw to float x3 = x1 + 100 + viewSize.X; float y3 = y1 + 100 + viewSize.Y; Material material = null; Texture texture = null; ColorRgba mainColor = ColorRgba.White; // Reserve the required space for vertex data in our locally cached buffer VertexC1P3T2[] vertexData; int neededVertices = (int)((((x3 - x1) / 32) + 1) * (((y3 - y1) / 32) + 1) * 4); if (cachedVertices[cacheIndex] == null || cachedVertices[cacheIndex].Length < neededVertices) { cachedVertices[cacheIndex] = vertexData = new VertexC1P3T2[neededVertices]; } else { vertexData = cachedVertices[cacheIndex]; } int vertexBaseIndex = 0; int tile_xo = -1; for (float x2 = x1; x2 < x3; x2 += 32) { tileX = (tileX + 1) % tileCount.X; tile_xo++; if (!layer.RepeatX) { // If the current tile isn't in the first iteration of the layer horizontally, don't draw this column if (tileAbsX + tile_xo + 1 < 0 || tileAbsX + tile_xo + 1 >= tileCount.X) { continue; } } tileY = tileYs; int tile_yo = -1; for (float y2 = y1; y2 < y3; y2 += 32) { tileY = (tileY + 1) % tileCount.Y; tile_yo++; LayerTile tile = layer.Layout[tileX + tileY * layer.LayoutWidth]; if (!layer.RepeatY) { // If the current tile isn't in the first iteration of the layer vertically, don't draw it if (tileAbsY + tile_yo + 1 < 0 || tileAbsY + tile_yo + 1 >= tileCount.Y) { continue; } } Point2 offset; bool isFlippedX, isFlippedY; if (tile.IsAnimated) { if (tile.TileID < animatedTiles.Count) { offset = animatedTiles[tile.TileID].CurrentTile.MaterialOffset; isFlippedX = (animatedTiles[tile.TileID].CurrentTile.IsFlippedX != tile.IsFlippedX); isFlippedY = (animatedTiles[tile.TileID].CurrentTile.IsFlippedY != tile.IsFlippedY); //mainColor.A = tile.MaterialAlpha; mainColor.A = animatedTiles[tile.TileID].CurrentTile.MaterialAlpha; } else { continue; } } else { offset = tile.MaterialOffset; isFlippedX = tile.IsFlippedX; isFlippedY = tile.IsFlippedY; mainColor.A = tile.MaterialAlpha; } if (material != tile.Material) { // Submit all the vertices as one draw batch device.AddVertices( material, VertexMode.Quads, vertexData, 0, vertexBaseIndex); vertexBaseIndex = 0; material = tile.Material.Res; texture = material.MainTexture.Res; } Rect uvRect = new Rect( offset.X * texture.UVRatio.X / texture.ContentWidth, offset.Y * texture.UVRatio.Y / texture.ContentHeight, tileset.TileSize * texture.UVRatio.X / texture.ContentWidth, tileset.TileSize * texture.UVRatio.Y / texture.ContentHeight ); // ToDo: Flip normal map somehow if (isFlippedX) { uvRect.X += uvRect.W; uvRect.W *= -1; } if (isFlippedY) { uvRect.Y += uvRect.H; uvRect.H *= -1; } Vector3 renderPos = new Vector3(x2, y2, layer.Depth); float scale = 1.0f; device.PreprocessCoords(ref renderPos, ref scale); renderPos.X = MathF.Round(renderPos.X); renderPos.Y = MathF.Round(renderPos.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { renderPos.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { renderPos.Y += 0.5f; } vertexData[vertexBaseIndex + 0].Pos.X = renderPos.X; vertexData[vertexBaseIndex + 0].Pos.Y = renderPos.Y; vertexData[vertexBaseIndex + 0].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 0].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 0].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 0].Color = mainColor; vertexData[vertexBaseIndex + 1].Pos.X = renderPos.X; vertexData[vertexBaseIndex + 1].Pos.Y = renderPos.Y + tileSize.Y; vertexData[vertexBaseIndex + 1].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 1].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 1].TexCoord.Y = uvRect.Y + uvRect.H; vertexData[vertexBaseIndex + 1].Color = mainColor; vertexData[vertexBaseIndex + 2].Pos.X = renderPos.X + tileSize.X; vertexData[vertexBaseIndex + 2].Pos.Y = renderPos.Y + tileSize.Y; vertexData[vertexBaseIndex + 2].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 2].TexCoord.X = uvRect.X + uvRect.W; vertexData[vertexBaseIndex + 2].TexCoord.Y = uvRect.Y + uvRect.H; vertexData[vertexBaseIndex + 2].Color = mainColor; vertexData[vertexBaseIndex + 3].Pos.X = renderPos.X + tileSize.X; vertexData[vertexBaseIndex + 3].Pos.Y = renderPos.Y; vertexData[vertexBaseIndex + 3].Pos.Z = renderPos.Z; vertexData[vertexBaseIndex + 3].TexCoord.X = uvRect.X + uvRect.W; vertexData[vertexBaseIndex + 3].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 3].Color = mainColor; vertexBaseIndex += 4; } } // Submit all the vertices as one draw batch device.AddVertices( material, VertexMode.Quads, vertexData, 0, vertexBaseIndex); } }
protected void PrepareVerticesSmooth(ref VertexC1P3T4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext) { 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; float nextLeft = uvRectNext.X; float nextRight = uvRectNext.RightX; float nextTop = uvRectNext.Y; float nextBottom = uvRectNext.BottomY; if ((this.flipMode & FlipMode.Horizontal) != FlipMode.None) { edge1.X = -edge1.X; edge2.X = -edge2.X; edge3.X = -edge3.X; edge4.X = -edge4.X; } if ((this.flipMode & FlipMode.Vertical) != FlipMode.None) { edge1.Y = -edge1.Y; edge2.Y = -edge2.Y; edge3.Y = -edge3.Y; edge4.Y = -edge4.Y; } if (vertices == null || vertices.Length != 4) { vertices = new VertexC1P3T4A1[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].TexCoord.Z = nextLeft; vertices[0].TexCoord.W = nextTop; vertices[0].Color = mainClr; vertices[0].Attrib = curAnimFrameFade; 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].TexCoord.Z = nextLeft; vertices[1].TexCoord.W = nextBottom; vertices[1].Color = mainClr; vertices[1].Attrib = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[2].TexCoord.W = nextBottom; vertices[2].Color = mainClr; vertices[2].Attrib = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[3].TexCoord.W = nextTop; vertices[3].Color = mainClr; vertices[3].Attrib = curAnimFrameFade; 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; } } }
/// <summary> /// Determines the rectangular tile area that is visible to the specified <see cref="IDrawDevice"/>. /// </summary> /// <param name="device"></param> /// <param name="input"></param> /// <returns></returns> public static TileOutput GetVisibleTileRect(IDrawDevice device, TileInput input) { TileOutput output; // Determine the view space transform of the tilemap Vector3 objPos = input.TilemapPos; float objScale = input.TilemapScale; float cameraScaleAtObj = 1.0f; device.PreprocessCoords(ref objPos, ref cameraScaleAtObj); objScale *= cameraScaleAtObj; // Early-out, if so small that it might break the math behind rendering a single tile. if (objScale <= 0.000000001f) { return(EmptyOutput); } // Determine transformed X and Y axis in view and world space output.XAxisView = Vector2.UnitX; output.YAxisView = Vector2.UnitY; MathF.TransformCoord(ref output.XAxisView.X, ref output.XAxisView.Y, input.TilemapAngle, objScale); MathF.TransformCoord(ref output.YAxisView.X, ref output.YAxisView.Y, input.TilemapAngle, objScale); output.XAxisWorld = Vector2.UnitX; output.YAxisWorld = Vector2.UnitY; MathF.TransformCoord(ref output.XAxisWorld.X, ref output.XAxisWorld.Y, input.TilemapAngle, input.TilemapScale); MathF.TransformCoord(ref output.YAxisWorld.X, ref output.YAxisWorld.Y, input.TilemapAngle, input.TilemapScale); // Determine which tile is in the center of view space. Point2 viewCenterTile = Point2.Zero; { // Project the view center coordinate (view space zero) into the local space of the rendered tilemap Vector2 viewRenderStartPos = objPos.Xy; Vector2 localViewCenter = Vector2.Zero - viewRenderStartPos; localViewCenter = new Vector2( Vector2.Dot(localViewCenter, output.XAxisView.Normalized), Vector2.Dot(localViewCenter, output.YAxisView.Normalized)) / objScale; viewCenterTile = new Point2( (int)MathF.Floor(localViewCenter.X / input.TileSize.X), (int)MathF.Floor(localViewCenter.Y / input.TileSize.Y)); } // Determine the edge length of a square that is big enough to enclose the world space rect of the Camera view float visualAngle = input.TilemapAngle - device.RefAngle; Vector2 visualBounds = new Vector2( device.TargetSize.Y * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.X * MathF.Abs(MathF.Cos(visualAngle)), device.TargetSize.X * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.Y * MathF.Abs(MathF.Cos(visualAngle))); Vector2 localVisualBounds = visualBounds / cameraScaleAtObj; Point2 targetVisibleTileCount = new Point2( 3 + (int)MathF.Ceiling(localVisualBounds.X / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale)), 3 + (int)MathF.Ceiling(localVisualBounds.Y / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale))); // Determine the tile indices (xy) that are visible within that rect output.VisibleTileStart = new Point2( MathF.Max(viewCenterTile.X - targetVisibleTileCount.X / 2, 0), MathF.Max(viewCenterTile.Y - targetVisibleTileCount.Y / 2, 0)); Point2 tileGridEndPos = new Point2( MathF.Min(viewCenterTile.X + targetVisibleTileCount.X / 2, input.TileCount.X), MathF.Min(viewCenterTile.Y + targetVisibleTileCount.Y / 2, input.TileCount.Y)); output.VisibleTileCount = new Point2( MathF.Clamp(tileGridEndPos.X - output.VisibleTileStart.X, 0, input.TileCount.X), MathF.Clamp(tileGridEndPos.Y - output.VisibleTileStart.Y, 0, input.TileCount.Y)); // Determine start position for rendering output.RenderOriginView = objPos + new Vector3( output.VisibleTileStart.X * output.XAxisView * input.TileSize.X + output.VisibleTileStart.Y * output.YAxisView * input.TileSize.Y); output.RenderOriginWorld = input.TilemapPos + new Vector3( output.VisibleTileStart.X * output.XAxisWorld * input.TileSize.X + output.VisibleTileStart.Y * output.YAxisWorld * input.TileSize.Y); return(output); }
/// <summary> /// Determines the rectangular tile area that is visible to the specified <see cref="IDrawDevice"/>. /// </summary> /// <param name="device"></param> /// <param name="input"></param> /// <returns></returns> public static TileOutput GetVisibleTileRect(IDrawDevice device, TileInput input) { TileOutput output; // Determine the view space transform of the tilemap Vector3 objPos = input.TilemapPos; float objScale = input.TilemapScale; float cameraScaleAtObj = 1.0f; device.PreprocessCoords(ref objPos, ref cameraScaleAtObj); objScale *= cameraScaleAtObj; // Early-out, if so small that it might break the math behind rendering a single tile. if (objScale <= 0.000000001f) return EmptyOutput; // Determine transformed X and Y axis in view and world space output.XAxisView = Vector2.UnitX; output.YAxisView = Vector2.UnitY; MathF.TransformCoord(ref output.XAxisView.X, ref output.XAxisView.Y, input.TilemapAngle, objScale); MathF.TransformCoord(ref output.YAxisView.X, ref output.YAxisView.Y, input.TilemapAngle, objScale); output.XAxisWorld = Vector2.UnitX; output.YAxisWorld = Vector2.UnitY; MathF.TransformCoord(ref output.XAxisWorld.X, ref output.XAxisWorld.Y, input.TilemapAngle, input.TilemapScale); MathF.TransformCoord(ref output.YAxisWorld.X, ref output.YAxisWorld.Y, input.TilemapAngle, input.TilemapScale); // Determine which tile is in the center of view space. Point2 viewCenterTile = Point2.Zero; { // Project the view center coordinate (view space zero) into the local space of the rendered tilemap Vector2 viewRenderStartPos = objPos.Xy; Vector2 localViewCenter = Vector2.Zero - viewRenderStartPos; localViewCenter = new Vector2( Vector2.Dot(localViewCenter, output.XAxisView.Normalized), Vector2.Dot(localViewCenter, output.YAxisView.Normalized)) / objScale; viewCenterTile = new Point2( (int)MathF.Floor(localViewCenter.X / input.TileSize.X), (int)MathF.Floor(localViewCenter.Y / input.TileSize.Y)); } // Determine the edge length of a square that is big enough to enclose the world space rect of the Camera view float visualAngle = input.TilemapAngle - device.RefAngle; Vector2 visualBounds = new Vector2( device.TargetSize.Y * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.X * MathF.Abs(MathF.Cos(visualAngle)), device.TargetSize.X * MathF.Abs(MathF.Sin(visualAngle)) + device.TargetSize.Y * MathF.Abs(MathF.Cos(visualAngle))); Vector2 localVisualBounds = visualBounds / cameraScaleAtObj; Point2 targetVisibleTileCount = new Point2( 3 + (int)MathF.Ceiling(localVisualBounds.X / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale)), 3 + (int)MathF.Ceiling(localVisualBounds.Y / (MathF.Min(input.TileSize.X, input.TileSize.Y) * input.TilemapScale))); // Determine the tile indices (xy) that are visible within that rect output.VisibleTileStart = new Point2( MathF.Max(viewCenterTile.X - targetVisibleTileCount.X / 2, 0), MathF.Max(viewCenterTile.Y - targetVisibleTileCount.Y / 2, 0)); Point2 tileGridEndPos = new Point2( MathF.Min(viewCenterTile.X + targetVisibleTileCount.X / 2, input.TileCount.X), MathF.Min(viewCenterTile.Y + targetVisibleTileCount.Y / 2, input.TileCount.Y)); output.VisibleTileCount = new Point2( MathF.Clamp(tileGridEndPos.X - output.VisibleTileStart.X, 0, input.TileCount.X), MathF.Clamp(tileGridEndPos.Y - output.VisibleTileStart.Y, 0, input.TileCount.Y)); // Determine start position for rendering output.RenderOriginView = objPos + new Vector3( output.VisibleTileStart.X * output.XAxisView * input.TileSize.X + output.VisibleTileStart.Y * output.YAxisView * input.TileSize.Y); output.RenderOriginWorld = input.TilemapPos + new Vector3( output.VisibleTileStart.X * output.XAxisWorld * input.TileSize.X + output.VisibleTileStart.Y * output.YAxisWorld * input.TileSize.Y); return output; }
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); } } } }
protected void PrepareVertices(ref VertexFormat.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 VertexFormat.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 = uvRect.X; vertices[0].TexCoord.Y = uvRect.Y; 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 = uvRect.X; vertices[1].TexCoord.Y = uvRect.MaxY; 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 = uvRect.MaxX; vertices[2].TexCoord.Y = uvRect.MaxY; 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 = uvRect.MaxX; vertices[3].TexCoord.Y = uvRect.Y; vertices[3].Color = mainClr; }
public override void Draw(IDrawDevice device) { 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, this.gameobj.Transform.Scale * scaleTemp, out xDot, out yDot); // Apply block alignment Vector2 textOffset = Vector2.Zero; Vector2 textSize = this.text.Size; if (this.text.MaxWidth > 0) textSize.X = this.text.MaxWidth; this.blockAlign.ApplyTo(ref textOffset, textSize); MathF.TransformDotVec(ref textOffset, ref xDot, ref yDot); posTemp.X += textOffset.X; posTemp.Y += textOffset.Y; if (this.text.Fonts != null && this.text.Fonts.Any(r => r.IsAvailable && r.Res.IsPixelGridAligned)) { posTemp.X = MathF.Round(posTemp.X); posTemp.Y = MathF.Round(posTemp.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) posTemp.X += 0.5f; if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) posTemp.Y += 0.5f; } ColorRgba matColor = this.customMat != null ? this.customMat.MainColor : ColorRgba.White; int[] vertLen = this.text.EmitVertices(ref this.vertFont, ref this.vertIcon, posTemp.X, posTemp.Y, posTemp.Z + this.VertexZOffset, this.colorTint * matColor, xDot, yDot); if (this.text.Fonts != null) { for (int i = 0; i < this.text.Fonts.Length; i++) { if (this.text.Fonts[i] != null && this.text.Fonts[i].IsAvailable) { if (this.customMat == null) { device.AddVertices(this.text.Fonts[i].Res.Material, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } else { BatchInfo cm = new BatchInfo(this.customMat); cm.Textures = this.text.Fonts[i].Res.Material.Textures; device.AddVertices(cm, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } } } } if (this.text.Icons != null && this.iconMat.IsAvailable) { device.AddVertices(this.iconMat, VertexMode.Quads, this.vertIcon, vertLen[0]); } }
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; } }
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 override void PrepareVertices(IDrawDevice inDevice) { /******************** * 0 1 2 3 * 4 5 6 7 * 8 9 10 11 * 12 13 14 15 ********************/ if (_skin.Res != null) { WidgetSkin skin = _skin.Res; Vector3 posTemp = GameObj.Transform.Pos; float scaleTemp = 1.0f; inDevice.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; Vector2 xDotWorld, yDotWorld; MathF.GetTransformDotVec(GameObj.Transform.Angle, scaleTemp, out xDot, out yDot); MathF.GetTransformDotVec(GameObj.Transform.Angle, GameObj.Transform.Scale, out xDotWorld, out yDotWorld); Rect rectTemp = Rect.Transform(GameObj.Transform.Scale, GameObj.Transform.Scale); Vector2 topLeft = rectTemp.TopLeft; Vector2 bottomRight = rectTemp.BottomRight; Vector2 innerTopLeft = rectTemp.TopLeft + (new Vector2(skin.Border.X, skin.Border.Y) * GameObj.Transform.Scale); Vector2 innerBottomRight = rectTemp.BottomRight - (new Vector2(skin.Border.Z, skin.Border.W) * GameObj.Transform.Scale); _points[0].SceneCoords.X = topLeft.X; _points[0].SceneCoords.Y = topLeft.Y; _points[1].SceneCoords.X = innerTopLeft.X; _points[1].SceneCoords.Y = topLeft.Y; _points[2].SceneCoords.X = innerBottomRight.X; _points[2].SceneCoords.Y = topLeft.Y; _points[3].SceneCoords.X = bottomRight.X; _points[3].SceneCoords.Y = topLeft.Y; _points[4].SceneCoords.X = topLeft.X; _points[4].SceneCoords.Y = innerTopLeft.Y; _points[5].SceneCoords.X = innerTopLeft.X; _points[5].SceneCoords.Y = innerTopLeft.Y; _points[6].SceneCoords.X = innerBottomRight.X; _points[6].SceneCoords.Y = innerTopLeft.Y; _points[7].SceneCoords.X = bottomRight.X; _points[7].SceneCoords.Y = innerTopLeft.Y; _points[8].SceneCoords.X = topLeft.X; _points[8].SceneCoords.Y = innerBottomRight.Y; _points[9].SceneCoords.X = innerTopLeft.X; _points[9].SceneCoords.Y = innerBottomRight.Y; _points[10].SceneCoords.X = innerBottomRight.X; _points[10].SceneCoords.Y = innerBottomRight.Y; _points[11].SceneCoords.X = bottomRight.X; _points[11].SceneCoords.Y = innerBottomRight.Y; _points[12].SceneCoords.X = topLeft.X; _points[12].SceneCoords.Y = bottomRight.Y; _points[13].SceneCoords.X = innerTopLeft.X; _points[13].SceneCoords.Y = bottomRight.Y; _points[14].SceneCoords.X = innerBottomRight.X; _points[14].SceneCoords.Y = bottomRight.Y; _points[15].SceneCoords.X = bottomRight.X; _points[15].SceneCoords.Y = bottomRight.Y; for (int i = 0; i < _points.Length; i++) { _points[i].SceneCoords.Z = 0; _points[i].WorldCoords = _points[i].SceneCoords; MathF.TransformDotVec(ref _points[i].SceneCoords, ref xDot, ref yDot); MathF.TransformDotVec(ref _points[i].WorldCoords, ref xDotWorld, ref yDotWorld); _points[i].SceneCoords += posTemp; _points[i].WorldCoords += GameObj.Transform.Pos; } /** * Repositioning the pieces **/ /***************************** * 0 3| 4 7| 8 11 * * 1 2| 5 6| 9 10 * -- --+-- --+-- -- * 12 15|16 19|20 23 * * 13 14|17 18|21 22 * -- --+-- --+-- -- * 24 27|28 31|32 35 * * 25 26|29 30|33 34 *****************************/ _vertices[0].Pos = _points[0].SceneCoords; _vertices[0].TexCoord = _points[0].UVCoords; _vertices[0].Color = _tint; _vertices[1].Pos = _points[4].SceneCoords; _vertices[1].TexCoord = _points[4].UVCoords; _vertices[1].Color = _tint; _vertices[2].Pos = _points[5].SceneCoords; _vertices[2].TexCoord = _points[5].UVCoords; _vertices[2].Color = _tint; _vertices[3].Pos = _points[1].SceneCoords; _vertices[3].TexCoord = _points[1].UVCoords; _vertices[3].Color = _tint; _vertices[4].Pos = _points[1].SceneCoords; _vertices[4].TexCoord = _points[1].UVCoords; _vertices[4].Color = _tint; _vertices[5].Pos = _points[5].SceneCoords; _vertices[5].TexCoord = _points[5].UVCoords; _vertices[5].Color = _tint; _vertices[6].Pos = _points[6].SceneCoords; _vertices[6].TexCoord = _points[6].UVCoords; _vertices[6].Color = _tint; _vertices[7].Pos = _points[2].SceneCoords; _vertices[7].TexCoord = _points[2].UVCoords; _vertices[7].Color = _tint; _vertices[8].Pos = _points[2].SceneCoords; _vertices[8].TexCoord = _points[2].UVCoords; _vertices[8].Color = _tint; _vertices[9].Pos = _points[6].SceneCoords; _vertices[9].TexCoord = _points[6].UVCoords; _vertices[9].Color = _tint; _vertices[10].Pos = _points[7].SceneCoords; _vertices[10].TexCoord = _points[7].UVCoords; _vertices[10].Color = _tint; _vertices[11].Pos = _points[3].SceneCoords; _vertices[11].TexCoord = _points[3].UVCoords; _vertices[11].Color = _tint; _vertices[12].Pos = _points[4].SceneCoords; _vertices[12].TexCoord = _points[4].UVCoords; _vertices[12].Color = _tint; _vertices[13].Pos = _points[8].SceneCoords; _vertices[13].TexCoord = _points[8].UVCoords; _vertices[13].Color = _tint; _vertices[14].Pos = _points[9].SceneCoords; _vertices[14].TexCoord = _points[9].UVCoords; _vertices[14].Color = _tint; _vertices[15].Pos = _points[5].SceneCoords; _vertices[15].TexCoord = _points[5].UVCoords; _vertices[15].Color = _tint; _vertices[16].Pos = _points[5].SceneCoords; _vertices[16].TexCoord = _points[5].UVCoords; _vertices[16].Color = _tint; _vertices[17].Pos = _points[9].SceneCoords; _vertices[17].TexCoord = _points[9].UVCoords; _vertices[17].Color = _tint; _vertices[18].Pos = _points[10].SceneCoords; _vertices[18].TexCoord = _points[10].UVCoords; _vertices[18].Color = _tint; _vertices[19].Pos = _points[6].SceneCoords; _vertices[19].TexCoord = _points[6].UVCoords; _vertices[19].Color = _tint; _vertices[20].Pos = _points[6].SceneCoords; _vertices[20].TexCoord = _points[6].UVCoords; _vertices[20].Color = _tint; _vertices[21].Pos = _points[10].SceneCoords; _vertices[21].TexCoord = _points[10].UVCoords; _vertices[21].Color = _tint; _vertices[22].Pos = _points[11].SceneCoords; _vertices[22].TexCoord = _points[11].UVCoords; _vertices[22].Color = _tint; _vertices[23].Pos = _points[7].SceneCoords; _vertices[23].TexCoord = _points[7].UVCoords; _vertices[23].Color = _tint; _vertices[24].Pos = _points[8].SceneCoords; _vertices[24].TexCoord = _points[8].UVCoords; _vertices[24].Color = _tint; _vertices[25].Pos = _points[12].SceneCoords; _vertices[25].TexCoord = _points[12].UVCoords; _vertices[25].Color = _tint; _vertices[26].Pos = _points[13].SceneCoords; _vertices[26].TexCoord = _points[13].UVCoords; _vertices[26].Color = _tint; _vertices[27].Pos = _points[9].SceneCoords; _vertices[27].TexCoord = _points[9].UVCoords; _vertices[27].Color = _tint; _vertices[28].Pos = _points[9].SceneCoords; _vertices[28].TexCoord = _points[9].UVCoords; _vertices[28].Color = _tint; _vertices[29].Pos = _points[13].SceneCoords; _vertices[29].TexCoord = _points[13].UVCoords; _vertices[29].Color = _tint; _vertices[30].Pos = _points[14].SceneCoords; _vertices[30].TexCoord = _points[14].UVCoords; _vertices[30].Color = _tint; _vertices[31].Pos = _points[10].SceneCoords; _vertices[31].TexCoord = _points[10].UVCoords; _vertices[31].Color = _tint; _vertices[32].Pos = _points[10].SceneCoords; _vertices[32].TexCoord = _points[10].UVCoords; _vertices[32].Color = _tint; _vertices[33].Pos = _points[14].SceneCoords; _vertices[33].TexCoord = _points[14].UVCoords; _vertices[33].Color = _tint; _vertices[34].Pos = _points[15].SceneCoords; _vertices[34].TexCoord = _points[15].UVCoords; _vertices[34].Color = _tint; _vertices[35].Pos = _points[11].SceneCoords; _vertices[35].TexCoord = _points[11].UVCoords; _vertices[35].Color = _tint; if (VisibleRect != Rect.Empty && VisibleRect != Rect) { ApplyVisibilityRectangle(); } } }
protected void PrepareVerticesSmooth(ref VertexC1P3T4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext) { 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); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T4A1[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 = uvRect.X; vertices[0].TexCoord.Y = uvRect.Y; vertices[0].TexCoord.Z = uvRectNext.X; vertices[0].TexCoord.W = uvRectNext.Y; vertices[0].Color = mainClr; vertices[0].Attrib = curAnimFrameFade; 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 = uvRect.X; vertices[1].TexCoord.Y = uvRect.BottomY; vertices[1].TexCoord.Z = uvRectNext.X; vertices[1].TexCoord.W = uvRectNext.BottomY; vertices[1].Color = mainClr; vertices[1].Attrib = curAnimFrameFade; 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 = uvRect.RightX; vertices[2].TexCoord.Y = uvRect.BottomY; vertices[2].TexCoord.Z = uvRectNext.RightX; vertices[2].TexCoord.W = uvRectNext.BottomY; vertices[2].Color = mainClr; vertices[2].Attrib = curAnimFrameFade; 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 = uvRect.RightX; vertices[3].TexCoord.Y = uvRect.Y; vertices[3].TexCoord.Z = uvRectNext.RightX; vertices[3].TexCoord.W = uvRectNext.Y; vertices[3].Color = mainClr; vertices[3].Attrib = curAnimFrameFade; 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; } } }
public override void Draw(IDrawDevice device) { if (this.particles == null) return; Texture tex = this.RetrieveTexture(); if (tex == null) return; Vector2 particleHalfSize = this.particleSize * 0.5f; float objAngle; float objScale; Vector3 objPos; if (this.worldSpace) { objAngle = 0.0f; objScale = 1.0f; objPos = Vector3.Zero; } else { objAngle = this.GameObj.Transform.Angle; objScale = this.GameObj.Transform.Scale; objPos = this.GameObj.Transform.Pos; } Vector2 objXDot, objYDot; MathF.GetTransformDotVec(objAngle, objScale, out objXDot, out objYDot); if (this.vertexBuffer == null) this.vertexBuffer = new RawList<VertexC1P3T2>(this.particles.Count * 4); this.vertexBuffer.Count = this.vertexBuffer.Count = this.particles.Count * 4; VertexC1P3T2[] vertexData = this.vertexBuffer.Data; Particle[] particleData = this.particles.Data; int particleCount = this.particles.Count; for (int i = 0; i < particleCount; i++) { ColorRgba color = particleData[i].Color; float alpha = (float)color.A / 255.0f; if (this.fadeOutAt < 1.0f) alpha *= MathF.Clamp((1.0f - particleData[i].AgeFactor) / this.fadeOutAt, 0.0f, 1.0f); if (this.fadeInAt > 0.0f) alpha *= MathF.Clamp(particleData[i].AgeFactor / this.fadeInAt, 0.0f, 1.0f); color.A = (byte)(alpha * 255.0f); Rect uvRect; tex.LookupAtlas(particleData[i].SpriteIndex, out uvRect); Vector3 particlePos = particleData[i].Position; MathF.TransformDotVec(ref particlePos, ref objXDot, ref objYDot); particlePos += objPos; float particleAngle = objAngle + particleData[i].Angle; float particleScale = objScale; device.PreprocessCoords(ref particlePos, ref particleScale); Vector2 xDot, yDot; MathF.GetTransformDotVec(particleAngle, particleScale, out xDot, out yDot); Vector2 edgeTopLeft = new Vector2(-particleHalfSize.X, -particleHalfSize.Y); Vector2 edgeBottomLeft = new Vector2(-particleHalfSize.X, particleHalfSize.Y); Vector2 edgeBottomRight = new Vector2(particleHalfSize.X, particleHalfSize.Y); Vector2 edgeTopRight = new Vector2(particleHalfSize.X, -particleHalfSize.Y); MathF.TransformDotVec(ref edgeTopLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeBottomLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeBottomRight, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeTopRight, ref xDot, ref yDot); int vertexBaseIndex = i * 4; vertexData[vertexBaseIndex + 0].Pos.X = particlePos.X + edgeTopLeft.X; vertexData[vertexBaseIndex + 0].Pos.Y = particlePos.Y + edgeTopLeft.Y; vertexData[vertexBaseIndex + 0].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 0].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 0].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 0].Color = color; vertexData[vertexBaseIndex + 1].Pos.X = particlePos.X + edgeBottomLeft.X; vertexData[vertexBaseIndex + 1].Pos.Y = particlePos.Y + edgeBottomLeft.Y; vertexData[vertexBaseIndex + 1].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 1].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 1].TexCoord.Y = uvRect.BottomY; vertexData[vertexBaseIndex + 1].Color = color; vertexData[vertexBaseIndex + 2].Pos.X = particlePos.X + edgeBottomRight.X; vertexData[vertexBaseIndex + 2].Pos.Y = particlePos.Y + edgeBottomRight.Y; vertexData[vertexBaseIndex + 2].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 2].TexCoord.X = uvRect.RightX; vertexData[vertexBaseIndex + 2].TexCoord.Y = uvRect.BottomY; vertexData[vertexBaseIndex + 2].Color = color; vertexData[vertexBaseIndex + 3].Pos.X = particlePos.X + edgeTopRight.X; vertexData[vertexBaseIndex + 3].Pos.Y = particlePos.Y + edgeTopRight.Y; vertexData[vertexBaseIndex + 3].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 3].TexCoord.X = uvRect.RightX; vertexData[vertexBaseIndex + 3].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 3].Color = color; } device.AddVertices(this.material, VertexMode.Quads, vertexData, this.vertexBuffer.Count); }
protected internal override void OnCollectDrawcalls(Canvas canvas) { base.OnCollectDrawcalls(canvas); IDrawDevice device = canvas.DrawDevice; float scaleTemp = 1.0f; Vector3 posTemp = Vector3.Zero; device.PreprocessCoords(ref posTemp, ref scaleTemp); if (posTemp.Z <= canvas.DrawDevice.NearZ) { return; } float alphaTemp = 0.5f; alphaTemp *= (float)Math.Min(1.0d, ((posTemp.Z - device.NearZ) / (device.NearZ * 5.0f))); if (alphaTemp <= 0.005f) { return; } ColorRgba gridColor = this.FgColor.WithAlpha(alphaTemp); float gridVisualMinSize = 50.0f; Vector2 gridBaseSize = this.View.EditingUserGuides.GridSize.Xy; if (gridBaseSize.X <= 0.0f) { gridBaseSize.X = 100.0f; } if (gridBaseSize.Y <= 0.0f) { gridBaseSize.Y = 100.0f; } Vector2 adjustedGridBaseSize; adjustedGridBaseSize.X = gridBaseSize.X * MathF.NextPowerOfTwo((int)MathF.Ceiling(gridVisualMinSize / gridBaseSize.X)); adjustedGridBaseSize.Y = gridBaseSize.Y * MathF.NextPowerOfTwo((int)MathF.Ceiling(gridVisualMinSize / gridBaseSize.Y)); float scaleAdjustmentFactor = 4.0f * MathF.Pow(2.0f, -MathF.Round(1.0f - MathF.Log(1.0f / scaleTemp, 2.0f))); Vector2 adjustedGridSize; adjustedGridSize.X = MathF.Max(adjustedGridBaseSize.X * scaleAdjustmentFactor, gridBaseSize.X); adjustedGridSize.Y = MathF.Max(adjustedGridBaseSize.Y * scaleAdjustmentFactor, gridBaseSize.Y); Vector2 stepTemp = adjustedGridSize; Vector2 scaledStep = stepTemp * scaleTemp; float viewBoundRad = device.TargetSize.Length * 0.5f; int lineCountX = (2 + (int)MathF.Ceiling(viewBoundRad * 2 / scaledStep.X)) * 4; int lineCountY = (2 + (int)MathF.Ceiling(viewBoundRad * 2 / scaledStep.Y)) * 4; int vertexCount = (lineCountX * 2 + lineCountY * 2); if (this.vertexBuffer == null) { this.vertexBuffer = new RawList <VertexC1P3>(vertexCount); } this.vertexBuffer.Count = vertexCount; VertexC1P3[] vertices = this.vertexBuffer.Data; float beginPos; float pos; int lineIndex; int vertOff = 0; beginPos = posTemp.X % scaledStep.X - (lineCountX / 8) * scaledStep.X; pos = beginPos; lineIndex = 0; for (int x = 0; x < lineCountX; x++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + x * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + x * 2 + 0].Pos.X = pos; vertices[vertOff + x * 2 + 0].Pos.Y = -viewBoundRad; vertices[vertOff + x * 2 + 0].Pos.Z = posTemp.Z + 1; vertices[vertOff + x * 2 + 1] = vertices[vertOff + x * 2 + 0]; vertices[vertOff + x * 2 + 1].Pos.Y = viewBoundRad; pos += scaledStep.X / 4; lineIndex++; } vertOff += lineCountX * 2; beginPos = posTemp.Y % scaledStep.Y - (lineCountY / 8) * scaledStep.Y; pos = beginPos; lineIndex = 0; for (int y = 0; y < lineCountY; y++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + y * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + y * 2 + 0].Pos.X = -viewBoundRad; vertices[vertOff + y * 2 + 0].Pos.Y = pos; vertices[vertOff + y * 2 + 0].Pos.Z = posTemp.Z + 1; vertices[vertOff + y * 2 + 1] = vertices[vertOff + y * 2 + 0]; vertices[vertOff + y * 2 + 1].Pos.X = viewBoundRad; pos += scaledStep.Y / 4; lineIndex++; } vertOff += lineCountY * 2; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.Lines, vertices, this.vertexBuffer.Count); }
public override void Draw(IDrawDevice device) { 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, this.gameobj.Transform.Scale * scaleTemp, out xDot, out yDot); // Apply block alignment Vector2 textOffset = Vector2.Zero; Vector2 textSize = this.text.Size; if (this.text.MaxWidth > 0) textSize.X = this.text.MaxWidth; this.blockAlign.ApplyTo(ref textOffset, textSize); MathF.TransformDotVec(ref textOffset, ref xDot, ref yDot); posTemp.X += textOffset.X; posTemp.Y += textOffset.Y; if (this.text.Fonts != null && this.text.Fonts.Any(r => r.IsAvailable && r.Res.IsPixelGridAligned)) { posTemp.X = MathF.Round(posTemp.X); posTemp.Y = MathF.Round(posTemp.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) posTemp.X += 0.5f; if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) posTemp.Y += 0.5f; } // Draw design time metrics data if (DualityApp.ExecContext == DualityApp.ExecutionContext.Editor) { bool showLimits = true; bool showLines = false; bool showElements = false; Vector3 metricsOffset = new Vector3(0.0f, 0.0f, 0.01f); Vector3 lineOffset = new Vector3(0.5f, 0.5f, 0.0f); Vector3 tUnitX = Vector3.UnitX; Vector3 tUnitY = Vector3.UnitY; MathF.TransformDotVec(ref tUnitX, ref xDot, ref yDot); MathF.TransformDotVec(ref tUnitY, ref xDot, ref yDot); // Actual text size and maximum text size if (showLimits) { Vector3 textWidth = tUnitX * this.text.Size.X; Vector3 textHeight = tUnitY * this.text.Size.Y; Vector3 textMaxWidth = tUnitX * this.text.MaxWidth; Vector3 textMaxHeight = tUnitY * MathF.Max(this.text.MaxHeight, this.text.Size.Y); ColorRgba clrSize = ColorRgba.Green.WithAlpha(128); ColorRgba clrMaxSize = ColorRgba.Red.WithAlpha(128); device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textWidth, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textWidth + textHeight, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textHeight, clrSize)); device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxWidth, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxWidth + textMaxHeight, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxHeight, clrMaxSize)); } // Individual line sizes if (showLines) { ColorRgba clrLineBg = (ColorRgba.Blue + ColorRgba.Red).WithAlpha(64); for (int i = 0; i < this.text.TextMetrics.LineBounds.Count; i++) { Rect lineRect = this.text.TextMetrics.LineBounds[i]; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.Quads, new VertexC1P3(metricsOffset + posTemp + lineRect.TopLeft.X * tUnitX + lineRect.TopLeft.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.BottomLeft.X * tUnitX + lineRect.BottomLeft.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.BottomRight.X * tUnitX + lineRect.BottomRight.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.TopRight.X * tUnitX + lineRect.TopRight.Y * tUnitY, clrLineBg)); } } // Individual line sizes if (showElements) { ColorRgba clrElementBg = (ColorRgba.Blue + ColorRgba.Green).WithAlpha(128); for (int i = 0; i < this.text.TextMetrics.ElementBounds.Count; i++) { Rect elemRect = this.text.TextMetrics.ElementBounds[i]; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.TopLeft.X * tUnitX + elemRect.TopLeft.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.BottomLeft.X * tUnitX + elemRect.BottomLeft.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.BottomRight.X * tUnitX + elemRect.BottomRight.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.TopRight.X * tUnitX + elemRect.TopRight.Y * tUnitY, clrElementBg)); } } } ColorRgba matColor = this.customMat != null ? this.customMat.MainColor : ColorRgba.White; int[] vertLen = this.text.EmitVertices(ref this.vertFont, ref this.vertIcon, posTemp.X, posTemp.Y, posTemp.Z, this.colorTint * matColor, xDot, yDot); if (this.text.Fonts != null) { for (int i = 0; i < this.text.Fonts.Length; i++) { if (this.text.Fonts[i] != null && this.text.Fonts[i].IsAvailable) { if (this.customMat == null) { device.AddVertices(this.text.Fonts[i].Res.Material, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } else { BatchInfo cm = new BatchInfo(this.customMat); cm.Textures = this.text.Fonts[i].Res.Material.Textures; device.AddVertices(cm, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } } } } if (this.text.Icons != null && this.iconMat.IsAvailable) { device.AddVertices(this.iconMat, VertexMode.Quads, this.vertIcon, vertLen[0]); } }
protected void PrepareVerticesLight(ref VertexC1P3T2A4[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, 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); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T2A4[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 = uvRect.X; vertices[0].TexCoord.Y = uvRect.Y; vertices[0].Color = mainClr; vertices[0].Attrib = perPixel ? objRotMat : vertexLight[0]; 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 = uvRect.X; vertices[1].TexCoord.Y = uvRect.MaximumY; vertices[1].Color = mainClr; vertices[1].Attrib = perPixel ? objRotMat : vertexLight[1]; 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 = uvRect.MaximumX; vertices[2].TexCoord.Y = uvRect.MaximumY; vertices[2].Color = mainClr; vertices[2].Attrib = perPixel ? objRotMat : vertexLight[2]; 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 = uvRect.MaximumX; vertices[3].TexCoord.Y = uvRect.Y; vertices[3].Color = mainClr; vertices[3].Attrib = perPixel ? objRotMat : vertexLight[3]; }
protected void PrepareVerticesLightSmooth(ref VertexC1P3T4A4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, 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); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) { objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); } if (vertices == null || vertices.Length != 4) { vertices = new VertexC1P3T4A4A1[4]; } // Calculate UV coordinates float left = uvRect.X; float right = uvRect.RightX; float top = uvRect.Y; float bottom = uvRect.BottomY; float nextLeft = uvRectNext.X; float nextRight = uvRectNext.RightX; float nextTop = uvRectNext.Y; float nextBottom = uvRectNext.BottomY; if ((this.flipMode & FlipMode.Horizontal) != FlipMode.None) { MathF.Swap(ref left, ref right); MathF.Swap(ref nextLeft, ref nextRight); } if ((this.flipMode & FlipMode.Vertical) != FlipMode.None) { MathF.Swap(ref top, ref bottom); MathF.Swap(ref nextTop, ref nextBottom); } // Directly pass World Position with each vertex, see note in Light.cs 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].TexCoord.Z = nextLeft; vertices[0].TexCoord.W = nextTop; vertices[0].Color = mainClr; vertices[0].Attrib = perPixel ? objRotMat : vertexLight[0]; vertices[0].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextLeft; vertices[1].TexCoord.W = nextBottom; vertices[1].Color = mainClr; vertices[1].Attrib = perPixel ? objRotMat : vertexLight[1]; vertices[1].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[2].TexCoord.W = nextBottom; vertices[2].Color = mainClr; vertices[2].Attrib = perPixel ? objRotMat : vertexLight[2]; vertices[2].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[3].TexCoord.W = nextTop; vertices[3].Color = mainClr; vertices[3].Attrib = perPixel ? objRotMat : vertexLight[3]; vertices[3].Attrib2 = curAnimFrameFade; 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; } } }
public int CalcPriority(IDrawDevice device) { if (!this.IsDirectional) { float uniformScale = this.GameObj.Transform.Scale; Vector3 pos = this.GameObj.Transform.Pos; float scale = 1.0f; device.PreprocessCoords(ref pos, ref scale); float planarDist = (this.GameObj.Transform.Pos.Xy - device.RefCoord.Xy).Length; float rangeFactor = 1.0f / (this.range * uniformScale); float distFactor = (MathF.Min(scale, 1.0f) * planarDist); float spotFactor; if (this.dir != Vector3.Zero) spotFactor = 0.5f * (1.0f + Vector3.Dot((device.RefCoord - this.GameObj.Transform.Pos).Normalized, this.dir)); else spotFactor = 1.0f; return MathF.RoundToInt(1000000.0f * spotFactor * distFactor * MathF.Pow(rangeFactor, 1.5f) * MathF.Pow(1.0f / this.intensity, 0.5f)); } else { return MathF.RoundToInt(100.0f * MathF.Pow(1.0f / this.intensity, 0.5f)); } }
protected internal override void OnCollectDrawcalls(Canvas canvas) { base.OnCollectDrawcalls(canvas); IDrawDevice device = canvas.DrawDevice; float scaleTemp = 1.0f; Vector3 posTemp = Vector3.Zero; device.PreprocessCoords(ref posTemp, ref scaleTemp); if (posTemp.Z <= canvas.DrawDevice.NearZ) { return; } float alphaTemp = 0.5f; alphaTemp *= (float)Math.Min(1.0d, ((posTemp.Z - device.NearZ) / (device.NearZ * 5.0f))); if (alphaTemp <= 0.005f) { return; } float stepTemp = 4.0f * this.gridSize * MathF.Max(0.25f, MathF.Pow(2.0f, -MathF.Round(1.0f - MathF.Log(1.0f / scaleTemp, 2.0f)))); float scaledStep = stepTemp * scaleTemp; float viewBoundRad = device.TargetSize.Length * 0.5f; int lineCount = (2 + (int)MathF.Ceiling(viewBoundRad * 2 / scaledStep)) * 4; ColorRgba gridColor = this.FgColor.WithAlpha(alphaTemp); VertexC1P3[] vertices = new VertexC1P3[lineCount * 4]; float beginPos; float pos; int lineIndex; int vertOff = 0; beginPos = posTemp.X % scaledStep - (lineCount / 8) * scaledStep; pos = beginPos; lineIndex = 0; for (int x = 0; x < lineCount; x++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + x * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + x * 2 + 0].Pos.X = pos; vertices[vertOff + x * 2 + 0].Pos.Y = -viewBoundRad; vertices[vertOff + x * 2 + 0].Pos.Z = posTemp.Z + 1; vertices[vertOff + x * 2 + 1] = vertices[vertOff + x * 2 + 0]; vertices[vertOff + x * 2 + 1].Pos.Y = viewBoundRad; pos += scaledStep / 4; lineIndex++; } vertOff += lineCount * 2; beginPos = posTemp.Y % scaledStep - (lineCount / 8) * scaledStep; pos = beginPos; lineIndex = 0; for (int y = 0; y < lineCount; y++) { bool primaryLine = lineIndex % 4 == 0; bool secondaryLine = lineIndex % 4 == 2; vertices[vertOff + y * 2 + 0].Color = primaryLine ? gridColor : gridColor.WithAlpha(alphaTemp * (secondaryLine ? 0.5f : 0.25f)); vertices[vertOff + y * 2 + 0].Pos.X = -viewBoundRad; vertices[vertOff + y * 2 + 0].Pos.Y = pos; vertices[vertOff + y * 2 + 0].Pos.Z = posTemp.Z + 1; vertices[vertOff + y * 2 + 1] = vertices[vertOff + y * 2 + 0]; vertices[vertOff + y * 2 + 1].Pos.X = viewBoundRad; pos += scaledStep / 4; lineIndex++; } vertOff += lineCount * 2; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.Lines, vertices); }
public override void Draw(IDrawDevice device) { if (this.particles == null) { return; } Texture tex = this.RetrieveTexture(); if (tex == null) { return; } Vector2 particleHalfSize = this.particleSize * 0.5f; float objAngle = this.GameObj.Transform.Angle; float objScale = this.GameObj.Transform.Scale; Vector3 objPos = this.GameObj.Transform.Pos; Vector2 objXDot, objYDot; MathF.GetTransformDotVec(objAngle, objScale, out objXDot, out objYDot); if (this.vertexBuffer == null) { this.vertexBuffer = new RawList <VertexC1P3T2>(this.particles.Count * 4); } this.vertexBuffer.Count = this.vertexBuffer.Count = this.particles.Count * 4; VertexC1P3T2[] vertexData = this.vertexBuffer.Data; Particle[] particleData = this.particles.Data; int particleCount = this.particles.Count; for (int i = 0; i < particleCount; i++) { ColorRgba color = particleData[i].Color; float alpha = (float)color.A / 255.0f; if (this.fadeOutAt < 1.0f) { alpha *= MathF.Clamp((1.0f - particleData[i].AgeFactor) / this.fadeOutAt, 0.0f, 1.0f); } if (this.fadeInAt > 0.0f) { alpha *= MathF.Clamp(particleData[i].AgeFactor / this.fadeInAt, 0.0f, 1.0f); } color.A = (byte)(alpha * 255.0f); Rect uvRect; tex.LookupAtlas(particleData[i].SpriteIndex, out uvRect); Vector3 particlePos = particleData[i].Position; MathF.TransformDotVec(ref particlePos, ref objXDot, ref objYDot); particlePos += objPos; float particleAngle = objAngle + particleData[i].Angle; float particleScale = objScale; device.PreprocessCoords(ref particlePos, ref particleScale); Vector2 xDot, yDot; MathF.GetTransformDotVec(particleAngle, particleScale, out xDot, out yDot); Vector2 edgeTopLeft = new Vector2(-particleHalfSize.X, -particleHalfSize.Y); Vector2 edgeBottomLeft = new Vector2(-particleHalfSize.X, particleHalfSize.Y); Vector2 edgeBottomRight = new Vector2(particleHalfSize.X, particleHalfSize.Y); Vector2 edgeTopRight = new Vector2(particleHalfSize.X, -particleHalfSize.Y); MathF.TransformDotVec(ref edgeTopLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeBottomLeft, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeBottomRight, ref xDot, ref yDot); MathF.TransformDotVec(ref edgeTopRight, ref xDot, ref yDot); int vertexBaseIndex = i * 4; vertexData[vertexBaseIndex + 0].Pos.X = particlePos.X + edgeTopLeft.X; vertexData[vertexBaseIndex + 0].Pos.Y = particlePos.Y + edgeTopLeft.Y; vertexData[vertexBaseIndex + 0].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 0].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 0].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 0].Color = color; vertexData[vertexBaseIndex + 1].Pos.X = particlePos.X + edgeBottomLeft.X; vertexData[vertexBaseIndex + 1].Pos.Y = particlePos.Y + edgeBottomLeft.Y; vertexData[vertexBaseIndex + 1].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 1].TexCoord.X = uvRect.X; vertexData[vertexBaseIndex + 1].TexCoord.Y = uvRect.BottomY; vertexData[vertexBaseIndex + 1].Color = color; vertexData[vertexBaseIndex + 2].Pos.X = particlePos.X + edgeBottomRight.X; vertexData[vertexBaseIndex + 2].Pos.Y = particlePos.Y + edgeBottomRight.Y; vertexData[vertexBaseIndex + 2].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 2].TexCoord.X = uvRect.RightX; vertexData[vertexBaseIndex + 2].TexCoord.Y = uvRect.BottomY; vertexData[vertexBaseIndex + 2].Color = color; vertexData[vertexBaseIndex + 3].Pos.X = particlePos.X + edgeTopRight.X; vertexData[vertexBaseIndex + 3].Pos.Y = particlePos.Y + edgeTopRight.Y; vertexData[vertexBaseIndex + 3].Pos.Z = particlePos.Z; vertexData[vertexBaseIndex + 3].TexCoord.X = uvRect.RightX; vertexData[vertexBaseIndex + 3].TexCoord.Y = uvRect.Y; vertexData[vertexBaseIndex + 3].Color = color; } device.AddVertices(this.material, VertexMode.Quads, vertexData, this.vertexBuffer.Count); }
public override void Draw(IDrawDevice device) { if (!Sprite.IsAvailable) { return; } var material = Sprite.Res.Material.Res; var mainTex = material?.MainTexture.Res; var uvRect = Sprite.Res.UVRect; Vector2 uvTexSize, uvRatio; if (mainTex != null) { uvTexSize = mainTex.Size; uvRatio = mainTex.UVRatio; } else { uvTexSize = new Vector2(128, 128); uvRatio = Vector2.One; } Vector3 posTemp = this.GameObj.Transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); MathF.GetTransformDotVec(this.GameObj.Transform.Angle, scaleTemp, out var xDot, out var yDot); var rectTemp = GetTargetRect(); Vector2 edge1 = rectTemp.TopLeft; Vector2 edge2 = rectTemp.BottomLeft; Vector2 edge3 = rectTemp.BottomRight; Vector2 edge4 = rectTemp.TopRight; if ((this.FlipMode & SpriteRenderer.FlipMode.Horizontal) != SpriteRenderer.FlipMode.None) { edge1.X = -edge1.X; edge2.X = -edge2.X; edge3.X = -edge3.X; edge4.X = -edge4.X; } if ((this.FlipMode & SpriteRenderer.FlipMode.Vertical) != SpriteRenderer.FlipMode.None) { edge1.Y = -edge1.Y; edge2.Y = -edge2.Y; edge3.Y = -edge3.Y; edge4.Y = -edge4.Y; } 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 = uvRatio.X * uvRect.X / uvTexSize.X; float right = uvRatio.X * uvRect.RightX / uvTexSize.X; float top = uvRatio.Y * uvRect.Y / uvTexSize.Y; float bottom = uvRatio.Y * uvRect.BottomY / uvTexSize.Y; 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 = Color; //vertices[0].Attrib = Attribute; 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 = Color; //vertices[1].Attrib = Attribute; 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 = Color; //vertices[2].Attrib = Attribute; 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 = Color; //vertices[3].Attrib = Attribute; if (this.AlignToPixelGrid) { 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; } } if (material != null) { device.AddVertices(material, VertexMode.Quads, vertices); } }
public override void Draw(IDrawDevice device) { 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, this.gameobj.Transform.Scale * scaleTemp, out xDot, out yDot); // Apply block alignment Vector2 textOffset = Vector2.Zero; Vector2 textSize = this.text.Size; if (this.text.MaxWidth > 0) { textSize.X = this.text.MaxWidth; } this.blockAlign.ApplyTo(ref textOffset, textSize); MathF.TransformDotVec(ref textOffset, ref xDot, ref yDot); posTemp.X += textOffset.X; posTemp.Y += textOffset.Y; if (this.text.Fonts != null && this.text.Fonts.Any(r => r.IsAvailable && r.Res.IsPixelGridAligned)) { posTemp.X = MathF.Round(posTemp.X); posTemp.Y = MathF.Round(posTemp.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { posTemp.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { posTemp.Y += 0.5f; } } ColorRgba matColor = this.customMat != null ? this.customMat.MainColor : ColorRgba.White; int[] vertLen = this.text.EmitVertices(ref this.vertFont, ref this.vertIcon, posTemp.X, posTemp.Y, posTemp.Z + this.VertexZOffset, this.colorTint * matColor, xDot, yDot); if (this.text.Fonts != null) { for (int i = 0; i < this.text.Fonts.Length; i++) { if (this.text.Fonts[i] != null && this.text.Fonts[i].IsAvailable) { if (this.customMat == null) { device.AddVertices(this.text.Fonts[i].Res.Material, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } else { BatchInfo cm = new BatchInfo(this.customMat); cm.Textures = this.text.Fonts[i].Res.Material.Textures; device.AddVertices(cm, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } } } } if (this.text.Icons != null && this.iconMat.IsAvailable) { device.AddVertices(this.iconMat, VertexMode.Quads, this.vertIcon, vertLen[0]); } }
protected void PrepareVertices(ref VertexC1P3T2[] vertices, IDrawDevice device) { Texture mainTex = this.RetrieveMainTexture(); ColorRgba mainClr = this.RetrieveMainColor(); // Determine texture sprite rect Rect blockSpriteRect; if (mainTex != null) blockSpriteRect = Rect.AlignTopLeft(0, 0, mainTex.PxWidth, mainTex.PxHeight); else blockSpriteRect = Rect.AlignTopLeft(0, 0, 1, 1); // Determine block rects to draw Collider col = this.GameObj.GetComponent<Collider>(); var blockShapes = col.Shapes.OfType<Collider.PolyShapeInfo>(); var blockRects = blockShapes.Select(p => p.AABB).ToArray(); Vector3 posTemp = this.GameObj.Transform.Pos; float scaleTemp = 1.0f; device.PreprocessCoords(this, ref posTemp, ref scaleTemp); Vector2 xDot, yDot; MathF.GetTransformDotVec(this.GameObj.Transform.Angle, scaleTemp, out xDot, out yDot); if (vertices == null || vertices.Length != blockRects.Length * 4) vertices = new VertexC1P3T2[blockRects.Length * 4]; for (int i = 0; i < blockRects.Length; i++) { Rect blockRect = blockRects[i]; Rect uvRect = new Rect( (blockRect.x - blockSpriteRect.x) / blockSpriteRect.w, (blockRect.y - blockSpriteRect.y) / blockSpriteRect.h, blockRect.w / blockSpriteRect.w, blockRect.h / blockSpriteRect.h); Rect rectTemp = blockRect.Transform(this.GameObj.Transform.Scale.Xy); 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); vertices[i * 4 + 0].pos.X = posTemp.X + edge1.X; vertices[i * 4 + 0].pos.Y = posTemp.Y + edge1.Y; vertices[i * 4 + 0].pos.Z = posTemp.Z; vertices[i * 4 + 0].texCoord.X = uvRect.x; vertices[i * 4 + 0].texCoord.Y = uvRect.y; vertices[i * 4 + 0].clr = mainClr; vertices[i * 4 + 1].pos.X = posTemp.X + edge2.X; vertices[i * 4 + 1].pos.Y = posTemp.Y + edge2.Y; vertices[i * 4 + 1].pos.Z = posTemp.Z; vertices[i * 4 + 1].texCoord.X = uvRect.x; vertices[i * 4 + 1].texCoord.Y = uvRect.MaxY; vertices[i * 4 + 1].clr = mainClr; vertices[i * 4 + 2].pos.X = posTemp.X + edge3.X; vertices[i * 4 + 2].pos.Y = posTemp.Y + edge3.Y; vertices[i * 4 + 2].pos.Z = posTemp.Z; vertices[i * 4 + 2].texCoord.X = uvRect.MaxX; vertices[i * 4 + 2].texCoord.Y = uvRect.MaxY; vertices[i * 4 + 2].clr = mainClr; vertices[i * 4 + 3].pos.X = posTemp.X + edge4.X; vertices[i * 4 + 3].pos.Y = posTemp.Y + edge4.Y; vertices[i * 4 + 3].pos.Z = posTemp.Z; vertices[i * 4 + 3].texCoord.X = uvRect.MaxX; vertices[i * 4 + 3].texCoord.Y = uvRect.y; vertices[i * 4 + 3].clr = mainClr; } }
public override void Draw(IDrawDevice device) { 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, this.gameobj.Transform.Scale * scaleTemp, out xDot, out yDot); // Apply block alignment Vector2 textOffset = Vector2.Zero; Vector2 textSize = this.text.Size; if (this.text.MaxWidth > 0) { textSize.X = this.text.MaxWidth; } this.blockAlign.ApplyTo(ref textOffset, textSize); MathF.TransformDotVec(ref textOffset, ref xDot, ref yDot); posTemp.X += textOffset.X; posTemp.Y += textOffset.Y; if (this.text.Fonts != null && this.text.Fonts.Any(r => r.IsAvailable && r.Res.IsPixelGridAligned)) { posTemp.X = MathF.Round(posTemp.X); posTemp.Y = MathF.Round(posTemp.Y); if (MathF.RoundToInt(device.TargetSize.X) != (MathF.RoundToInt(device.TargetSize.X) / 2) * 2) { posTemp.X += 0.5f; } if (MathF.RoundToInt(device.TargetSize.Y) != (MathF.RoundToInt(device.TargetSize.Y) / 2) * 2) { posTemp.Y += 0.5f; } } // Draw design time metrics data if (DualityApp.ExecContext == DualityApp.ExecutionContext.Editor) { bool showLimits = true; bool showLines = false; bool showElements = false; Vector3 metricsOffset = new Vector3(0.0f, 0.0f, 0.01f); Vector3 lineOffset = new Vector3(0.5f, 0.5f, 0.0f); Vector3 tUnitX = Vector3.UnitX; Vector3 tUnitY = Vector3.UnitY; MathF.TransformDotVec(ref tUnitX, ref xDot, ref yDot); MathF.TransformDotVec(ref tUnitY, ref xDot, ref yDot); // Actual text size and maximum text size if (showLimits) { Vector3 textWidth = tUnitX * this.text.Size.X; Vector3 textHeight = tUnitY * this.text.Size.Y; Vector3 textMaxWidth = tUnitX * this.text.MaxWidth; Vector3 textMaxHeight = tUnitY * MathF.Max(this.text.MaxHeight, this.text.Size.Y); ColorRgba clrSize = ColorRgba.Green.WithAlpha(128); ColorRgba clrMaxSize = ColorRgba.Red.WithAlpha(128); device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textWidth, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textWidth + textHeight, clrSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textHeight, clrSize)); device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxWidth, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxWidth + textMaxHeight, clrMaxSize), new VertexC1P3(metricsOffset + lineOffset + posTemp + textMaxHeight, clrMaxSize)); } // Individual line sizes if (showLines) { ColorRgba clrLineBg = (ColorRgba.Blue + ColorRgba.Red).WithAlpha(64); for (int i = 0; i < this.text.TextMetrics.LineBounds.Count; i++) { Rect lineRect = this.text.TextMetrics.LineBounds[i]; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.Quads, new VertexC1P3(metricsOffset + posTemp + lineRect.TopLeft.X * tUnitX + lineRect.TopLeft.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.BottomLeft.X * tUnitX + lineRect.BottomLeft.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.BottomRight.X * tUnitX + lineRect.BottomRight.Y * tUnitY, clrLineBg), new VertexC1P3(metricsOffset + posTemp + lineRect.TopRight.X * tUnitX + lineRect.TopRight.Y * tUnitY, clrLineBg)); } } // Individual line sizes if (showElements) { ColorRgba clrElementBg = (ColorRgba.Blue + ColorRgba.Green).WithAlpha(128); for (int i = 0; i < this.text.TextMetrics.ElementBounds.Count; i++) { Rect elemRect = this.text.TextMetrics.ElementBounds[i]; device.AddVertices(new BatchInfo(DrawTechnique.Alpha, ColorRgba.White), VertexMode.LineLoop, new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.TopLeft.X * tUnitX + elemRect.TopLeft.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.BottomLeft.X * tUnitX + elemRect.BottomLeft.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.BottomRight.X * tUnitX + elemRect.BottomRight.Y * tUnitY, clrElementBg), new VertexC1P3(metricsOffset + lineOffset + posTemp + elemRect.TopRight.X * tUnitX + elemRect.TopRight.Y * tUnitY, clrElementBg)); } } } ColorRgba matColor = this.customMat != null ? this.customMat.MainColor : ColorRgba.White; int[] vertLen = this.text.EmitVertices(ref this.vertFont, ref this.vertIcon, posTemp.X, posTemp.Y, posTemp.Z, this.colorTint * matColor, xDot, yDot); if (this.text.Fonts != null) { for (int i = 0; i < this.text.Fonts.Length; i++) { if (this.text.Fonts[i] != null && this.text.Fonts[i].IsAvailable) { if (this.customMat == null) { device.AddVertices(this.text.Fonts[i].Res.Material, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } else { BatchInfo cm = new BatchInfo(this.customMat); cm.Textures = this.text.Fonts[i].Res.Material.Textures; device.AddVertices(cm, VertexMode.Quads, this.vertFont[i], vertLen[i + 1]); } } } } if (this.text.Icons != null && this.iconMat.IsAvailable) { device.AddVertices(this.iconMat, VertexMode.Quads, this.vertIcon, vertLen[0]); } }
protected void PrepareVerticesLight(ref VertexC1P3T2A4[] vertices, IDrawDevice device, ColorRgba mainClr, Rect uvRect, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, 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); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) { objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); } if (vertices == null || vertices.Length != 4) { vertices = new VertexC1P3T2A4[4]; } // Directly pass World Position with each vertex, see note in Light.cs 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 = uvRect.X; vertices[0].texCoord.Y = uvRect.Y; vertices[0].clr = mainClr; vertices[0].attrib = perPixel ? objRotMat : vertexLight[0]; 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 = uvRect.X; vertices[1].texCoord.Y = uvRect.MaxY; vertices[1].clr = mainClr; vertices[1].attrib = perPixel ? objRotMat : vertexLight[1]; 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 = uvRect.MaxX; vertices[2].texCoord.Y = uvRect.MaxY; vertices[2].clr = mainClr; vertices[2].attrib = perPixel ? objRotMat : vertexLight[2]; 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 = uvRect.MaxX; vertices[3].texCoord.Y = uvRect.Y; vertices[3].clr = mainClr; vertices[3].attrib = perPixel ? objRotMat : vertexLight[3]; }
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; } } }
public void Draw(IDrawDevice device) { if( Gid == 0 ) return; if( Points.Count > 0 ) { var pos = new Vector3(X, Y, 0.0f); var scale = 1.0f; device.PreprocessCoords(ref pos, ref scale); foreach( var point in Points ) { } } }
protected void PrepareVerticesLightSmooth(ref VertexC1P3T4A4A1[] vertices, IDrawDevice device, float curAnimFrameFade, ColorRgba mainClr, Rect uvRect, Rect uvRectNext, DrawTechnique tech) { bool perPixel = tech is LightingTechnique; Vector3 pos = this.GameObj.Transform.Pos; Vector3 posTemp = pos; float scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); Vector2 xDot, yDot; float rotation = this.GameObj.Transform.Angle; MathF.GetTransformDotVec(rotation, 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); // Using Per-Vertex Lighting? Calculate vertex light values Vector4[] vertexLight = null; if (!perPixel) { vertexLight = new Vector4[4]; Light.GetLightAtWorldPos(pos + new Vector3(edge1), out vertexLight[0], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge2), out vertexLight[1], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge3), out vertexLight[2], this.vertexTranslucency); Light.GetLightAtWorldPos(pos + new Vector3(edge4), out vertexLight[3], this.vertexTranslucency); } Vector2.Multiply(ref edge1, scaleTemp, out edge1); Vector2.Multiply(ref edge2, scaleTemp, out edge2); Vector2.Multiply(ref edge3, scaleTemp, out edge3); Vector2.Multiply(ref edge4, scaleTemp, out edge4); // Using Per-Pixel Lighting? Pass objRotation Matrix via vertex attribute. Vector4 objRotMat = Vector4.Zero; if (perPixel) objRotMat = new Vector4((float)Math.Cos(-rotation), -(float)Math.Sin(-rotation), (float)Math.Sin(-rotation), (float)Math.Cos(-rotation)); if (vertices == null || vertices.Length != 4) vertices = new VertexC1P3T4A4A1[4]; // Calculate UV coordinates float left = uvRect.X; float right = uvRect.RightX; float top = uvRect.Y; float bottom = uvRect.BottomY; float nextLeft = uvRectNext.X; float nextRight = uvRectNext.RightX; float nextTop = uvRectNext.Y; float nextBottom = uvRectNext.BottomY; if ((this.flipMode & FlipMode.Horizontal) != FlipMode.None) { MathF.Swap(ref left, ref right); MathF.Swap(ref nextLeft, ref nextRight); } if ((this.flipMode & FlipMode.Vertical) != FlipMode.None) { MathF.Swap(ref top, ref bottom); MathF.Swap(ref nextTop, ref nextBottom); } // Directly pass World Position with each vertex, see note in Light.cs 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].TexCoord.Z = nextLeft; vertices[0].TexCoord.W = nextTop; vertices[0].Color = mainClr; vertices[0].Attrib = perPixel ? objRotMat : vertexLight[0]; vertices[0].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextLeft; vertices[1].TexCoord.W = nextBottom; vertices[1].Color = mainClr; vertices[1].Attrib = perPixel ? objRotMat : vertexLight[1]; vertices[1].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[2].TexCoord.W = nextBottom; vertices[2].Color = mainClr; vertices[2].Attrib = perPixel ? objRotMat : vertexLight[2]; vertices[2].Attrib2 = curAnimFrameFade; 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].TexCoord.Z = nextRight; vertices[3].TexCoord.W = nextTop; vertices[3].Color = mainClr; vertices[3].Attrib = perPixel ? objRotMat : vertexLight[3]; vertices[3].Attrib2 = curAnimFrameFade; 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; } } }
private void PrepareVertices(IDrawDevice device, ColorRgba colour) { var posTemp = GameObj.Transform.Pos; var scaleTemp = 1.0f; device.PreprocessCoords(ref posTemp, ref scaleTemp); var vertIndex = 0; for (var i = 0; i < _points.Length - 2; i += 2) { _vertices[vertIndex].Pos = posTemp + _points[i] * scaleTemp; _vertices[vertIndex].Color = colour; _vertices[vertIndex + 1].Pos = posTemp + _points[i + 1] * scaleTemp; _vertices[vertIndex + 1].Color = colour; _vertices[vertIndex + 2].Pos = posTemp + _points[i + 3] * scaleTemp; _vertices[vertIndex + 2].Color = colour; _vertices[vertIndex + 3].Pos = posTemp + _points[i + 2] * scaleTemp; _vertices[vertIndex + 3].Color = colour; vertIndex += 4; } }