예제 #1
0
 public TriangleMesh(Transform o2w, Transform w2o, bool ro, int nt,
                     int nv, int[] vi, Point[] P, Normal[] N,
                      Vector[] S, float[] uv, Texture<float> atex)
     : base(o2w, w2o, ro)
 {
     alphaTexture = atex;
     ntris = nt;
     nverts = nv;
     MathHelper.Copy<int>(ref vertexIndex, ref vi);
     if (uv != null)
     {
         MathHelper.Copy<float>(ref uvs, ref uv);
     }
     else
         uvs = null;
     if (N != null)
     {
         MathHelper.Copy<Normal>(ref n, ref N);
     }
     else n = null;
     if (S != null)
     {
         MathHelper.Copy<Vector>(ref s, ref S);
     }
     else s = null;
     for (int i = 0; i < nverts; ++i)
         p[i] = (ObjectToWorld)[P[i]];
 }
예제 #2
0
 public override bool Intersect(Ray r, Pointer<float> tHit, Pointer<float> rayEpsilon, Pointer<DifferentialGeometry> dg)
 {
     Ray ray = (WorldToObject)[r];
     if (MathHelper.Abs(ray.Direction.Z) < 1e-7) return false;
     float thit = (Height - ray.Origin.Z) / ray.Direction.Z;
     if (thit < ray.MinT || thit > ray.MaxT)
         return false;
     Point phit = ray[thit];
     float dist2 = phit.X * phit.X + phit.Y * phit.Y;
     if (dist2 > Radius * Radius || dist2 < InnerRadius * InnerRadius)
         return false;
     float phi = MathHelper.Atan2(phit.Y, phit.X);
     if (phi < 0) phi += 2.0f * MathHelper.PI;
     if (phi > PhiMax)
         return false;
     float u = phi / PhiMax;
     float oneMinusV = ((MathHelper.Sqrt(dist2) - InnerRadius) /
                        (Radius - InnerRadius));
     float invOneMinusV = (oneMinusV > 0.0f) ? (1.0f / oneMinusV) : 0.0f;
     float v = 1.0f - oneMinusV;
     Vector dpdu = new Vector(-PhiMax * phit.Y, PhiMax * phit.X, 0);
     Vector dpdv = new Vector(-phit.X * invOneMinusV, -phit.Y * invOneMinusV, 0);
     dpdu *= PhiMax * MathHelper.InvTwoPI;
     dpdv *= (Radius - InnerRadius) / Radius;
     Normal dndu = new Normal(0, 0, 0), dndv = new Normal(0, 0, 0);
     Transform o2w = ObjectToWorld;
     dg[0] = new DifferentialGeometry(o2w[phit], o2w[dpdu], o2w[dpdv],
                                o2w[dndu], o2w[dndv], u, v, this);
     tHit[0] = thit;
     rayEpsilon[0] = 5e-4f * ~tHit;
     return true;
 }
예제 #3
0
 public override bool Intersect(Ray r, Pointer<float> tHit, Pointer<float> rayEpsilon, Pointer<DifferentialGeometry> dg)
 {
     float phi;
     Point phit;
     Ray ray = (WorldToObject)[r];
     float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y;
     float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y);
     float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y - Radius * Radius;
     float t0 = 0, t1 = 0;
     if (!MathHelper.Quadratic(A, B, C, ref t0, ref t1))
         return false;
     if (t0 > ray.MaxT || t1 < ray.MinT)
         return false;
     float thit = t0;
     if (t0 < ray.MinT)
     {
         thit = t1;
         if (thit > ray.MaxT) return false;
     }
     phit = ray[thit];
     phi = MathHelper.Atan2(phit.Y, phit.X);
     if (phi < 0) phi += 2.0f * MathHelper.PI;
     if (phit.Z < ZMin || phit.Z > ZMax || phi > PhiMax)
     {
         if (thit == t1) return false;
         thit = t1;
         if (t1 > ray.MaxT) return false;
         phit = ray[thit];
         phi = MathHelper.Atan2(phit.Y, phit.X);
         if (phi < 0) phi += 2.0f * MathHelper.PI;
         if (phit.Z < ZMin || phit.Z > ZMax || phi > PhiMax)
             return false;
     }
     float u = phi / PhiMax;
     float v = (phit.Z - ZMin) / (ZMax - ZMin);
     Vector dpdu = new Vector(-PhiMax * phit.Y, PhiMax * phit.X, 0);
     Vector dpdv = new Vector(0, 0, ZMax - ZMin);
     Vector d2Pduu = -PhiMax * PhiMax * new Vector(phit.X, phit.Y, 0);
     Vector d2Pduv = new Vector(0, 0, 0), d2Pdvv = new Vector(0, 0, 0);
     float E = Vector.Dot(dpdu, dpdu);
     float F = Vector.Dot(dpdu, dpdv);
     float G = Vector.Dot(dpdv, dpdv);
     Vector N = Vector.Normalize(Vector.Cross(dpdu, dpdv));
     float e = Vector.Dot(N, d2Pduu);
     float f = Vector.Dot(N, d2Pduv);
     float g = Vector.Dot(N, d2Pdvv);
     float invEGF2 = 1.0f / (E * G - F * F);
     Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv);
     Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv);
     Transform o2w = ObjectToWorld;
     dg[0] = new DifferentialGeometry(o2w[phit], o2w[dpdu], o2w[dpdv],
                                o2w[dndu], o2w[dndv], u, v, this);
     tHit[0] = thit;
     rayEpsilon[0] = 5e-4f * ~tHit;
     return true;
 }
예제 #4
0
 public DifferentialGeometry(Point P, Vector DPDU, Vector DPDV, Normal DNDU, Normal DNDV, float uu, float vv, Shape sh)
 {
     p = (P);
     dpdu = (DPDU);
     dpdv = (DPDV);
     dndu = (DNDU);
     dndv = (DNDV);
     nn = new Normal(Vector.Normalize(Vector.Cross(dpdu, dpdv)));
     u = uu;
     v = vv;
     shape = sh;
     dudx = dvdx = dudy = dvdy = 0;
     dpdx = dpdy = new Vector();
     if (shape != null && (shape.ReverseOrientation ^ shape.TransformSwapsHandedness))
         nn *= -1.0f;
 }
예제 #5
0
 public void Setdndv(Normal n)
 {
     dndv = n;
 }
예제 #6
0
 public void Setdndu(Normal n)
 {
     dndu = n;
 }
예제 #7
0
 public void Setnn(Normal nn)
 {
     this.nn = nn;
 }
예제 #8
0
 public override bool Intersect(Ray r, Pointer<float> tHit, Pointer<float> rayEpsilon, Pointer<DifferentialGeometry> dg)
 {
     float phi, v;
     Point phit;
     Ray ray = (WorldToObject)[r];
     float A = a * ray.Direction.X * ray.Direction.X +
               a * ray.Direction.Y * ray.Direction.Y -
               c * ray.Direction.Z * ray.Direction.Z;
     float B = 2.0f * (a * ray.Direction.X * ray.Origin.X +
                      a * ray.Direction.Y * ray.Origin.Y -
                      c * ray.Direction.Z * ray.Origin.Z);
     float C = a * ray.Origin.X * ray.Origin.X +
               a * ray.Origin.Y * ray.Origin.Y -
               c * ray.Origin.Z * ray.Origin.Z - 1;
     float t0 = 0, t1 = 0;
     if (!MathHelper.Quadratic(A, B, C, ref t0, ref t1))
         return false;
     if (t0 > ray.MaxT || t1 < ray.MinT)
         return false;
     float thit = t0;
     if (t0 < ray.MinT)
     {
         thit = t1;
         if (thit > ray.MaxT) return false;
     }
     phit = ray[thit];
     v = (phit.Z - p1.Z) / (p2.Z - p1.Z);
     Point pr = (1.0f - v) * p1 + v * p2;
     phi = MathHelper.Atan2(pr.X * phit.Y - phit.X * pr.Y,
         phit.X * pr.X + phit.Y * pr.Y);
     if (phi < 0)
         phi += 2 * MathHelper.PI;
     if (phit.Z < zmin || phit.Z > zmax || phi > phiMax)
     {
         if (thit == t1) return false;
         thit = t1;
         if (t1 > ray.MaxT) return false;
         phit = ray[thit];
         v = (phit.Z - p1.Z) / (p2.Z - p1.Z);
         Point pr2 = (1.0f - v) * p1 + v * p2;
         phi = MathHelper.Atan2(pr2.X * phit.Y - phit.X * pr2.Y,
             phit.X * pr2.X + phit.Y * pr2.Y);
         if (phi < 0)
             phi += 2 * MathHelper.PI;
         if (phit.Z < zmin || phit.Z > zmax || phi > phiMax)
             return false;
     }
     float u = phi / phiMax;
     float cosphi = MathHelper.Cos(phi), sinphi = MathHelper.Sin(phi);
     Vector dpdu = new Vector(-phiMax * phit.Y, phiMax * phit.X, 0);
     Vector dpdv = new Vector((p2.X - p1.X) * cosphi - (p2.Y - p1.Y) * sinphi,
         (p2.X - p1.X) * sinphi + (p2.Y - p1.Y) * cosphi,
         p2.Z - p1.Z);
     Vector d2Pduu = -phiMax * phiMax *
                     new Vector(phit.X, phit.Y, 0);
     Vector d2Pduv = phiMax *
                     new Vector(-dpdv.Y, dpdv.X, 0);
     Vector d2Pdvv = new Vector(0, 0, 0);
     float E = Vector.Dot(dpdu, dpdu);
     float F = Vector.Dot(dpdu, dpdv);
     float G = Vector.Dot(dpdv, dpdv);
     Vector N = Vector.Normalize(Vector.Cross(dpdu, dpdv));
     float e = Vector.Dot(N, d2Pduu);
     float f = Vector.Dot(N, d2Pduv);
     float g = Vector.Dot(N, d2Pdvv);
     float invEGF2 = 1.0f / (E * G - F * F);
     Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu +
                          (e * F - f * E) * invEGF2 * dpdv);
     Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu +
                          (f * F - g * E) * invEGF2 * dpdv);
     Transform o2w = ObjectToWorld;
     dg[0] = new DifferentialGeometry(o2w[phit], o2w[dpdu], o2w[dpdv],
                                o2w[dndu], o2w[dndv], u, v, this);
     tHit[0] = thit;
     rayEpsilon[0] = 5e-4f * tHit;
     return true;
 }
예제 #9
0
 public static Vector Cross(Normal v1, Vector v2)
 {
     return v1.Cross(v2);
 }
예제 #10
0
 public static Vector Cross(Vector v1, Normal v2)
 {
     return v2.Cross(v1);
 }
예제 #11
0
 public Normal this[Normal n]
 {
     get
     {
         float x = n.X, y = n.Y, z = n.Z;
         return new Normal(minv[0, 0] * x + minv[1, 0] * y + minv[2, 0] * z,
                       minv[0, 1] * x + minv[1, 1] * y + minv[2, 1] * z,
                       minv[0, 2] * x + minv[1, 2] * y + minv[2, 2] * z);
     }
 }
예제 #12
0
 public static Normal Normalize(Normal vector)
 {
     vector.Normalize();
     return vector;
 }
예제 #13
0
        public override void GetShadingGeometry(Transform obj2world, DifferentialGeometry dg, Pointer<DifferentialGeometry> dgShading)
        {
            if (mesh.n == null && mesh.s == null)
            {
                dgShading[0] = dg;
                return;
            }
            float[] b = new float[3];
            float[][] uv = new float[3][];
            uv[0] = new float[2];
            uv[1] = new float[2];
            uv[2] = new float[2];
            GetUVs(uv);
            float[][] A = { new float[2]
    { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] },
    new float[2]
    { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] } 
    };
            float[] C = { dg.u - uv[0][0], dg.v - uv[0][1] };
            if (!Transform.SolveLinearSystem2x2(A, C, ref b[1], ref b[2]))
            {
                b[0] = b[1] = b[2] = 1.0f / 3.0f;
            }
            else
                b[0] = 1.0f - b[1] - b[2];
            Normal ns;
            Vector ss, ts;
            if (mesh.n != null) ns = Normal.Normalize(obj2world[b[0] * mesh.n[v[0]] +
                                                  b[1] * mesh.n[v[1]] +
                                                  b[2] * mesh.n[v[2]]]);
            else ns = dg.nn;
            if (mesh.s != null) ss = Vector.Normalize(obj2world[b[0] * mesh.s[v[0]] +
                                                  b[1] * mesh.s[v[1]] +
                                                  b[2] * mesh.s[v[2]]]);
            else ss = Vector.Normalize(dg.dpdu);

            ts = Vector.Cross(ss, ns);
            if (ts.SquaredMagnitude > 0.0f)
            {
                ts = Vector.Normalize(ts);
                ss = Vector.Cross(ts, ns);
            }
            else
                Extensions.CoordinateSystem((Vector)ns, out ss, out ts);
            Normal dndu, dndv;
            if (mesh.n != null)
            {
                float[][] uvs = new float[3][];
                uvs[0] = new float[2];
                uvs[1] = new float[2];
                uvs[2] = new float[2];
                GetUVs(uvs);
                float du1 = uvs[0][0] - uvs[2][0];
                float du2 = uvs[1][0] - uvs[2][0];
                float dv1 = uvs[0][1] - uvs[2][1];
                float dv2 = uvs[1][1] - uvs[2][1];
                Normal dn1 = mesh.n[v[0]] - mesh.n[v[2]];
                Normal dn2 = mesh.n[v[1]] - mesh.n[v[2]];
                float determinant = du1 * dv2 - dv1 * du2;
                if (determinant == 0.0f)
                    dndu = dndv = new Normal(0, 0, 0);
                else
                {
                    float invdet = 1.0f / determinant;
                    dndu = ((dv2 * dn1 - dv1 * dn2) * invdet);
                    dndv = ((-du2 * dn1 + du1 * dn2) * invdet);
                }
            }
            else
                dndu = dndv = new Normal(0, 0, 0);
            dgShading[0] = new DifferentialGeometry(dg.p, ss, ts, (ObjectToWorld)[dndu], (ObjectToWorld)[dndv],
                dg.u, dg.v, dg.shape);
            dgShading[0].Setdudx(dg.dudx); 
            dgShading[0].Setdvdx(dg.dvdx);
            dgShading[0].Setdudy(dg.dudy); 
            dgShading[0].Setdvdy(dg.dvdy);
            dgShading[0].Setdpdx(dg.dpdx); 
            dgShading[0].Setdpdy(dg.dpdy);
        }
예제 #14
0
 public override Point Sample(float u1, float u2, Pointer<Normal> n)
 {
     float b1 = 0, b2 = 0;
     Extensions.UniformSampleTriangle(u1, u2, ref b1, ref b2);
     Point p1 = mesh.p[v[0]];
     Point p2 = mesh.p[v[1]];
     Point p3 = mesh.p[v[2]];
     Point p = b1 * p1 + b2 * p2 + (1.0f - b1 - b2) * p3;
     Normal n2 = new Normal(Vector.Cross(p2 - p1, p3 - p1));
     n[0] = Normal.Normalize(n2);
     if (ReverseOrientation) n[0] *= -1.0f;
     return p;
 }
예제 #15
0
 public override bool Intersect(Ray r, Pointer<float> tHit, Pointer<float> rayEpsilon, Pointer<DifferentialGeometry> dg)
 {
     float phi;
     Point phit = new Point();
     Ray ray = (WorldToObject)[r];
     float A = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y + ray.Direction.Z * ray.Direction.Z;
     float B = 2 * (ray.Direction.X * ray.Origin.X + ray.Direction.Y * ray.Origin.Y + ray.Direction.Z * ray.Origin.Z);
     float C = ray.Origin.X * ray.Origin.X + ray.Origin.Y * ray.Origin.Y +
               ray.Origin.Z * ray.Origin.Z - Radius * Radius;
     float t0 = 0, t1 = 0;
     if (!MathHelper.Quadratic(A, B, C, ref t0, ref t1))
         return false;
     if (t0 > ray.MaxT || t1 < ray.MinT)
         return false;
     float thit = t0;
     if (t0 < ray.MinT)
     {
         thit = t1;
         if (thit > ray.MaxT) return false;
     }
     phit = ray[thit];
     if (phit.X == 0.0f && phit.Y == 0.0f) phit.X = 1e-5f * Radius;
     phi = MathHelper.Atan2(phit.Y, phit.X);
     if (phi < 0.0f) phi += 2.0f * MathHelper.PI;
     if ((zmin > -Radius && phit.Z < zmin) ||
         (zmax < Radius && phit.Z > zmax) || phi > phiMax)
     {
         if (thit == t1) return false;
         if (t1 > ray.MaxT) return false;
         thit = t1;
         phit = ray[thit];
         if (phit.X == 0.0f && phit.Y == 0.0f) phit.X = 1e-5f * Radius;
         phi = MathHelper.Atan2(phit.Y, phit.X);
         if (phi < 0.0f) phi += 2.0f * MathHelper.PI;
         if ((zmin > -Radius && phit.Z < zmin) ||
             (zmax < Radius && phit.Z > zmax) || phi > phiMax)
             return false;
     }
     float u = phi / phiMax;
     float theta = MathHelper.Acos(MathHelper.Clamp(phit.Z / Radius, -1.0f, 1.0f));
     float v = (theta - thetaMin) / (thetaMax - thetaMin);
     float zradius = MathHelper.Sqrt(phit.X * phit.X + phit.Y * phit.Y);
     float invzradius = 1.0f / zradius;
     float cosphi = phit.X * invzradius;
     float sinphi = phit.Y * invzradius;
     Vector dpdu = new Vector(-phiMax * phit.Y, phiMax * phit.X, 0);
     Vector dpdv = (thetaMax - thetaMin) *
         new Vector(phit.Z * cosphi, phit.Z * sinphi,
                -Radius * MathHelper.Sin(theta));
     Vector d2Pduu = -phiMax * phiMax * new Vector(phit.X, phit.Y, 0);
     Vector d2Pduv = (thetaMax - thetaMin) * phit.Z * phiMax *
                     new Vector(-sinphi, cosphi, 0.0f);
     Vector d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) *
                     new Vector(phit.X, phit.Y, phit.Z);
     float E = Vector.Dot(dpdu, dpdu);
     float F = Vector.Dot(dpdu, dpdv);
     float G = Vector.Dot(dpdv, dpdv);
     Vector N = Vector.Normalize(Vector.Cross(dpdu, dpdv));
     float e = Vector.Dot(N, d2Pduu);
     float f = Vector.Dot(N, d2Pduv);
     float g = Vector.Dot(N, d2Pdvv);
     float invEGF2 = 1.0f / (E * G - F * F);
     Normal dndu = new Normal((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv);
     Normal dndv = new Normal((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv);
     Transform o2w = ObjectToWorld;
     dg[0] = new DifferentialGeometry(o2w[phit], o2w[dpdu], o2w[dpdv], o2w[dndu], o2w[dndv], u, v, this);
     tHit[0] = thit;
     rayEpsilon[0] = 5e-4f * ~tHit;
     return true;
 }
예제 #16
0
 public override Point Sample(Point p, float u1, float u2, Pointer<Normal> ns)
 {
     Point Pcenter = (ObjectToWorld)[(new Point(0, 0, 0))];
     Vector wc = Vector.Normalize(Pcenter - p);
     Vector wcX, wcY;
     Extensions.CoordinateSystem(wc, out wcX, out wcY);
     if (Point.DistanceSquared(p, Pcenter) - Radius * Radius < 1e-4f)
         return Sample(u1, u2, ns);
     float sinThetaMax2 = Radius * Radius / Point.DistanceSquared(p, Pcenter);
     float cosThetaMax = MathHelper.Sqrt(MathHelper.Max(0.0f, 1.0f - sinThetaMax2));
     Pointer<DifferentialGeometry> dgSphere = new Pointer<DifferentialGeometry>(new DifferentialGeometry());
     Pointer<float> thit = (Pointer<float>)0, rayEpsilon = (Pointer<float>)0;
     Point ps;
     Ray r = new Ray(p, Extensions.UniformSampleCone(u1, u2, cosThetaMax, wcX, wcY, wc), 1e-3f);
     if (!Intersect(r, thit, rayEpsilon, dgSphere))
         thit[0] = Vector.Dot(Pcenter - p, Vector.Normalize(r.Direction));
     ps = r[thit];
     ns[0] = new Normal(Vector.Normalize(ps - Pcenter));
     if (ReverseOrientation) ns[0] *= -1.0f;
     return ps;
 }