Пример #1
0
        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());
            }
        }
Пример #6
0
 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
        }