public Game() { Scene = new Scene(); Viewport = new Viewport { Scene = Scene, Width = 800, Height = 600 }; Camera = new Camera() { Target = Vector.Forward, Position = Vector.Zero }; Constructed(); }
public void Render(Viewport viewport, Sprite sprite, Matrix view, Matrix projection, Matrix world, float xScale, float yScale, float rotation) { var image = sprite.CurrentFrame; var position = new Vector(0, 0, 0); var transformedPosition = Vector.Transform(position, world, view); var translatedPosition = Vector.Translate(transformedPosition, projection, viewport.Width, viewport.Height); var z = ((transformedPosition.Z / viewport.View.DepthDivisor) + viewport.View.DepthZero); var depthBufferAdjustedZ = z; var bufferSize = BufferContainer.Stride * BufferContainer.Height; var bufferZ = (UInt32)((1.0f - depthBufferAdjustedZ) * (float)UInt32.MaxValue); if (depthBufferAdjustedZ < 0f || depthBufferAdjustedZ >= 1f) { return; } var xOriginOffset = (int)-((sprite.CurrentFrame.Width / 2f) * xScale); var yOriginOffset = (int)-((sprite.CurrentFrame.Height / 2f) * yScale); var actualX = ((int) translatedPosition.X) + xOriginOffset; var actualY = ((int) translatedPosition.Y) + yOriginOffset; var positionOffset = actualX + (actualY * BufferContainer.Stride); if (xScale != 1f || yScale != 1f) { RenderScaled(viewport, positionOffset, actualX, actualY, sprite.CurrentFrame, translatedPosition, bufferSize, bufferZ, xScale, yScale); } else { RenderUnscaled(viewport, positionOffset, actualX, actualY, sprite.CurrentFrame, translatedPosition, bufferSize, bufferZ); } }
public static void DrawLine(Viewport viewport, IBuffers buffers, int xstart, int ystart, int xend, int yend, Color color) { var colorAsInt = (int)color.ToUInt32(); var deltaX = xend - xstart; var deltaY = yend - ystart; var lengthX = deltaX >= 0 ? deltaX : -deltaX; var lengthY = deltaY >= 0 ? deltaY : -deltaY; var actualLength = lengthX > lengthY ? lengthX : lengthY; if( actualLength != 0 ) { var slopeX = (float) deltaX/(float) actualLength; var slopeY = (float) deltaY/(float) actualLength; var currentX = (float)xstart; var currentY = (float)ystart; for( var pixel=0; pixel<actualLength; pixel++) { if (currentX > 0 && currentY > 0 && currentX < viewport.Width && currentY < viewport.Height) { var bufferOffset = (buffers.FrameBuffer.Stride*(int) currentY) + (int) currentX; buffers.FrameBuffer.Pixels[bufferOffset] = colorAsInt; } currentX += slopeX; currentY += slopeY; } } }
public void Setup() { var viewport = new Viewport { Width = 640, Height = 480 }; var camera = new Camera(viewport) { Target = Vector.Forward, Position = Vector.Zero }; camera.Prepare(viewport); camera.Update(); _frustum = new Frustum(); _frustum.SetCameraDefinition(camera); }
public void UnprojectingCenterOfViewportWithIdentityViewShouldGenerateAVectorAtCenter() { var viewport = new Viewport { Width = 640, Height = 480 }; var aspect = (float) viewport.Height/(float) viewport.Width; var projection = Matrix.CreatePerspectiveFieldOfView(40f, aspect, 1, 4000f); var view = Matrix.Identity; var world = Matrix.Identity; var position = new Vector((float)viewport.Width/2, (float)viewport.Height/2,0); var result = viewport.Unproject(position, projection, view, world); Assert.That(result,Is.EqualTo(new Vector(0,0,-1))); }
public Color Calculate(Viewport viewport, Vector vector, Vector normal) { var color = viewport.Scene.AmbientColor; foreach( ILight light in viewport.Scene.Lights ) { var lightColor = light.Calculate(viewport, vector, normal); color = color.Additive(lightColor); } return color; }
public void UnprojectingCenterOfViewportWithViewRotated90DegreesAroundYAxisShouldGenerateAVectorRotated90DegreesInOpositeDirection() { var viewport = new Viewport { Width = 640, Height = 480 }; var aspect = (float)viewport.Height / (float)viewport.Width; var projection = Matrix.CreatePerspectiveFieldOfView(40f, aspect, 1, 4000f); var view = Matrix.CreateRotationY(90); var world = Matrix.Identity; var position = new Vector((float)viewport.Width / 2, (float)viewport.Height / 2, 0); var result = viewport.Unproject(position, projection, view, world); var negativeView = Matrix.CreateRotationY(-90); var expected = new Vector(0, 0, -1); var rotatedExpected = expected*negativeView; Assert.That(result, Is.EqualTo(rotatedExpected)); }
public void RenderBoundingSphere(BoundingSphere sphere, Viewport viewport, Matrix view, Matrix projection, Matrix world) { var scaleMatrix = Matrix.CreateScale(sphere.Radius); var translationMatrix = Matrix.CreateTranslation(sphere.Center) * world; var rotateYMatrix = Matrix.CreateRotationY(90); var rotateXMatrix = Matrix.CreateRotationX(90); _boundingSphereDebugShape.World = scaleMatrix * translationMatrix; _boundingSphereDebugShape.Render(viewport, view, projection); _boundingSphereDebugShape.World = rotateYMatrix * scaleMatrix * translationMatrix; _boundingSphereDebugShape.Render(viewport, view, projection); _boundingSphereDebugShape.World = rotateXMatrix * scaleMatrix * translationMatrix; _boundingSphereDebugShape.Render(viewport, view, projection); }
public Camera(Viewport viewport) { Position = new Vector(0f, -30f, 50f); Target = new Vector(0f, 0f, 0f); Up = new Vector(0f, -1f, 0f); Near = DefaultNear; Far = DefaultFar; Roll = 0; FieldOfView = DefaultFieldOfView; ProjectionMatrix = null; UpdateDepthDivisor(); Frustum = new Frustum(); Viewport = viewport; }
public void GettingObjectAtCenterOfScreenWithSingleObjectAtCenterOfSceneShouldReturnTheObject() { var viewport = new Viewport {Width = 640, Height = 480}; var scene = new Scene(); var camera = new Camera(viewport) {Position = {Z = -10}}; camera.Update(); var node = new Geometry { BoundingSphere = new BoundingSphere(Vector.Zero, 10f) }; scene.AddNode(node); var nodeAtCoordinate = scene.GetNodeAtScreenCoordinate(viewport, viewport.Width / 2, viewport.Height / 2); Assert.That(nodeAtCoordinate, Is.Not.Null); Assert.That(nodeAtCoordinate, Is.EqualTo(node)); }
public override Color Calculate(Viewport viewport, Vector point, Vector normal) { var actualAmbient = Ambient; var actualDiffuse = Diffuse; var actualSpecular = Specular; // Use dotproduct for diffuse lighting. Add point functionality as this now is a directional light. // Ambient light var ambient = actualAmbient * Strength; // Diffuse light var lightDir = Position-point; lightDir.Normalize(); normal.Normalize(); var dfDot = lightDir.Dot(normal); dfDot = MathHelper.Saturate(dfDot); var diffuse = actualDiffuse * dfDot * Strength; // Specular highlight var reflection = 2f * dfDot * normal - lightDir; reflection.Normalize(); var view = viewport.View.Position - point; view.Normalize(); var spDot = reflection.Dot(view); spDot = MathHelper.Saturate(spDot); var specular = actualSpecular * spDot * Strength; // Compute self shadowing var shadow = 4.0f * lightDir.Dot(normal); shadow = MathHelper.Saturate(shadow); // Compute range for the light var attenuation = ((lightDir / Range).Dot(lightDir / Range)); attenuation = MathHelper.Saturate(attenuation); attenuation = 1f - attenuation; // Final result var colorVector = ambient + shadow * (diffuse + specular) * attenuation; //var colorVector = ambient + diffuse; return colorVector; }
public override void Render(Viewport viewport, Matrix view, Matrix projection) { /* From DirectX sample w = width passed to D3DXMatrixPerspectiveLH h = height passed to D3DXMatrixPerspectiveLH n = z near passed to D3DXMatrixPerspectiveLH f = z far passed to D3DXMatrixPerspectiveLH d = distance of sprite from camera along Z qw = width of sprite quad qh = height of sprite quad vw = viewport height vh = viewport width scale = n / d (i.e. near/distance, such that at d = n, scale = 1.0) renderedWidth = vw * qw * scale / w renderedHeight = vh * qh * scale / h */ var position = new Vector(0, 0, 0); var actualPosition = new Vector(World.data[12], World.data[13], World.data[14]); var transformedPosition = Vector.Transform(position, World, view); var translatedPosition = Vector.Translate(transformedPosition, projection, viewport.Width, viewport.Height); var distanceVector = viewport.Camera.Position - actualPosition; var distance = distanceVector.Length; var n = 100.0f; distance = MathHelper.Abs(distance); var scale = 0.0f + ((2 * n) / distance); if (scale <= 0) { scale = 0; } var xscale = scale; var yscale = scale; _spriteContext.Render(viewport,this,view,projection,World,xscale,yscale,0f); }
private void CalculateVertexColorsForFace(ref Face face, Viewport viewport, Node node) { if (null == face.Material || face.Material.Shade == MaterialShade.Gouraud) { if (!Vertices[face.A].IsColorCalculated) { CalculateColorForVertex(ref Vertices[face.A], viewport, node); } if (!Vertices[face.B].IsColorCalculated) { CalculateColorForVertex(ref Vertices[face.B], viewport, node); } if (!Vertices[face.C].IsColorCalculated) { CalculateColorForVertex(ref Vertices[face.C], viewport, node); } } }
private void TransformAndTranslateVertex(ref Vertex vertex, Viewport viewport, Matrix view, Matrix projection, Matrix world) { var matrix = (world*view)*projection; vertex.Transform(world, matrix); vertex.Translate(projection, viewport.Width, viewport.Height); vertex.MakeScreenCoordinates(); vertex.TransformedVectorNormalized = vertex.TransformedNormal; vertex.TransformedVectorNormalized.Normalize(); var z = ((vertex.TransformedVector.Z/viewport.Camera.DepthDivisor) + viewport.Camera.DepthZero); vertex.DepthBufferAdjustedZ = z; }
public override void Prepare(Viewport viewport) { Viewport = viewport; SetupProjection(); base.Prepare(viewport); }
private void CalculateColorForVertex(ref Vertex vertex, Viewport viewport, Node node) { vertex.CalculatedColor = vertex.Color.Additive(_colorCalculator.Calculate(viewport, vertex.TransformedVector, vertex.TransformedNormal)); }
private static void RenderUnscaled(Viewport viewport, int positionOffset, int actualX, int actualY, Image image, Vector translatedPosition, int bufferSize, UInt32 bufferZ) { var imageContext = image.ImageContext as ImageContext; var spriteOffset = 0; var currentY = actualY; for (var y = 0; y < image.Height; y++) { if (currentY >= viewport.Height) { break; } if (currentY >= 0) { var offset = y*BufferContainer.Stride; var currentX = actualX; for (var x = 0; x < image.Width; x++) { if (currentX >= viewport.Width) { break; } if (currentX >= 0) { var actualOffset = offset + positionOffset; if (actualOffset >= 0 && actualOffset < bufferSize && bufferZ < BufferContainer.DepthBuffer[actualOffset]) { var pixel = BlendPixel(imageContext.Pixels[spriteOffset], BufferContainer.Framebuffer[actualOffset]); if ((pixel & 0xff000000) != 0) { BufferContainer.Framebuffer[actualOffset] = pixel; BufferContainer.DepthBuffer[actualOffset] = bufferZ; } } } offset++; spriteOffset++; currentX++; } } currentY++; } }
public void Update(Viewport viewport) { ViewMatrix = Matrix.CreateLookAt(Position, Target, Up); SetupProjection(viewport); UpdateDepthDivisor(); _frustum.SetCameraDefinition(viewport, this); }
private void InitializeGame() { if( null == GameClass ) { GameClass = new InternalGame(); } Runtime.RegisterGame(Display, GameClass); Viewport = GameClass.Viewport; Scene = GameClass.Scene; if( null == Camera ) { Camera = new Camera(GameClass.Camera); } else { Camera.ActualCamera = GameClass.Camera; } }
private void RenderFaces(Node node, Viewport viewport, Matrix view, Matrix projection, Matrix world) { if (null == Faces) { return; } var matrix = world*view; for (var faceIndex = 0; faceIndex < Faces.Length; faceIndex++) { var face = Faces[faceIndex]; var a = Vertices[face.A]; var b = Vertices[face.B]; var c = Vertices[face.C]; var mixedProduct = (b.TranslatedVector.X - a.TranslatedVector.X) * (c.TranslatedVector.Y - a.TranslatedVector.Y) - (c.TranslatedVector.X - a.TranslatedVector.X) * (b.TranslatedVector.Y - a.TranslatedVector.Y); var visible = mixedProduct < 0; // && viewport.View.IsInView(a.TransformedVector); if (null != face.Material) { visible |= face.Material.DoubleSided; } if (!visible) { continue; } CalculateVertexColorsForFace(ref face, viewport, node); if (null != face.Material) { switch (face.Material.Shade) { case MaterialShade.None: { face.Color = face.Material.Diffuse; if (null != face.Material.DiffuseMap || null != face.Material.ReflectionMap) { TextureTriangleRenderer.Draw(face, Vertices); } else { FlatTriangleRenderer.Draw(face, Vertices); } } break; case MaterialShade.Flat: { face.Transform(matrix); var color = face.Material.Diffuse; face.Color = color.Additive(_colorCalculator.Calculate(viewport, face.TransformedPosition, face.TransformedNormal)); if (null != face.Material.DiffuseMap || null != face.Material.ReflectionMap) { TextureTriangleRenderer.Draw(face, Vertices); } else { FlatTriangleRenderer.Draw(face, Vertices); } } break; case MaterialShade.Gouraud: { var color = face.Material.Diffuse; Vertices[face.A].CalculatedColor = color.Additive(Vertices[face.A].CalculatedColor); Vertices[face.B].CalculatedColor = color.Additive(Vertices[face.B].CalculatedColor); Vertices[face.C].CalculatedColor = color.Additive(Vertices[face.C].CalculatedColor); if (null != face.Material.DiffuseMap || null != face.Material.ReflectionMap) { TextureTriangleRenderer.Draw(face, Vertices); } else { GouraudTriangleRenderer.Draw(face, Vertices); } } break; } } else { var color = node.Color; var aColor = Vertices[face.A].CalculatedColor; var bColor = Vertices[face.B].CalculatedColor; var cColor = Vertices[face.C].CalculatedColor; Vertices[face.A].CalculatedColor = Vertices[face.A].CalculatedColor.Additive(color); Vertices[face.B].CalculatedColor = Vertices[face.B].CalculatedColor.Additive(color); Vertices[face.C].CalculatedColor = Vertices[face.C].CalculatedColor.Additive(color); GouraudTriangleRenderer.Draw(face, Vertices); Vertices[face.A].CalculatedColor = aColor; Vertices[face.B].CalculatedColor = bColor; Vertices[face.C].CalculatedColor = cColor; } } }
public abstract Color Calculate(Viewport viewport, Vector point, Vector normal);
private void TransformAndTranslateVertices(Viewport viewport, Node node, Matrix view, Matrix projection, Matrix world) { var negativePivot = -(Vector)node.PivotPoint; var localView = (world * view); for (var vertexIndex = 0; vertexIndex < Vertices.Length; vertexIndex++) { var vertex = Vertices[vertexIndex]; vertex.Vector += negativePivot; TransformAndTranslateVertex(ref vertex, viewport, localView, projection); //CalculateColorForVertex(ref vertex, viewport, node); vertex.Vector -= negativePivot; Vertices[vertexIndex] = vertex; } }
private void RenderVertices(Node node, Viewport viewport, Matrix view, Matrix projection, Matrix world) { for (var vertexIndex = 0; vertexIndex < Vertices.Length; vertexIndex++) { PointRenderer.Draw((int)Vertices[vertexIndex].TranslatedScreenCoordinates.X, (int)Vertices[vertexIndex].TranslatedScreenCoordinates.Y, viewport.DebugInfo.Color, 4); } }
private void RenderLines(Node node, Viewport viewport, Matrix view, Matrix projection, Matrix world) { if (null == Lines) { return; } for (var lineIndex = 0; lineIndex < Lines.Length; lineIndex++) { var line = Lines[lineIndex]; var a = Vertices[line.A]; var b = Vertices[line.B]; var xstart = a.TranslatedScreenCoordinates.X; var ystart = a.TranslatedScreenCoordinates.Y; var xend = b.TranslatedScreenCoordinates.X; var yend = b.TranslatedScreenCoordinates.Y; Shapes.DrawLine(viewport, (int)xstart, (int)ystart, (int)xend, (int)yend, node.Color); } }
public void Render(Viewport viewport, RenderableNode node, Matrix view, Matrix projection, Matrix world) { if (null == Vertices) { return; } if (!_hasPrepared) { Prepare(); _hasPrepared = true; } TransformAndTranslateVertices(viewport, node, view, projection, world); RenderFaces(node, viewport, view, projection, world); RenderLines(node, viewport, view, projection, world); if (viewport.DebugInfo.ShowVertices) { RenderVertices(node, viewport, view, projection, world); } }
public void SetCameraDefinition(Viewport viewport, Camera camera) { Vector dir, nc, fc, X, Y, Z; SetCameraInternals(camera.FieldOfView, viewport.AspectRatio, camera.Near, camera.Far); Z = camera.Target-camera.Position; Z.Normalize(); X = camera.Up * Z; X.Normalize(); Y = Z * X; nc = camera.Position - Z * _near; fc = camera.Position - Z * _far; ntl = nc + Y * _nh - X * _nw; ntr = nc + Y * _nh + X * _nw; nbl = nc - Y * _nh - X * _nw; nbr = nc - Y * _nh + X * _nw; ftl = fc + Y * _fh - X * _fw; ftr = fc + Y * _fh + X * _fw; fbl = fc - Y * _fh - X * _fw; fbr = fc - Y * _fh + X * _fw; _planes[(int)FrustumLocation.Top].SetVectors(ntr, ntl, ftl); _planes[(int)FrustumLocation.Bottom].SetVectors(nbl, nbr, fbr); _planes[(int)FrustumLocation.Left].SetVectors(ntl, nbl, fbl); _planes[(int)FrustumLocation.Right].SetVectors(nbr, ntr, fbr); _planes[(int)FrustumLocation.Near].SetVectors(ntl, ntr, fbr); _planes[(int)FrustumLocation.Far].SetVectors(ftr, ftl, fbl); }
/// <summary> /// Calculates the projection matrix /// </summary> private void SetupProjection(Viewport viewport) { var projectionMatrix = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(FieldOfView), viewport.AspectRatio, Near, Far); //var screenTranslationMatrix = Matrix.CreateScreenTranslation(viewport.Width, viewport.Height); ProjectionMatrix = projectionMatrix; // *screenTranslationMatrix; }
private static void RenderScaled(Viewport viewport, int positionOffset, int actualX, int actualY, Image image, Vector translatedPosition, int bufferSize, UInt32 bufferZ, float xScale, float yScale) { var imageContext = image.ImageContext as ImageContext; var actualWidth = (int)(((float)image.Width) * xScale); var actualHeight = (int)(((float)image.Height) * yScale); if (actualWidth <= 0 || actualHeight <= 0) { return; } var spriteOffset = 0; XScalingInterpolator.SetPoint(0, 0f, image.Width); XScalingInterpolator.Interpolate(actualWidth); YScalingInterpolator.SetPoint(0, 0f, image.Height); YScalingInterpolator.Interpolate(actualHeight); var currentY = actualY; for (var y = 0; y < actualHeight; y++) { if (currentY >= viewport.Height) { break; } if (currentY >= 0) { var currentX = actualX; var offset = y*BufferContainer.Stride; var spriteY = (int) YScalingInterpolator.Points[0].InterpolatedValues[y]; for (var x = 0; x < actualWidth; x++) { if (currentX >= viewport.Width) { break; } if (currentX >= 0) { var actualOffset = offset + positionOffset; var spriteX = (int) XScalingInterpolator.Points[0].InterpolatedValues[x]; spriteOffset = (int) ((spriteY*image.Width) + spriteX); if (actualOffset >= 0 && actualOffset < bufferSize && bufferZ > BufferContainer.DepthBuffer[actualOffset]) { var pixel = BlendPixel(imageContext.Pixels[spriteOffset], BufferContainer.Framebuffer[actualOffset]); if ((pixel & 0xff000000) != 0) { BufferContainer.Framebuffer[actualOffset] = pixel; BufferContainer.DepthBuffer[actualOffset] = bufferZ; } } } offset++; currentX++; } } currentY++; } }
private void TransformAndTranslateVertices(Viewport viewport, RenderableNode node, Matrix view, Matrix projection, Matrix world) { for (var vertexIndex = 0; vertexIndex < Vertices.Length; vertexIndex++) { var vertex = Vertices[vertexIndex]; TransformAndTranslateVertex(ref vertex, viewport, view, projection, world); CalculateColorForVertex(ref vertex, viewport, node); Vertices[vertexIndex] = vertex; } }
private static void TransformAndTranslateVertex(ref Vertex vertex, Viewport viewport, Matrix view, Matrix projection) { vertex.Transform(view); vertex.Translate(projection, viewport.Width, viewport.Height); vertex.MakeScreenCoordinates(); vertex.TransformedVectorNormalized = vertex.TransformedNormal; vertex.TransformedVectorNormalized.Normalize(); var z = ((vertex.TransformedVector.Z / viewport.View.DepthDivisor) + viewport.View.DepthZero); vertex.DepthBufferAdjustedZ = z; }