public override void draw(Graphics graphics, Camera camera, WorldLights worldLights) { if (Settings.debug) { distanceToCamera = (float)camera.Position.getMagnitude(); Matrix4 ModelViewProjection = camera.Frustum * camera.View * StaticMatrices.UniformScaleMatrix(scale); renderVertices = GameShapes.UnitAxes(); foreach (Vector4D vertex in renderVertices) { vertex.LeftMultiply(ModelViewProjection); if (Math.Abs(vertex.Z) < Math.Abs(vertex.W)) { vertex.divideByW(); vertex.moveOriginToCenterScreen(); } } PointF[] pointsAll = renderVertices.Select(x => x.getPointXY()).ToArray(); graphics.DrawLine(new Pen(Color.Cyan), pointsAll[0], pointsAll[1]); graphics.DrawLine(new Pen(Color.Magenta), pointsAll[0], pointsAll[2]); graphics.DrawLine(new Pen(Color.Yellow), pointsAll[0], pointsAll[3]); } }
/// <summary> /// For now, the whole game is initialized right here in the construcor. All it needs is a GDI graphics object. /// </summary> #region Constructor public GameHub(Graphics g) { /// New gadget I'm trying out to prevent repeat toggle key presses for pause and debug mode without causing pauses in engines. toggleKeyRepeatPreventer = new ToggleKeyRepeatPreventer(); toggleKeyRepeatPreventer.registerNewToggleKey('p'); toggleKeyRepeatPreventer.registerNewToggleKey('b'); Utilities.findScreenEdges(); System.Windows.Forms.Cursor.Hide(); /// Makes the games camera. Use an FPSCamera for walking or a FreeCamera for space ship like controls camera = new FreeCamera(new Vector4D(500, 20, -60, 1)); /// The WorldLights struct holds all of the lights for the game world. It is given to the graphics engine. lights = new WorldLights(); lights.AmbientLights = new AmbientLight[] { new AmbientLight(10, 10, 10) }; lights.DirectionalLights = new DirectionalLight[] { /*new DirectionalLight(new Vector3D(0, 1, 0), 0, 100, 0)*/ }; lights.PointLights = new PointLight[] { new PointLight(new Vector3D(100, 100, -200), 60000, 100, 170, 240, camera), new PointLight(new Vector3D(500, -100, 100), 30000, 200, 90, 210, camera) }; origin = new Origin(50); graphics = new GraphicsEngineGDI(16, g, camera, lights); physics = new PhysicsEngine(16); graphics.Initialize(); physics.Initialize(); testObjs = new GameEntity[128]; for (int i = 0; i < 128; i++) { testObjs[i] = new GameObject (i * 4 + 8, (i * 20) % 100, 8, // Position x, y, z, 0, 0, 0, // Velocity x, y, z, 0, 0, 0, // Rotation x, y, z, 10, 10, 10, // Scale x, y, z, GameShapes.UnitCubeGDI(), 10); // Mesh, Radius } /// Put our test cubes into the graphics engine for depth-sorted rendering graphics.addObjectsToRenderZSorted(testObjs.ToList()); graphics.addObjectToRenderZSorted(origin); graphics.addObjectToRenderZSorted(lights.PointLights[0]); graphics.addObjectToRenderZSorted(lights.PointLights[1]); /// User input is processed by the physics engine right now. physics.addControlRoutine(ParseInput); /// Put our test cubes into the physics engine. physics.addObjectsToMove(testObjs); }
/// <summary> /// Calculates the lighting for a face before it is drawn /// </summary> /// <param name="meshVertices">List of all vertices of the mesh to which this face belongs</param> /// <param name="worldLights">Set of all the world's lights that affect this face</param> /// <param name="position">Position of the mesh to which this face belongs, in world space</param> public void calculateWorldLighting(Vector4D[] meshVertices, WorldLights worldLights, Vector3D position) { color[0] = 0; color[1] = 0; color[2] = 0; normal = Vector4D.cross3D(meshVertices[vertexIndex[0]] - meshVertices[vertexIndex[1]], meshVertices[vertexIndex[1]] - meshVertices[vertexIndex[2]]); normal.normalize(); #region Ambient Lights foreach (AmbientLight light in worldLights.AmbientLights) { color[0] += light.Red; color[1] += light.Green; color[2] += light.Blue; } #endregion #region Directional Lights foreach (DirectionalLight light in worldLights.DirectionalLights) { lightBrightness = (float)Math.Max(0, Vector3D.dot(normal, light.Direction)); color[0] += (int)(light.Red * lightBrightness); color[1] += (int)(light.Green * lightBrightness); color[2] += (int)(light.Blue * lightBrightness); } #endregion #region Point Lights foreach (PointLight light in worldLights.PointLights) { lightDirection = position - light.Position; pointLightBrightnessFallOff = (float)(Math.Pow(lightDirection.getMagnitude(), 2) / light.Intensity); lightDirection.normalize(); lightBrightness = (float)Math.Max(0, Vector3D.dot(normal, lightDirection) / Math.Max(1, pointLightBrightnessFallOff)); color[0] += (int)(light.Red * lightBrightness); color[1] += (int)(light.Green * lightBrightness); color[2] += (int)(light.Blue * lightBrightness); } #endregion }
public GraphicsEngineGDI(int inverseFPMS, Graphics graphics, Camera camera, WorldLights worldLights) : base(inverseFPMS) { renderQueue = new RenderQueue((Graphics g, Camera c, WorldLights l) => { }); zSortedObjects = new List <GameEntity>(); cullData = new FrustumCullingData(camera.FOV, camera.AspRat); this.camera = camera; this.graphics = graphics; this.worldLights = worldLights; backBufferContext = BufferedGraphicsManager.Current; backBuffer = backBufferContext.Allocate(graphics, Utilities.screenBounds); addPermanentRoutine(backBuffer.Render); addPermanentRoutine(camera.createView); addPermanentRoutine(ClearScreen); addPermanentRoutine(cullAndSortRenderOrder); }
public override void draw(Graphics graphics, Camera camera, WorldLights worldLights) { if (Settings.debug) { Vector4D centerVector = Vector4D.Zero(); centerVector.LeftMultiply(StaticMatrices.TranslationMatrix(position)); centerVector.LeftMultiply(camera.View); distanceToCamera = (float)centerVector.getMagnitude(); centerVector.LeftMultiply(camera.Frustum); centerVector.divideByW(); centerVector.moveOriginToCenterScreen(); Matrix4 mat = camera.Frustum * camera.View * StaticMatrices.TranslationMatrix(position) * StaticMatrices.ScaleMatrix(new Vector3D(intensity * .0005, intensity * .0005, intensity * .0005)); Vector4D[] vertices = GameShapes.Tetrahedron(); for (int i = 0; i < 4; i++) { vertices[i].LeftMultiply(mat); vertices[i].divideByW(); vertices[i].moveOriginToCenterScreen(); } PointF[] pointsAll = vertices.Select(x => x.getPointXY()).ToArray(); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[0], pointsAll[1]); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[0], pointsAll[2]); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[0], pointsAll[3]); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[1], pointsAll[2]); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[1], pointsAll[3]); graphics.DrawLine(new Pen(Color.FromArgb((int)red, (int)green, (int)blue), 2), pointsAll[2], pointsAll[3]); graphics.DrawString((intensity * .001).ToString() + "K", new Font("Arial", 12), new SolidBrush(Color.White), centerVector.getPointXY()); } }
public override void preDraw(Graphics graphics, Camera camera, WorldLights worldLights) { }
public override void draw(Graphics graphics, Camera camera, WorldLights worldLights) { mesh.draw(graphics); }
public override void preDraw(Graphics graphics, Camera camera, WorldLights worldLights) { mesh.preDraw(graphics, camera, worldLights, rotation, scale, position); }
public abstract void preDraw(Graphics graphics, Camera camera, WorldLights worldLights);
public abstract override void draw(Graphics graphics, Camera camera, WorldLights worldLights);
/// <summary> /// preDraw is called by the graphics engine before object Z-sorting is done. It get's everything ready for drawing. /// </summary> /// <param name="graphics">GDI graphics to use</param> /// <param name="camera">Camera to use</param> /// <param name="worldLights">Set of lights to use</param> /// <param name="rotation">Rotation of mesh</param> /// <param name="scale">Scale of mesh</param> /// <param name="position">Position of mesh</param> public void preDraw(Graphics graphics, Camera camera, WorldLights worldLights, Vector3D rotation, Vector3D scale, Vector3D position) { #region Generate transform matrices Matrix4 ViewProjectionMatrix = camera.Frustum * camera.View; Matrix4 WorldTransformMatrix = StaticMatrices.TranslationMatrix(position) * StaticMatrices.RotationMatrixZYX(rotation) * StaticMatrices.ScaleMatrix(scale); #endregion #region Start with vertices in object (local) space for (int i = 0; i < dynamicVertices.Length; i++) { dynamicVertices[i].setVector(staticVertices[i]); } #endregion #region Transform vertices to world space (combinining the scale, rotation, and position matrices) foreach (Vector4D vertex in dynamicVertices) { vertex.LeftMultiply(WorldTransformMatrix); } #endregion #region Calculate lighting from world lights /// Have yet to test whether parallel is actually faster, so leaving original code: //foreach (FaceGDI face in faces) // face.calculateWorldLighting(dynamicVertices, worldLights, position); Parallel.For(0, faces.Length, i => { faces[i].calculateWorldLighting(dynamicVertices, worldLights, position); }); #endregion #region Transform vertices to view space (combining camera view and frustum transforms) foreach (Vector4D vertex in dynamicVertices) { /// Transforms vertex into camera space and applies frustum matrix vertex.LeftMultiply(ViewProjectionMatrix); /// Creates the illusion of perspective, shringing the x, y, and z values based on the original z value, as stored in w. vertex.divideByW(); /// Required to compensate for GDI's upper-left-hand corner origin - could be done elsewhere - maybe doesn't need to be done for each vertex each frame - look into it. vertex.moveOriginToCenterScreen(); } #endregion // Faces are now ready to draw. This last bit is for the Z-Sorting and distance read out and stuff. #region Calculate render position and distance from camera renderPositionGDI.zero(); renderPositionGDI.LeftMultiply(WorldTransformMatrix); renderPositionGDI.LeftMultiply(camera.View); distanceFromCamera = (float)renderPositionGDI.getMagnitude(); if (Settings.debug) { renderPositionGDI.LeftMultiply(camera.Frustum); renderPositionGDI.divideByW(); renderPositionGDI.moveOriginToCenterScreen(); } #endregion }