예제 #1
0
        public Float3 lerpNormal(Float3 currentValue, Float3 newValue)
        {
            if (currentValue == Float3.zero)
                return newValue;

            return Float3.lerp(currentValue, newValue, 0.5f).normalize();
        }
예제 #2
0
 public Quaternion(float w, Float3 v)
 {
     this.w = w;
     this.x = v.x;
     this.y = v.y;
     this.z = v.z;
 }
        public void NoTransformTest()
        {
            Float3 p = new Float3(1, 3, 7);
            Float4x4 M = Float4x4.identity;

            Assert.AreEqual(p, M.transformPoint(p));
        }
예제 #4
0
 public Vertex(Float3 position)
 {
     this.position = position;
     this.normal = Float3.zero;
     this.color = Color.Black;
     this.uv = new Float2(0, 0);
 }
예제 #5
0
 public Float4(Float3 v, float w)
 {
     this.x = v.x;
     this.y = v.y;
     this.z = v.z;
     this.w = w;
 }
예제 #6
0
 public IVertex(Vertex v)
 {
     this.position = (Int3)v.position;
     this.normal = v.normal;
     this.color = v.color;
     this.uv = v.uv;
 }
        public void AddTranslationToExistingMatrixTests()
        {
            Float3 p = new Float3(0, 0, 1);
            Float3 t = new Float3(1, 3, 323);

            Float4x4 X = Float4x4.identity;
            X.setTranslation(t);
            Float4x4 minusX = Float4x4.identity;
            minusX.setTranslation(t.getOpposite());

            Assert.AreEqual(p + t, X.transformPoint(p));
            Assert.AreEqual(p, minusX.transformPoint(X.transformPoint(p)));
        }
        public void SimpleTranslationTest()
        {
            Float3 p = new Float3(1, 3, 7);
            Float3 t = new Float3(1, 2, 3);

            Float4x4 M = new Float4x4(1  , 0  , 0  , 0,
                                      0  , 1  , 0  , 0,
                                      0  , 0  , 1  , 0,
                                      t.x, t.y, t.z, 1);

            Float4x4 M2 = Float4x4.getTranslationMatrix(t);

            Assert.AreEqual(M, M2);
            Assert.AreEqual(p + t, M.transformPoint(p));
            Assert.AreEqual(p + t, M2.transformPoint(p));
        }
        public void SimpleProjectionTest()
        {
            Float3 p = new Float3(2, 4, 2);

            const float n = 3f;
            const float f = 100f;
            const float b = -10;
            const float t = 10;
            const float r = 10;
            const float l = -10;

            Float4x4 Projection = Float4x4.getProjectionMatrix(n, f, t, b, r, l);

            Float3 p2 = Projection.transformPoint(new Float3(r, b, n));
            Float3 p1 = Projection.transformPoint(p);
            Assert.IsTrue(p1.x < 1f);
        }
예제 #10
0
        public static Float3x3 getRotationMatrix(Float3 rotation)
        {
            float xAngle = rotation.x;
            float yAngle = rotation.y;
            float zAngle = rotation.z;

            xAngle *= ((float)Math.PI / 180.0f);
            yAngle *= ((float)Math.PI / 180.0f);
            zAngle *= ((float)Math.PI / 180.0f);

            Float3x3 aboutX = new Float3x3(1, 0, 0,
                                            0, (float)Cos(xAngle), (float)Sin(xAngle),
                                            0, (float)(-Sin(xAngle)), (float)Cos(xAngle));
            Float3x3 aboutY = new Float3x3((float)Cos(yAngle), 0, (float)(-Sin(yAngle)),
                                           0, 1, 0,
                                           (float)Sin(yAngle), 0, (float)Cos(yAngle));
            return aboutX * aboutY;
        }
예제 #11
0
        public Float3 cross(Float3 other)
        {
            //c  = a cross b
            //cx = aybz − azby
            //cy = azbx − axbz
            //cz = axby − aybx

            return new Float3(this.y * other.z - this.z * other.y,
                              this.z * other.x - this.x * other.z,
                              this.x * other.y - this.y * other.x);
        }
예제 #12
0
 public static Float3 lerp(Float3 start, Float3 end, float delta)
 {
     return start + (end - start) * delta;
 }
예제 #13
0
        public void Render(SceneObject sObject, Float3 viewDirection, Float3 lightDirection, bool useProjection = true)
        {
            Mesh mesh = sObject.mesh;
            Color wireFrameColor = Color.LightGreen;
            RenderType renderType = sObject.material.renderType;

            // Vertex uniforms

            // scale matrix
            Float3x3 S = Float3x3.identity * sObject.uniformScale;
            // rotation matrix
            Float3x3 R = Float3x3.getRotationMatrix(sObject.rotation);
            Float3x3 CombinedLinear = S * R;
            // translation
            Float4x4 Tr = Float4x4.identity;
            Tr.setTranslation(sObject.localPosition);
            // projection
            Float4x4 Pr = useProjection ? Float4x4.getProjectionMatrix(10f, 1300f, 1f, 1f) : Float4x4.identity;

            // BACK FACE CULLING
            if (backFaceCulling)
            {
                for (int i = mesh.Triangles.Count - 1; i >= 0; i--)
                {
                    Triangle t = mesh.Triangles[i];

                    Float3 v1 = mesh.Vertices[t[0] - 1].position;
                    Float3 v2 = mesh.Vertices[t[1] - 1].position;
                    Float3 v3 = mesh.Vertices[t[2] - 1].position;
                    Float3 normal = Utils.getTriangleNormalR(v1, v2, v3);

                    // remove faced back triangles
                    if (viewDirection.dot(normal) >= 0)
                        mesh.Triangles.Remove(t);
                }
            }
            // VERTEX SHADER
            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                Vertex v = mesh.Vertices[i];
                // scale
                var p = v.position.mul(S);
                // rotate
                p = p.mul(R);
                // translate
                p = Tr.transformPoint(p);
                // project
                if(useProjection)
                    p = Pr.transformPoint(p);
                // TODO: Transforming normals while NON UNIFORM TRANSFORMS
                v.normal = v.normal.mul(R);

                // TODO: place to center of screen
                if(useProjection)
                    v.position = new Float3(p.x * Defaults.WIDTH + Defaults.WIDTH / 2f, p.y * Defaults.HEIGHT + Defaults.HEIGHT / 2f, p.z);
                else
                    v.position = new Float3(p.x + Defaults.WIDTH / 2f, p.y + Defaults.HEIGHT / 2f, p.z);
            }

            if((renderType & RenderType.Regular) != 0)
                RenderRegular(mesh, sObject.material, lightDirection);

            if ((renderType & RenderType.Wireframe) != 0)
                RenderWireframe(mesh, wireFrameColor);

            if ((renderType & RenderType.Normals) != 0)
                DrawVertexNormals(mesh, Color.Red);
        }
예제 #14
0
 public float dot(Float3 other)
 {
     return this.x * other.x + this.y * other.y + this.z * other.z;
 }
예제 #15
0
        public void Rasterize(Mesh mesh, Material material, Float3 lightDirection)
        {
            // set interpolated color
            for (int i = 0; i < mesh.Triangles.Count; i++)
            {
                Triangle t = mesh.Triangles[i];

                Vertex v1 = mesh.Vertices[t[0] - 1];
                Vertex v2 = mesh.Vertices[t[1] - 1];
                Vertex v3 = mesh.Vertices[t[2] - 1];

                //v2.normal = v1.normal;
                //v3.normal = v1.normal;

                int cc1 = (int)(getLamberComponent(v1.normal, lightDirection) * 255);
                int cc2 = (int)(getLamberComponent(v2.normal, lightDirection) * 255);
                int cc3 = (int)(getLamberComponent(v3.normal, lightDirection) * 255);

                v1.color = Color.FromArgb(cc1, cc1, cc1);//.lerpTo(Color.Green, 0.5f);
                v2.color = Color.FromArgb(cc2, cc2, cc2);//.lerpTo(Color.Blue, 0.5f);
                v3.color = Color.FromArgb(cc3, cc3, cc3);//.lerpTo(Color.Red, 0.5f);
            }

            for (int i = 0; i < mesh.Triangles.Count; i++)
            {
                Triangle t = mesh.Triangles[i];
                Vertex v1 = mesh.Vertices[t[0] - 1];
                Vertex v2 = mesh.Vertices[t[1] - 1];
                Vertex v3 = mesh.Vertices[t[2] - 1];
                RenderTriangle2(v1, v2, v3, material, lightDirection);
            }
        }
예제 #16
0
        private void RenderRegular(Mesh mesh, Material material, Float3 lightDirection)
        {
            rasterizer.Rasterize(mesh, material, lightDirection);

            // FRAGMENT SHADER
            for (int x = 0; x < Defaults.WIDTH; x++)
                for (int y = 0; y < Defaults.HEIGHT; y++)
                    bitmap.elDrawPoint(x, y, zBuffer[x, y].color);
        }
예제 #17
0
        private float getLamberComponent(Float3 normal, Float3 lightDirection)
        {
            normal = normal.normalize();
            lightDirection = lightDirection.normalize();

            float lambertComponent = normal.dot(lightDirection.normalize());
            lambertComponent = lambertComponent < 0 ? 0 : lambertComponent;
            return Utils.Clamp(0, 255, lambertComponent);
        }
예제 #18
0
 public float dot(Float3 other)
 {
     return(this.x * other.x + this.y * other.y + this.z * other.z);
 }
예제 #19
0
 public void setTranslation(Float3 t)
 {
     this._m[3, 0] = t.x;
     this._m[3, 1] = t.y;
     this._m[3, 2] = t.z;
 }
예제 #20
0
        public Float3 transformPoint(Float3 p)
        {
            Float4 tP = this.mul(new Float4(p, 1));

            return(tP.xyz * (1f / tP.w));
        }
예제 #21
0
        private void RenderTriangle2(Vertex _v1, Vertex _v2, Vertex _v3, Material material, Float3 lightDirection)
        {
            IVertex v1 = new IVertex(_v1);
            IVertex v2 = new IVertex(_v2);
            IVertex v3 = new IVertex(_v3);

            if (v1.y > v2.y) Utils.swap(ref v1, ref v2);
            if (v1.y > v3.y) Utils.swap(ref v1, ref v3);
            if (v2.y > v3.y) Utils.swap(ref v2, ref v3);

            int triangleYHeight = v3.y - v1.y + 1;
            int firstSegmentHeight = v2.y - v1.y + 1;
            int secondSegmentHeight = v3.y - v2.y + 1;

            for (int y = v1.y; y <= v3.y; y++)
            {
                bool isFirstSegment = y < v2.y;
                int segmentStartY = isFirstSegment ? v1.y : v2.y;

                float alpha = (float)(y - v1.y) / (float)triangleYHeight;
                IVertex A = IVertex.lerp(v1, v3, alpha);

                float beta = (float)(y - segmentStartY) / (float)(isFirstSegment ? firstSegmentHeight : secondSegmentHeight);
                IVertex B = IVertex.lerp(isFirstSegment ? v1 : v2, isFirstSegment ? v2 : v3, beta);

                if (A.x > B.x)
                    Utils.swap(ref A, ref B);
                for (int x = A.x; x <= B.x; x++)
                {
                    // check extremes
                    float delta = (A.x == B.x) ? 1.0f : (float)(x - A.x) / (float)(B.x - A.x);

                    IVertex C = IVertex.lerp(A, B, delta);

                    float lc = getLamberComponent(C.normal, lightDirection);
                    int intLambert = (int)(lc * 255);
                    Color c = Color.FromArgb(intLambert, intLambert, intLambert);

                    c = tex2D(material.diffuseTexture, C.u, C.v);
                    DrawPointToFrameBuffer(x, y, C.z, c);
                }
            }
        }
예제 #22
0
 public static Float3 lerp(Float3 start, Float3 end, float delta)
 {
     return(start + (end - start) * delta);
 }
예제 #23
0
 public Float3 transformPoint(Float3 p)
 {
     Float4 tP = this.mul(new Float4(p, 1));
     return tP.xyz * (1f / tP.w);
 }
예제 #24
0
 public static Float4x4 getTranslationMatrix(Float3 t)
 {
     return new Float4x4(1  , 0  , 0  , 0,
                         0  , 1  , 0  , 0,
                         0  , 0  , 1  , 0,
                         t.x, t.y, t.z, 1);
 }
예제 #25
0
        public static Mesh ReadMeshFromFile(string filePath)
        {
            Mesh result = new Mesh();
            string[] lines = File.ReadAllLines(filePath);

            List<Float3> normals = new List<Float3>();
            List<Float3> vPositions = new List<Float3>();
            List<Float2> uvs = new List<Float2>();
            List<WObjTriangle> wTriangles = new List<WObjTriangle>();

            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Length == 0)
                    continue;

                string[] lineParts = ReplaceMultipleSpaces(lines[i]).Split(' ');

                // vertex positions
                if (lineParts[0] == "v")
                {
                    Float3 position = new Float3(float.Parse(lineParts[1], System.Globalization.CultureInfo.InvariantCulture),
                                                 float.Parse(lineParts[2], System.Globalization.CultureInfo.InvariantCulture),
                                                 float.Parse(lineParts[3], System.Globalization.CultureInfo.InvariantCulture)
                                                 );

                    vPositions.Add(position);
                }
                // uv coordinates
                if (lineParts[0] == "vt")
                {
                    Float2 uv = new Float2(float.Parse(lineParts[1], System.Globalization.CultureInfo.InvariantCulture),
                                                 float.Parse(lineParts[2], System.Globalization.CultureInfo.InvariantCulture));
                    uvs.Add(uv);
                }
                // normals
                if (lineParts[0] == "vn")
                {
                    Float3 normal = new Float3(float.Parse(lineParts[1], System.Globalization.CultureInfo.InvariantCulture),
                                                float.Parse(lineParts[2], System.Globalization.CultureInfo.InvariantCulture),
                                                float.Parse(lineParts[3], System.Globalization.CultureInfo.InvariantCulture)
                                                );
                    normals.Add(normal);
                }
                if (lineParts[0] == "f")
                {
                    string[] f1 = lineParts[1].Split('/');
                    string[] f2 = lineParts[2].Split('/');
                    string[] f3 = lineParts[3].Split('/');

                    int v1 = int.Parse(f1[0]);
                    int v2 = int.Parse(f2[0]);
                    int v3 = int.Parse(f3[0]);

                    int t1 = -1;
                    int t2 = -1;
                    int t3 = -1;

                    // if texture coordinates specified
                    if (f1.Length > 1)
                    {
                        if (!string.IsNullOrEmpty(f1[1]))
                            t1 = int.Parse(f1[1]);
                        if (!string.IsNullOrEmpty(f2[1]))
                            t2 = int.Parse(f2[1]);
                        if (!string.IsNullOrEmpty(f3[1]))
                            t3 = int.Parse(f3[1]);
                    }

                    int n1 = 0, n2 = 0, n3 = 0;
                    // if normals specified
                    if (f1.Length > 2) {
                        n1 = int.Parse(f1[2]);
                        n2 = int.Parse(f2[2]);
                        n3 = int.Parse(f3[2]);
                    }

                    wTriangles.Add(new WObjTriangle(v1, v2, v3, n1, n2, n3, t1, t2, t3));
                    result.Triangles.Add(new Triangle(v1, v2, v3));
                }
            }

            result.Vertices = new List<Vertex>();
            for(int i = 0; i < vPositions.Count; i++)
            {
                result.Vertices.Add(new Vertex(vPositions[i]));
            }

            for(int i = 0; i < wTriangles.Count; i++)
            {
                WObjTriangle wTriangle = wTriangles[i];

                Vertex v1 = result.Vertices[wTriangle.v1 - 1];
                Vertex v2 = result.Vertices[wTriangle.v2 - 1];
                Vertex v3 = result.Vertices[wTriangle.v3 - 1];

                if(normals.Count > 0)
                {
                    v1.normal = normals[wTriangle.n1 - 1];
                    v2.normal = normals[wTriangle.n2 - 1];
                    v3.normal = normals[wTriangle.n3 - 1];
                }

                if (uvs.Count > 0)
                {
                    if (wTriangle.uv1 < 0 || wTriangle.uv2 < 0 || wTriangle.uv3 < 0)
                        continue;
                    v1.uv = uvs[wTriangle.uv1 - 1];
                    v2.uv = uvs[wTriangle.uv2 - 1];
                    v3.uv = uvs[wTriangle.uv3 - 1];
                }
            }

            return result;
        }
예제 #26
0
 public void setTranslation(Float3 t)
 {
     this._m[3, 0] = t.x;
     this._m[3, 1] = t.y;
     this._m[3, 2] = t.z;
 }
예제 #27
0
 public Float3x3(Float3[] rows)
     :this(rows[0].x, rows[0].y, rows[0].z,
          rows[1].x, rows[1].y, rows[1].z,
          rows[2].x, rows[2].y, rows[2].z)
 {}