コード例 #1
0
ファイル: sphere.cpp プロジェクト: KojiNakamaru/pbrt-v3
bool Sphere::Intersect(const Ray &r, Float *tHit,
                       SurfaceInteraction *isect) const {
    Float phi;
    Point3f pHit;
    // Transform _Ray_ to object space
    Vector3f oErr, dErr;
    Ray ray = (*WorldToObject)(r, &oErr, &dErr);

    // Compute quadratic sphere coefficients

    // Initialize _EFloat_ ray coordinate values
    EFloat ox(ray.o.x, oErr.x), oy(ray.o.y, oErr.y), oz(ray.o.z, oErr.z);
    EFloat dx(ray.d.x, dErr.x), dy(ray.d.y, dErr.y), dz(ray.d.z, dErr.z);
    EFloat a = dx * dx + dy * dy + dz * dz;
    EFloat b = 2 * (dx * ox + dy * oy + dz * oz);
    EFloat c = ox * ox + oy * oy + oz * oz - EFloat(radius) * EFloat(radius);

    // Solve quadratic equation for _t_ values
    EFloat t0, t1;
    if (!Quadratic(a, b, c, &t0, &t1)) return false;

    // Check quadric shape _t0_ and _t1_ for nearest intersection
    if (t0.UpperBound() > ray.tMax || t1.LowerBound() <= 0) return false;
    EFloat tShapeHit = t0;
    if (t0.LowerBound() <= 0) {
        tShapeHit = t1;
        if (tShapeHit.UpperBound() > ray.tMax) return false;
    }

    // Compute sphere hit position and $\phi$
    pHit = ray((Float)tShapeHit);

    // Refine sphere intersection point
    pHit *= radius / Distance(pHit, Point3f(0, 0, 0));
    if (pHit.x == 0 && pHit.y == 0) pHit.x = 1e-5f * radius;
    phi = std::atan2(pHit.y, pHit.x);
    if (phi < 0) phi += 2 * Pi;

    // Test sphere intersection against clipping parameters
    if ((zMin > -radius && pHit.z < zMin) || (zMax < radius && pHit.z > zMax) ||
        phi > phiMax) {
        if (tShapeHit == t1) return false;
        if (t1.UpperBound() > ray.tMax) return false;
        tShapeHit = t1;
        // Compute sphere hit position and $\phi$
        pHit = ray((Float)tShapeHit);

        // Refine sphere intersection point
        pHit *= radius / Distance(pHit, Point3f(0, 0, 0));
        if (pHit.x == 0 && pHit.y == 0) pHit.x = 1e-5f * radius;
        phi = std::atan2(pHit.y, pHit.x);
        if (phi < 0) phi += 2 * Pi;
        if ((zMin > -radius && pHit.z < zMin) ||
            (zMax < radius && pHit.z > zMax) || phi > phiMax)
            return false;
    }

    // Find parametric representation of sphere hit
    Float u = phi / phiMax;
    Float theta = std::acos(Clamp(pHit.z / radius, -1, 1));
    Float v = (theta - thetaMin) / (thetaMax - thetaMin);

    // Compute sphere $\dpdu$ and $\dpdv$
    Float zRadius = std::sqrt(pHit.x * pHit.x + pHit.y * pHit.y);
    Float invZRadius = 1 / zRadius;
    Float cosPhi = pHit.x * invZRadius;
    Float sinPhi = pHit.y * invZRadius;
    Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0);
    Vector3f dpdv =
        (thetaMax - thetaMin) *
        Vector3f(pHit.z * cosPhi, pHit.z * sinPhi, -radius * std::sin(theta));

    // Compute sphere $\dndu$ and $\dndv$
    Vector3f d2Pduu = -phiMax * phiMax * Vector3f(pHit.x, pHit.y, 0);
    Vector3f d2Pduv =
        (thetaMax - thetaMin) * pHit.z * phiMax * Vector3f(-sinPhi, cosPhi, 0.);
    Vector3f d2Pdvv = -(thetaMax - thetaMin) * (thetaMax - thetaMin) *
                      Vector3f(pHit.x, pHit.y, pHit.z);

    // Compute coefficients for fundamental forms
    Float E = Dot(dpdu, dpdu);
    Float F = Dot(dpdu, dpdv);
    Float G = Dot(dpdv, dpdv);
    Vector3f N = Normalize(Cross(dpdu, dpdv));
    Float e = Dot(N, d2Pduu);
    Float f = Dot(N, d2Pduv);
    Float g = Dot(N, d2Pdvv);

    // Compute $\dndu$ and $\dndv$ from fundamental form coefficients
    Float invEGF2 = 1 / (E * G - F * F);
    Normal3f dndu = Normal3f((f * F - e * G) * invEGF2 * dpdu +
                             (e * F - f * E) * invEGF2 * dpdv);
    Normal3f dndv = Normal3f((g * F - f * G) * invEGF2 * dpdu +
                             (f * F - g * E) * invEGF2 * dpdv);

    // Compute error bounds for sphere intersection
    Vector3f pError = gamma(5) * Abs((Vector3f)pHit);

    // Initialize _SurfaceInteraction_ from parametric information
    *isect = (*ObjectToWorld)(SurfaceInteraction(pHit, pError, Point2f(u, v),
                                                 -ray.d, dpdu, dpdv, dndu, dndv,
                                                 ray.time, this));

    // Update _tHit_ for quadric intersection
    *tHit = (Float)tShapeHit;
    return true;
}
コード例 #2
0
ファイル: Octree.cpp プロジェクト: Allenjonesing/tutorials
void COctree::DrawOctree(COctree *pNode)
{
	// We should already have the octree created before we call this function.
	// This only goes through the nodes that are in our frustum, then renders those
	// vertices stored in their end nodes.  Before we draw a node we check to
	// make sure it is a subdivided node (from m_bSubdivided).  If it is, then
	// we haven't reaches the end and we need to keep recursing through the tree.
	// Once we get to a node that isn't subdivided we draw it's vertices.

	// Make sure a valid node was passed in, otherwise go back to the last node
	if(!pNode) return;


/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *

	// Before we do any checks with the current node, let's make sure we even need too.
	// We want to check if this node's cube is even in our frustum first.
	// To do that we pass in our center point of the node and 1/2 it's width to our 
	// CubeInFrustum() function.  This will return "true" if it is inside the frustum 
	// (camera's view), otherwise return false.  
	else if(g_Frustum.CubeInFrustum(pNode->m_vCenter.x, pNode->m_vCenter.y, 
									pNode->m_vCenter.z, pNode->m_Width / 2))

/////// * /////////// * /////////// * NEW * /////// * /////////// * /////////// *


	// Check if this node is subdivided. If so, then we need to recurse and draw it's nodes
	if(pNode->IsSubDivided())
	{
		// Recurse to the bottom of these nodes and draw the end node's vertices
		// Like creating the octree, we need to recurse through each of the 8 nodes.
		DrawOctree(pNode->m_pOctreeNodes[TOP_LEFT_FRONT]);
		DrawOctree(pNode->m_pOctreeNodes[TOP_LEFT_BACK]);
		DrawOctree(pNode->m_pOctreeNodes[TOP_RIGHT_BACK]);
		DrawOctree(pNode->m_pOctreeNodes[TOP_RIGHT_FRONT]);
		DrawOctree(pNode->m_pOctreeNodes[BOTTOM_LEFT_FRONT]);
		DrawOctree(pNode->m_pOctreeNodes[BOTTOM_LEFT_BACK]);
		DrawOctree(pNode->m_pOctreeNodes[BOTTOM_RIGHT_BACK]);
		DrawOctree(pNode->m_pOctreeNodes[BOTTOM_RIGHT_FRONT]);
	}
	else
	{
		// Increase the amount of nodes in our viewing frustum (camera's view)
		g_TotalNodesDrawn++;

		// Make sure we have valid vertices assigned to this node
		if(!pNode->m_pVertices) return;

		// Render the world data with triangles
		glBegin(GL_TRIANGLES);

		// Turn the polygons green
		glColor3ub(0, 255, 0);

		// Store the vertices in a local pointer to keep code more clean
		CVector3 *pVertices = pNode->m_pVertices;

		// Go through all of the vertices (the number of triangles * 3)
		for(int i = 0; i < pNode->GetTriangleCount() * 3; i += 3)
		{
			// Before we render the vertices we want to calculate the face normal
			// of the current polygon.  That way when lighting is turned on we can
			// see the definition of the terrain more clearly.  In reality you wouldn't do this.
			
			// Here we get a vector from each side of the triangle
			CVector3 vVector1 = pVertices[i + 1] - pVertices[i];
			CVector3 vVector2 = pVertices[i + 2] - pVertices[i];

			// Then we need to get the cross product of those 2 vectors (The normal's direction)
			CVector3 vNormal = Cross(vVector1, vVector2);

			// Now we normalize the normal so it is a unit vector (length of 1)
			vNormal = Normalize(vNormal);

			// Pass in the normal for this triangle so we can see better depth in the scene
			glNormal3f(vNormal.x, vNormal.y, vNormal.z);

			// Render the first point in the triangle
			glVertex3f(pVertices[i].x, pVertices[i].y, pVertices[i].z);

			// Render the next point in the triangle
			glVertex3f(pVertices[i + 1].x, pVertices[i + 1].y, pVertices[i + 1].z);

			// Render the last point in the triangle to form the current triangle
			glVertex3f(pVertices[i + 2].x, pVertices[i + 2].y, pVertices[i + 2].z);
		}

		// Quit Drawing
		glEnd();
	}
}
コード例 #3
0
ファイル: Polygon.cpp プロジェクト: Mars999/MathGeoLib
float3 Polygon::EdgeNormal(int edgeIndex) const
{
	return Cross(Edge(edgeIndex).Dir(), PlaneCCW().normal).Normalized();
}
コード例 #4
0
ファイル: Spline.cpp プロジェクト: Gary1234567/ppsspp
void TesselateBezierPatch(u8 *&dest, int &count, const BezierPatch &patch, u32 origVertType) {
	const float third = 1.0f / 3.0f;

	if (g_Config.bLowQualitySplineBezier) {
		// Fast and easy way - just draw the control points, generate some very basic normal vector subsitutes.
		// Very inaccurate though but okay for Loco Roco. Maybe should keep it as an option.

		float u_base = patch.u_index / 3.0f;
		float v_base = patch.v_index / 3.0f;

		for (int tile_v = 0; tile_v < 3; tile_v++) {
			for (int tile_u = 0; tile_u < 3; tile_u++) {
				int point_index = tile_u + tile_v * 4;

				SimpleVertex v0 = *patch.points[point_index];
				SimpleVertex v1 = *patch.points[point_index+1];
				SimpleVertex v2 = *patch.points[point_index+4];
				SimpleVertex v3 = *patch.points[point_index+5];

				// Generate UV. TODO: Do this even if UV specified in control points?
				if ((origVertType & GE_VTYPE_TC_MASK) == 0) {
					float u = u_base + tile_u * third;
					float v = v_base + tile_v * third;
					v0.uv[0] = u;
					v0.uv[1] = v;
					v1.uv[0] = u + third;
					v1.uv[1] = v;
					v2.uv[0] = u;
					v2.uv[1] = v + third;
					v3.uv[0] = u + third;
					v3.uv[1] = v + third;
				}

				// Generate normal if lighting is enabled (otherwise there's no point).
				// This is a really poor quality algorithm, we get facet normals.
				if (gstate.isLightingEnabled()) {
					Vec3f norm = Cross(v1.pos - v0.pos, v2.pos - v0.pos);
					norm.Normalize();
					if (gstate.patchfacing & 1)
						norm *= -1.0f;
					v0.nrm = norm;
					v1.nrm = norm;
					v2.nrm = norm;
					v3.nrm = norm;
				}

				CopyQuad(dest, &v0, &v1, &v2, &v3);
				count += 6;
			}
		}
	} else {
		// Full correct tesselation of bezier patches.
		// Note: Does not handle splines correctly.

		int tess_u = gstate.getPatchDivisionU();
		int tess_v = gstate.getPatchDivisionV();

		// First compute all the vertices and put them in an array
		SimpleVertex *vertices = new SimpleVertex[(tess_u + 1) * (tess_v + 1)];

		Vec3f *horiz = new Vec3f[(tess_u + 1) * 4];
		Vec3f *horiz2 = horiz + (tess_u + 1) * 1;
		Vec3f *horiz3 = horiz + (tess_u + 1) * 2;
		Vec3f *horiz4 = horiz + (tess_u + 1) * 3;

		// Precompute the horizontal curves to we only have to evaluate the vertical ones.
		for (int i = 0; i < tess_u + 1; i++) {
			float u = ((float)i / (float)tess_u);
			horiz[i] = Bernstein3D(patch.points[0]->pos, patch.points[1]->pos, patch.points[2]->pos, patch.points[3]->pos, u);
			horiz2[i] = Bernstein3D(patch.points[4]->pos, patch.points[5]->pos, patch.points[6]->pos, patch.points[7]->pos, u);
			horiz3[i] = Bernstein3D(patch.points[8]->pos, patch.points[9]->pos, patch.points[10]->pos, patch.points[11]->pos, u);
			horiz4[i] = Bernstein3D(patch.points[12]->pos, patch.points[13]->pos, patch.points[14]->pos, patch.points[15]->pos, u);
		}

		bool computeNormals = gstate.isLightingEnabled();

		for (int tile_v = 0; tile_v < tess_v + 1; ++tile_v) {
			for (int tile_u = 0; tile_u < tess_u + 1; ++tile_u) {
				float u = ((float)tile_u / (float)tess_u);
				float v = ((float)tile_v / (float)tess_v);
				float bu = u;
				float bv = v;

				// TODO: Should be able to precompute the four curves per U, then just Bernstein per V. Will benefit large tesselation factors.
				const Vec3f &pos1 = horiz[tile_u];
				const Vec3f &pos2 = horiz2[tile_u];
				const Vec3f &pos3 = horiz3[tile_u];
				const Vec3f &pos4 = horiz4[tile_u];

				SimpleVertex &vert = vertices[tile_v * (tess_u + 1) + tile_u];

				if (computeNormals) {
					Vec3f derivU1 = Bernstein3DDerivative(patch.points[0]->pos, patch.points[1]->pos, patch.points[2]->pos, patch.points[3]->pos, bu);
					Vec3f derivU2 = Bernstein3DDerivative(patch.points[4]->pos, patch.points[5]->pos, patch.points[6]->pos, patch.points[7]->pos, bu);
					Vec3f derivU3 = Bernstein3DDerivative(patch.points[8]->pos, patch.points[9]->pos, patch.points[10]->pos, patch.points[11]->pos, bu);
					Vec3f derivU4 = Bernstein3DDerivative(patch.points[12]->pos, patch.points[13]->pos, patch.points[14]->pos, patch.points[15]->pos, bu);
					Vec3f derivU = Bernstein3D(derivU1, derivU2, derivU3, derivU4, bv);
					Vec3f derivV = Bernstein3DDerivative(pos1, pos2, pos3, pos4, bv);

					// TODO: Interpolate normals instead of generating them, if available?
					vert.nrm = Cross(derivU, derivV).Normalized();
					if (gstate.patchfacing & 1)
						vert.nrm *= -1.0f;
				} else {
					vert.nrm.SetZero();
				}

				vert.pos = Bernstein3D(pos1, pos2, pos3, pos4, bv);

				if ((origVertType & GE_VTYPE_TC_MASK) == 0) {
					// Generate texcoord
					vert.uv[0] = u + patch.u_index * third;
					vert.uv[1] = v + patch.v_index * third;
				} else {
					// Sample UV from control points
					patch.sampleTexUV(u, v, vert.uv[0], vert.uv[1]);
				}

				if (origVertType & GE_VTYPE_COL_MASK) {
					patch.sampleColor(u, v, vert.color);
				} else {
					memcpy(vert.color, patch.points[0]->color, 4);
				}
			}
		}
		delete [] horiz;

		// Tesselate. TODO: Use indices so we only need to emit 4 vertices per pair of triangles instead of six.
		for (int tile_v = 0; tile_v < tess_v; ++tile_v) {
			for (int tile_u = 0; tile_u < tess_u; ++tile_u) {
				float u = ((float)tile_u / (float)tess_u);
				float v = ((float)tile_v / (float)tess_v);

				const SimpleVertex *v0 = &vertices[tile_v * (tess_u + 1) + tile_u];
				const SimpleVertex *v1 = &vertices[tile_v * (tess_u + 1) + tile_u + 1];
				const SimpleVertex *v2 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u];
				const SimpleVertex *v3 = &vertices[(tile_v + 1) * (tess_u + 1) + tile_u + 1];

				CopyQuad(dest, v0, v1, v2, v3);
				count += 6;
			}
		}

		delete [] vertices;
	}
}
コード例 #5
0
ファイル: Polygon.cpp プロジェクト: juj/MathGeoLib
vec Polygon::BasisV() const
{
	if (p.size() < 2)
		return vec::unitY;
	return Cross(PlaneCCW().normal, BasisU()).Normalized();
}
コード例 #6
0
ファイル: Manifold.cpp プロジェクト: Paradxil/ImpulseEngine
void Manifold::ApplyImpulse( void )
{
  // Early out and positional correct if both objects have infinite mass
  if(Equal( A->im + B->im, 0 ))
  {
    InfiniteMassCorrection( );
    return;
  }

  for(uint32 i = 0; i < contact_count; ++i)
  {
    // Calculate radii from COM to contact
    Vec2 ra = contacts[i] - A->position;
    Vec2 rb = contacts[i] - B->position;

    // Relative velocity
    Vec2 rv = B->velocity + Cross( B->angularVelocity, rb ) -
              A->velocity - Cross( A->angularVelocity, ra );

    // Relative velocity along the normal
    real contactVel = Dot( rv, normal );

    // Do not resolve if velocities are separating
    if(contactVel > 0)
      return;

    real raCrossN = Cross( ra, normal );
    real rbCrossN = Cross( rb, normal );
    real invMassSum = A->im + B->im + Sqr( raCrossN ) * A->iI + Sqr( rbCrossN ) * B->iI;

    // Calculate impulse scalar
    real j = -(1.0f + e) * contactVel;
    j /= invMassSum;
    j /= (real)contact_count;

    // Apply impulse
    Vec2 impulse = normal * j;
    A->ApplyImpulse( -impulse, ra );
    B->ApplyImpulse(  impulse, rb );

    // Friction impulse
    rv = B->velocity + Cross( B->angularVelocity, rb ) -
         A->velocity - Cross( A->angularVelocity, ra );

    Vec2 t = rv - (normal * Dot( rv, normal ));
    t.Normalize( );

    // j tangent magnitude
    real jt = -Dot( rv, t );
    jt /= invMassSum;
    jt /= (real)contact_count;

    // Don't apply tiny friction impulses
    if(Equal( jt, 0.0f ))
      return;

    // Coulumb's law
    Vec2 tangentImpulse;
    if(std::abs( jt ) < j * sf)
      tangentImpulse = t * jt;
    else
      tangentImpulse = t * -j * df;

    // Apply friction impulse
    A->ApplyImpulse( -tangentImpulse, ra );
    B->ApplyImpulse(  tangentImpulse, rb );
  }
}
コード例 #7
0
ファイル: naiadmesh.cpp プロジェクト: karlssonper/cs348b
void NaiadTriangle::GetShadingGeometry(const Transform &obj2world,
        const DifferentialGeometry &dg,
        DifferentialGeometry *dgShading) const {
    if (!mesh->n && !mesh->s) {
        *dgShading = dg;
        return;
    }
    // Initialize _NaiadTriangle_ shading geometry with _n_ and _s_

    // Compute barycentric coordinates for point
    float b[3];

    // Initialize _A_ and _C_ matrices for barycentrics
    float uv[3][2];
    GetUVs(uv);
    float A[2][2] =
        { { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] },
          { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] } };
    float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] };
    if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) {
        // Handle degenerate parametric mapping
        b[0] = b[1] = b[2] = 1.f/3.f;
    }
    else
        b[0] = 1.f - b[1] - b[2];

    // Use _n_ and _s_ to compute shading tangents for NaiadTriangle, _ss_ and _ts_
    Normal ns;
    Vector ss, ts;
    if (mesh->n) ns = 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) ss = Normalize(obj2world(b[0] * mesh->s[v[0]] +
                                          b[1] * mesh->s[v[1]] +
                                          b[2] * mesh->s[v[2]]));
    else   ss = Normalize(dg.dpdu);
    
    ts = Cross(ss, ns);
    if (ts.LengthSquared() > 0.f) {
        ts = Normalize(ts);
        ss = Cross(ts, ns);
    }
    else
        CoordinateSystem((Vector)ns, &ss, &ts);
    Normal dndu, dndv;

    // Compute $\dndu$ and $\dndv$ for NaiadTriangle shading geometry
    if (mesh->n) {
        float uvs[3][2];
        GetUVs(uvs);
        // Compute deltas for NaiadTriangle partial derivatives of normal
        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.f)
            dndu = dndv = Normal(0,0,0);
        else {
            float invdet = 1.f / determinant;
            dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
            dndv = (-du2 * dn1 + du1 * dn2) * invdet;
        }
    }
    else
        dndu = dndv = Normal(0,0,0);
    *dgShading = DifferentialGeometry(dg.p, ss, ts,
        (*ObjectToWorld)(dndu), (*ObjectToWorld)(dndv),
        dg.u, dg.v, dg.shape);
    dgShading->dudx = dg.dudx;  dgShading->dvdx = dg.dvdx;
    dgShading->dudy = dg.dudy;  dgShading->dvdy = dg.dvdy;
    dgShading->dpdx = dg.dpdx;  dgShading->dpdy = dg.dpdy;
}
コード例 #8
0
ファイル: triangle.cpp プロジェクト: Graphics3D/pbrt-v3
bool Triangle::Intersect(const Ray &ray, Float *tHit, SurfaceInteraction *isect,
                         bool testAlphaTexture) const {
    ProfilePhase p(Prof::TriIntersect);
    ++nTests;
    // Get triangle vertices in _p0_, _p1_, and _p2_
    const Point3f &p0 = mesh->p[v[0]];
    const Point3f &p1 = mesh->p[v[1]];
    const Point3f &p2 = mesh->p[v[2]];

    // Perform ray--triangle intersection test

    // Transform triangle vertices to ray coordinate space

    // Translate vertices based on ray origin
    Point3f p0t = p0 - Vector3f(ray.o);
    Point3f p1t = p1 - Vector3f(ray.o);
    Point3f p2t = p2 - Vector3f(ray.o);

    // Permute components of triangle vertices and ray direction
    int kz = MaxDimension(Abs(ray.d));
    int kx = kz + 1;
    if (kx == 3) kx = 0;
    int ky = kx + 1;
    if (ky == 3) ky = 0;
    Vector3f d = Permute(ray.d, kx, ky, kz);
    p0t = Permute(p0t, kx, ky, kz);
    p1t = Permute(p1t, kx, ky, kz);
    p2t = Permute(p2t, kx, ky, kz);

    // Apply shear transformation to translated vertex positions
    Float Sx = -d.x / d.z;
    Float Sy = -d.y / d.z;
    Float Sz = 1.f / d.z;
    p0t.x += Sx * p0t.z;
    p0t.y += Sy * p0t.z;
    p1t.x += Sx * p1t.z;
    p1t.y += Sy * p1t.z;
    p2t.x += Sx * p2t.z;
    p2t.y += Sy * p2t.z;

    // Compute edge function coefficients _e0_, _e1_, and _e2_
    Float e0 = p1t.x * p2t.y - p1t.y * p2t.x;
    Float e1 = p2t.x * p0t.y - p2t.y * p0t.x;
    Float e2 = p0t.x * p1t.y - p0t.y * p1t.x;

    // Fall back to double precision test at triangle edges
    if (sizeof(Float) == sizeof(float) &&
        (e0 == 0.0f || e1 == 0.0f || e2 == 0.0f)) {
        double p2txp1ty = (double)p2t.x * (double)p1t.y;
        double p2typ1tx = (double)p2t.y * (double)p1t.x;
        e0 = (float)(p2typ1tx - p2txp1ty);
        double p0txp2ty = (double)p0t.x * (double)p2t.y;
        double p0typ2tx = (double)p0t.y * (double)p2t.x;
        e1 = (float)(p0typ2tx - p0txp2ty);
        double p1txp0ty = (double)p1t.x * (double)p0t.y;
        double p1typ0tx = (double)p1t.y * (double)p0t.x;
        e2 = (float)(p1typ0tx - p1txp0ty);
    }

    // Perform triangle edge and determinant tests
    if ((e0 < 0 || e1 < 0 || e2 < 0) && (e0 > 0 || e1 > 0 || e2 > 0))
        return false;
    Float det = e0 + e1 + e2;
    if (det == 0) return false;

    // Compute scaled hit distance to triangle and test against ray $t$ range
    p0t.z *= Sz;
    p1t.z *= Sz;
    p2t.z *= Sz;
    Float tScaled = e0 * p0t.z + e1 * p1t.z + e2 * p2t.z;
    if (det < 0 && (tScaled >= 0 || tScaled < ray.tMax * det))
        return false;
    else if (det > 0 && (tScaled <= 0 || tScaled > ray.tMax * det))
        return false;

    // Compute barycentric coordinates and $t$ value for triangle intersection
    Float invDet = 1 / det;
    Float b0 = e0 * invDet;
    Float b1 = e1 * invDet;
    Float b2 = e2 * invDet;
    Float t = tScaled * invDet;

    // Ensure that computed triangle $t$ is conservatively greater than zero

    // Compute $\delta_z$ term for triangle $t$ error bounds
    Float maxZt = MaxComponent(Abs(Vector3f(p0t.z, p1t.z, p2t.z)));
    Float deltaZ = gamma(3) * maxZt;

    // Compute $\delta_x$ and $\delta_y$ terms for triangle $t$ error bounds
    Float maxXt = MaxComponent(Abs(Vector3f(p0t.x, p1t.x, p2t.x)));
    Float maxYt = MaxComponent(Abs(Vector3f(p0t.y, p1t.y, p2t.y)));
    Float deltaX = gamma(5) * (maxXt + maxZt);
    Float deltaY = gamma(5) * (maxYt + maxZt);

    // Compute $\delta_e$ term for triangle $t$ error bounds
    Float deltaE =
        2 * (gamma(2) * maxXt * maxYt + deltaY * maxXt + deltaX * maxYt);

    // Compute $\delta_t$ term for triangle $t$ error bounds and check _t_
    Float maxE = MaxComponent(Abs(Vector3f(e0, e1, e2)));
    Float deltaT = 3 *
                   (gamma(3) * maxE * maxZt + deltaE * maxZt + deltaZ * maxE) *
                   std::abs(invDet);
    if (t <= deltaT) return false;

    // Compute triangle partial derivatives
    Vector3f dpdu, dpdv;
    Point2f uv[3];
    GetUVs(uv);

    // Compute deltas for triangle partial derivatives
    Vector2f duv02 = uv[0] - uv[2], duv12 = uv[1] - uv[2];
    Vector3f dp02 = p0 - p2, dp12 = p1 - p2;
    Float determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];
    if (determinant == 0) {
        // Handle zero determinant for triangle partial derivative matrix
        CoordinateSystem(Normalize(Cross(p2 - p0, p1 - p0)), &dpdu, &dpdv);
    } else {
        Float invdet = 1 / determinant;
        dpdu = (duv12[1] * dp02 - duv02[1] * dp12) * invdet;
        dpdv = (-duv12[0] * dp02 + duv02[0] * dp12) * invdet;
    }

    // Compute error bounds for triangle intersection
    Float xAbsSum =
        (std::abs(b0 * p0.x) + std::abs(b1 * p1.x) + std::abs(b2 * p2.x));
    Float yAbsSum =
        (std::abs(b0 * p0.y) + std::abs(b1 * p1.y) + std::abs(b2 * p2.y));
    Float zAbsSum =
        (std::abs(b0 * p0.z) + std::abs(b1 * p1.z) + std::abs(b2 * p2.z));
    Vector3f pError = gamma(7) * Vector3f(xAbsSum, yAbsSum, zAbsSum);

    // Interpolate $(u,v)$ parametric coordinates and hit point
    Point3f pHit = b0 * p0 + b1 * p1 + b2 * p2;
    Point2f uvHit = b0 * uv[0] + b1 * uv[1] + b2 * uv[2];

    // Test intersection against alpha texture, if present
    if (testAlphaTexture && mesh->alphaMask) {
        SurfaceInteraction isectLocal(pHit, Vector3f(0, 0, 0), uvHit, -ray.d,
                                      dpdu, dpdv, Normal3f(0, 0, 0),
                                      Normal3f(0, 0, 0), ray.time, this);
        if (mesh->alphaMask->Evaluate(isectLocal) == 0) return false;
    }

    // Fill in _SurfaceInteraction_ from triangle hit
    *isect = SurfaceInteraction(pHit, pError, uvHit, -ray.d, dpdu, dpdv,
                                Normal3f(0, 0, 0), Normal3f(0, 0, 0), ray.time,
                                this);

    // Override surface normal in _isect_ for triangle
    isect->n = isect->shading.n = Normal3f(Normalize(Cross(dp02, dp12)));
    if (mesh->n || mesh->s) {
        // Initialize _Triangle_ shading geometry

        // Compute shading normal _ns_ for triangle
        Normal3f ns;
        if (mesh->n) {
            ns = (b0 * mesh->n[v[0]] + b1 * mesh->n[v[1]] +
                  b2 * mesh->n[v[2]]);
            if (ns.LengthSquared() > 0)
                ns = Normalize(ns);
            else
                ns = isect->n;
        } else
            ns = isect->n;

        // Compute shading tangent _ss_ for triangle
        Vector3f ss;
        if (mesh->s) {
            ss = (b0 * mesh->s[v[0]] + b1 * mesh->s[v[1]] +
                  b2 * mesh->s[v[2]]);
            if (ss.LengthSquared() > 0)
                ss = Normalize(ss);
            else
                ss = Normalize(isect->dpdu);
        }
        else
            ss = Normalize(isect->dpdu);

        // Compute shading bitangent _ts_ for triangle and adjust _ss_
        Vector3f ts = Cross(ss, ns);
        if (ts.LengthSquared() > 0.f) {
            ts = Normalize(ts);
            ss = Cross(ts, ns);
        } else
            CoordinateSystem((Vector3f)ns, &ss, &ts);

        // Compute $\dndu$ and $\dndv$ for triangle shading geometry
        Normal3f dndu, dndv;
        if (mesh->n) {
            // Compute deltas for triangle partial derivatives of normal
            Vector2f duv02 = uv[0] - uv[2];
            Vector2f duv12 = uv[1] - uv[2];
            Normal3f dn1 = mesh->n[v[0]] - mesh->n[v[2]];
            Normal3f dn2 = mesh->n[v[1]] - mesh->n[v[2]];
            Float determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];
            if (determinant == 0)
                dndu = dndv = Normal3f(0, 0, 0);
            else {
                Float invDet = 1 / determinant;
                dndu = (duv12[1] * dn1 - duv02[1] * dn2) * invDet;
                dndv = (-duv12[0] * dn1 + duv02[0] * dn2) * invDet;
            }
        } else
            dndu = dndv = Normal3f(0, 0, 0);
        isect->SetShadingGeometry(ss, ts, dndu, dndv, true);
    }

    // Ensure correct orientation of the geometric normal
    if (mesh->n)
        isect->n = Faceforward(isect->n, isect->shading.n);
    else if (reverseOrientation ^ transformSwapsHandedness)
        isect->n = isect->shading.n = -isect->n;
    *tHit = t;
    ++nHits;
    return true;
}
コード例 #9
0
ファイル: triangle.cpp プロジェクト: Graphics3D/pbrt-v3
bool Triangle::IntersectP(const Ray &ray, bool testAlphaTexture) const {
    ProfilePhase p(Prof::TriIntersectP);
    ++nTests;
    // Get triangle vertices in _p0_, _p1_, and _p2_
    const Point3f &p0 = mesh->p[v[0]];
    const Point3f &p1 = mesh->p[v[1]];
    const Point3f &p2 = mesh->p[v[2]];

    // Perform ray--triangle intersection test

    // Transform triangle vertices to ray coordinate space

    // Translate vertices based on ray origin
    Point3f p0t = p0 - Vector3f(ray.o);
    Point3f p1t = p1 - Vector3f(ray.o);
    Point3f p2t = p2 - Vector3f(ray.o);

    // Permute components of triangle vertices and ray direction
    int kz = MaxDimension(Abs(ray.d));
    int kx = kz + 1;
    if (kx == 3) kx = 0;
    int ky = kx + 1;
    if (ky == 3) ky = 0;
    Vector3f d = Permute(ray.d, kx, ky, kz);
    p0t = Permute(p0t, kx, ky, kz);
    p1t = Permute(p1t, kx, ky, kz);
    p2t = Permute(p2t, kx, ky, kz);

    // Apply shear transformation to translated vertex positions
    Float Sx = -d.x / d.z;
    Float Sy = -d.y / d.z;
    Float Sz = 1.f / d.z;
    p0t.x += Sx * p0t.z;
    p0t.y += Sy * p0t.z;
    p1t.x += Sx * p1t.z;
    p1t.y += Sy * p1t.z;
    p2t.x += Sx * p2t.z;
    p2t.y += Sy * p2t.z;

    // Compute edge function coefficients _e0_, _e1_, and _e2_
    Float e0 = p1t.x * p2t.y - p1t.y * p2t.x;
    Float e1 = p2t.x * p0t.y - p2t.y * p0t.x;
    Float e2 = p0t.x * p1t.y - p0t.y * p1t.x;

    // Fall back to double precision test at triangle edges
    if (sizeof(Float) == sizeof(float) &&
        (e0 == 0.0f || e1 == 0.0f || e2 == 0.0f)) {
        double p2txp1ty = (double)p2t.x * (double)p1t.y;
        double p2typ1tx = (double)p2t.y * (double)p1t.x;
        e0 = (float)(p2typ1tx - p2txp1ty);
        double p0txp2ty = (double)p0t.x * (double)p2t.y;
        double p0typ2tx = (double)p0t.y * (double)p2t.x;
        e1 = (float)(p0typ2tx - p0txp2ty);
        double p1txp0ty = (double)p1t.x * (double)p0t.y;
        double p1typ0tx = (double)p1t.y * (double)p0t.x;
        e2 = (float)(p1typ0tx - p1txp0ty);
    }

    // Perform triangle edge and determinant tests
    if ((e0 < 0 || e1 < 0 || e2 < 0) && (e0 > 0 || e1 > 0 || e2 > 0))
        return false;
    Float det = e0 + e1 + e2;
    if (det == 0) return false;

    // Compute scaled hit distance to triangle and test against ray $t$ range
    p0t.z *= Sz;
    p1t.z *= Sz;
    p2t.z *= Sz;
    Float tScaled = e0 * p0t.z + e1 * p1t.z + e2 * p2t.z;
    if (det < 0 && (tScaled >= 0 || tScaled < ray.tMax * det))
        return false;
    else if (det > 0 && (tScaled <= 0 || tScaled > ray.tMax * det))
        return false;

    // Compute barycentric coordinates and $t$ value for triangle intersection
    Float invDet = 1 / det;
    Float b0 = e0 * invDet;
    Float b1 = e1 * invDet;
    Float b2 = e2 * invDet;
    Float t = tScaled * invDet;

    // Ensure that computed triangle $t$ is conservatively greater than zero

    // Compute $\delta_z$ term for triangle $t$ error bounds
    Float maxZt = MaxComponent(Abs(Vector3f(p0t.z, p1t.z, p2t.z)));
    Float deltaZ = gamma(3) * maxZt;

    // Compute $\delta_x$ and $\delta_y$ terms for triangle $t$ error bounds
    Float maxXt = MaxComponent(Abs(Vector3f(p0t.x, p1t.x, p2t.x)));
    Float maxYt = MaxComponent(Abs(Vector3f(p0t.y, p1t.y, p2t.y)));
    Float deltaX = gamma(5) * (maxXt + maxZt);
    Float deltaY = gamma(5) * (maxYt + maxZt);

    // Compute $\delta_e$ term for triangle $t$ error bounds
    Float deltaE =
        2 * (gamma(2) * maxXt * maxYt + deltaY * maxXt + deltaX * maxYt);

    // Compute $\delta_t$ term for triangle $t$ error bounds and check _t_
    Float maxE = MaxComponent(Abs(Vector3f(e0, e1, e2)));
    Float deltaT = 3 *
                   (gamma(3) * maxE * maxZt + deltaE * maxZt + deltaZ * maxE) *
                   std::abs(invDet);
    if (t <= deltaT) return false;

    // Test shadow ray intersection against alpha texture, if present
    if (testAlphaTexture && (mesh->alphaMask || mesh->shadowAlphaMask)) {
        // Compute triangle partial derivatives
        Vector3f dpdu, dpdv;
        Point2f uv[3];
        GetUVs(uv);

        // Compute deltas for triangle partial derivatives
        Vector2f duv02 = uv[0] - uv[2], duv12 = uv[1] - uv[2];
        Vector3f dp02 = p0 - p2, dp12 = p1 - p2;
        Float determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];
        if (determinant == 0) {
            // Handle zero determinant for triangle partial derivative matrix
            CoordinateSystem(Normalize(Cross(p2 - p0, p1 - p0)), &dpdu, &dpdv);
        } else {
            Float invdet = 1 / determinant;
            dpdu = (duv12[1] * dp02 - duv02[1] * dp12) * invdet;
            dpdv = (-duv12[0] * dp02 + duv02[0] * dp12) * invdet;
        }

        // Interpolate $(u,v)$ parametric coordinates and hit point
        Point3f pHit = b0 * p0 + b1 * p1 + b2 * p2;
        Point2f uvHit = b0 * uv[0] + b1 * uv[1] + b2 * uv[2];
        SurfaceInteraction isectLocal(pHit, Vector3f(0, 0, 0), uvHit, -ray.d,
                                      dpdu, dpdv, Normal3f(0, 0, 0),
                                      Normal3f(0, 0, 0), ray.time, this);
        if (mesh->alphaMask && mesh->alphaMask->Evaluate(isectLocal) == 0)
            return false;
        if (mesh->shadowAlphaMask &&
            mesh->shadowAlphaMask->Evaluate(isectLocal) == 0)
            return false;
    }
    ++nHits;
    return true;
}
コード例 #10
0
void FVoronoiDiagramSite::GenerateCentroid(FIntRect Bounds)
{
    TArray<FVector2D> SortedVertices;

    // Gather all vertices from the edges
    // Solve for corners
    
	bool bHas_X_Min = false;
    bool bHas_X_Max = false;
    bool bHas_Min_Y = false;
    bool bHas_Max_Y = false;
	for(auto Itr(Edges.CreateConstIterator()); Itr; ++Itr)
    {
		TSharedPtr<FVoronoiDiagramEdge, ESPMode::ThreadSafe> CurrentEdge = (*Itr);

        // Don't add edge that is (0,0) -> (0,0).  Increment Index if no edge is removed, otherwise the remove should do this shifting for us
        if(
            FMath::IsNearlyEqual(CurrentEdge->LeftClippedEndPoint.X, FLT_MIN) && FMath::IsNearlyEqual(CurrentEdge->LeftClippedEndPoint.Y, FLT_MIN)  &&
            FMath::IsNearlyEqual(CurrentEdge->RightClippedEndPoint.X, FLT_MIN) && FMath::IsNearlyEqual(CurrentEdge->RightClippedEndPoint.Y, FLT_MIN)
        )
        {
            continue;
        }
        
        FVector2D LeftEndPoint = CurrentEdge->LeftClippedEndPoint;
        FVector2D RightEndPoint = CurrentEdge->RightClippedEndPoint;

        // (x, Min)
        if(FMath::IsNearlyZero(LeftEndPoint.Y, NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyZero(RightEndPoint.Y, NOT_REALLY_KINDA_SMALL_NUMBER))
        {
            bHas_X_Min = true;
        }

        // (x, Max)
        if(FMath::IsNearlyEqual(LeftEndPoint.Y, Bounds.Height(), NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyEqual(RightEndPoint.Y, Bounds.Height(), NOT_REALLY_KINDA_SMALL_NUMBER))
        {
            bHas_X_Max = true;
        }
        
        // (Min, y)
        if(FMath::IsNearlyZero(LeftEndPoint.X, NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyZero(RightEndPoint.X, NOT_REALLY_KINDA_SMALL_NUMBER))
        {
            bHas_Min_Y = true;
        }

        // (Max, y)
        if(FMath::IsNearlyEqual(LeftEndPoint.X, Bounds.Width(), NOT_REALLY_KINDA_SMALL_NUMBER) || FMath::IsNearlyEqual(RightEndPoint.X, Bounds.Width(), NOT_REALLY_KINDA_SMALL_NUMBER))
        {
            bHas_Max_Y = true;
        }
        
        SortedVertices.Add(LeftEndPoint);
        SortedVertices.Add(RightEndPoint);
    }
    
    // Add corners if applicable
    // (x, Min) -> (Min, y)
    // Min, Min Corner
    if(bHas_X_Min && bHas_Min_Y)
    {
        SortedVertices.Add(FVector2D(0.0f, 0.0f));
        bIsCorner = true;
    }
    
    // x, Min -> Max, y
    // Min, Max Corner
    if(bHas_X_Min && bHas_Max_Y)
    {
        SortedVertices.Add(FVector2D(Bounds.Width(), 0.0f));
        bIsCorner = true;
    }
    
    // x, Max -> Min, y
    // Max, Min Corner
    if(bHas_X_Max && bHas_Min_Y)
    {
        SortedVertices.Add(FVector2D(0.0f, static_cast<float>(Bounds.Height())));
        bIsCorner = true;
    }
    
    // x, Max -> Max, y
    // Max, Max Corner
    if(bHas_X_Max && bHas_Max_Y)
    {
        SortedVertices.Add(FVector2D(static_cast<float>(Bounds.Width()), static_cast<float>(Bounds.Height())));
        bIsCorner = true;
    }
    
    if(bHas_X_Min || bHas_X_Max || bHas_Min_Y || bHas_Max_Y)
    {
        bIsEdge = true;
    }

    // Monotone Chain
    // Sort the vertices lexigraphically by X and then Y
    struct FSortVertex
    {
        bool operator()(const FVector2D& A, const FVector2D& B) const
        {
            if(A.X < B.X)
            {
                return true;
            }
            
            if(A.X > B.X)
            {
                return false;
            }
            
            if(A.Y < B.Y)
            {
                return true;
            }
            
            if(A.Y > B.Y)
            {
                return false;
            }
            return false;
        }
    };
    SortedVertices.Sort(FSortVertex());
    
    TArray<FVector2D> LowerHull;
    for(int32 i = 0; i < SortedVertices.Num(); ++i)
    {
        while(LowerHull.Num() >= 2 && (Cross( LowerHull[ LowerHull.Num() - 2 ], LowerHull[ LowerHull.Num() - 1 ], SortedVertices[i]) < 0.0f || FMath::IsNearlyZero(Cross( LowerHull[ LowerHull.Num() - 2 ], LowerHull[ LowerHull.Num() - 1 ], SortedVertices[i]))))
        {
            LowerHull.RemoveAt(LowerHull.Num() - 1);
        }
        LowerHull.Add(SortedVertices[i]);
    }
    
    TArray<FVector2D> UpperHull;
    for(int32 i = SortedVertices.Num() - 1; i >= 0; --i)
    {
        while(UpperHull.Num() >= 2 && (Cross( UpperHull[ UpperHull.Num() - 2 ], UpperHull[ UpperHull.Num() - 1 ], SortedVertices[i]) < 0.0f || FMath::IsNearlyZero(Cross( UpperHull[ UpperHull.Num() - 2 ], UpperHull[ UpperHull.Num() - 1 ], SortedVertices[i]))))
        {
            UpperHull.RemoveAt(UpperHull.Num() - 1);
        }
        UpperHull.Add(SortedVertices[i]);
    }
    
    // Remove last point because they are represented in the other list
    UpperHull.RemoveAt(UpperHull.Num() - 1);
    LowerHull.RemoveAt(LowerHull.Num() - 1);
    
    SortedVertices.Empty();
    SortedVertices.Append(LowerHull);
    SortedVertices.Append(UpperHull);



    // Calculate Centroid
    Centroid = FVector2D::ZeroVector;
    Vertices.Empty();
    Vertices.Append(SortedVertices);

    FVector2D CurrentVertex;
    FVector2D NextVertex;
    float SignedArea = 0.0f;
    float PartialArea;
    
    // Use all vertices except the last one
    for(int32 Index = 0; Index < SortedVertices.Num() - 1; ++Index)
    {
        CurrentVertex = FVector2D(SortedVertices[Index]);
        NextVertex = FVector2D(SortedVertices[Index + 1]);

        PartialArea = CurrentVertex.X * NextVertex.Y - NextVertex.X * CurrentVertex.Y;
        SignedArea += PartialArea;

        Centroid = FVector2D(Centroid.X + (CurrentVertex.X + NextVertex.X) * PartialArea, Centroid.Y + (CurrentVertex.Y + NextVertex.Y) * PartialArea);
    }

    // Process last vertex
    CurrentVertex = SortedVertices[SortedVertices.Num() - 1];
    NextVertex = SortedVertices[0];
    PartialArea = (CurrentVertex.X * NextVertex.Y - NextVertex.X * CurrentVertex.Y);
    SignedArea += PartialArea;
    Centroid = FVector2D(Centroid.X + (CurrentVertex.X + NextVertex.X) * PartialArea, Centroid.Y + (CurrentVertex.Y + NextVertex.Y) * PartialArea);
    
    SignedArea *= 0.5f;
    Centroid = FVector2D( Centroid.X / (6.0f * SignedArea), Centroid.Y / (6.0f * SignedArea) );
  
//    UE_LOG(LogVoronoiDiagram, Log, TEXT("Centroid (%f, %f)"), Centroid.X, Centroid.Y);
//    if(Centroid.X == NAN || Centroid.Y == NAN)
//    {
//        UE_LOG(LogVoronoiDiagram, Log, TEXT("Centroid (%f, %f)"), Centroid.X, Centroid.Y);
//        for(auto Itr(SortedVertices.CreateConstIterator()); Itr; ++Itr)
//        {
//            UE_LOG(LogVoronoiDiagram, Log, TEXT("Vertex (%f, %f)"), (*Itr).X, (*Itr).Y);
//        }
//    }
}
コード例 #11
0
ファイル: nurbs.cpp プロジェクト: acpa2691/cs348b
void NURBS::Refine(vector<Reference<Shape> > &refined) const {
	// Compute NURBS dicing rates
	int diceu = 30, dicev = 30;
	float *ueval = new float[diceu];
	float *veval = new float[dicev];
	Point *evalPs = new Point[diceu*dicev];
	Normal *evalNs = new Normal[diceu*dicev];
	int i;
	for (i = 0; i < diceu; ++i)
		ueval[i] = Lerp((float)i / (float)(diceu-1), umin, umax);
	for (i = 0; i < dicev; ++i)
		veval[i] = Lerp((float)i / (float)(dicev-1), vmin, vmax);
	// Evaluate NURBS over grid of points
	memset(evalPs, 0, diceu*dicev*sizeof(Point));
	memset(evalNs, 0, diceu*dicev*sizeof(Point));
	float *uvs = new float[2*diceu*dicev];
	// Turn NURBS into triangles
	Homogeneous3 *Pw = (Homogeneous3 *)P;
	if (!isHomogeneous) {
		Pw = (Homogeneous3 *)alloca(nu*nv*sizeof(Homogeneous3));
		for (int i = 0; i < nu*nv; ++i) {
			Pw[i].x = P[3*i];
			Pw[i].y = P[3*i+1];
			Pw[i].z = P[3*i+2];
			Pw[i].w = 1.;
		}
	}
	for (int v = 0; v < dicev; ++v) {
		for (int u = 0; u < diceu; ++u) {
			uvs[2*(v*diceu+u)]   = ueval[u];
			uvs[2*(v*diceu+u)+1] = veval[v];
	
			Vector dPdu, dPdv;
			Point pt = NURBSEvaluateSurface(uorder, uknot, nu, ueval[u],
				vorder, vknot, nv, veval[v], Pw, &dPdu, &dPdv);
			evalPs[v*diceu + u].x = pt.x;
			evalPs[v*diceu + u].y = pt.y;
			evalPs[v*diceu + u].z = pt.z;
			evalNs[v*diceu + u] = Normal(Normalize(Cross(dPdu, dPdv)));
		}
	}
	// Generate points-polygons mesh
	int nTris = 2*(diceu-1)*(dicev-1);
	int *vertices = new int[3 * nTris];
	int *vertp = vertices;
	// Compute the vertex offset numbers for the triangles
	for (int v = 0; v < dicev-1; ++v) {
		for (int u = 0; u < diceu-1; ++u) {
	#define VN(u,v) ((v)*diceu+(u))
			*vertp++ = VN(u,   v);
			*vertp++ = VN(u+1, v);
			*vertp++ = VN(u+1, v+1);
	
			*vertp++ = VN(u,   v);
			*vertp++ = VN(u+1, v+1);
			*vertp++ = VN(u,   v+1);
	#undef VN
		}
	}
	int nVerts = diceu*dicev;
	ParamSet paramSet;
	paramSet.AddInt("indices", vertices, 3*nTris);
	paramSet.AddPoint("P", evalPs, nVerts);
	paramSet.AddFloat("uv", uvs, 2 * nVerts);
	paramSet.AddNormal("N", evalNs, nVerts);
	refined.push_back(MakeShape("trianglemesh", ObjectToWorld,
			reverseOrientation, paramSet));
	// Cleanup from NURBS refinement
	delete[] uvs;
	delete[] ueval;
	delete[] veval;
	delete[] evalPs;
	delete[] evalNs;
	delete[] vertices;
}
コード例 #12
0
ファイル: main.cpp プロジェクト: naps62/papi-cuda
bool Shade(Path* path, Geometry *geometry, BVHAccel *bvh, const RayHit& rayHit) {

	uint tracedShadowRayCount;

	if (rayHit.index == 0xffffffffu) {
		return false;
	}

	// Something was hit
	unsigned int currentTriangleIndex = rayHit.index;
	RGB triInterpCol = geometry->triangles[currentTriangleIndex].InterpolateColor(
			geometry->vertColors, rayHit.b1, rayHit.b2);
	Normal shadeN = geometry->triangles[currentTriangleIndex].InterpolateNormal(
			geometry->vertNormals, rayHit.b1, rayHit.b2);

	// Calculate next step
	path->depth++;

	// Check if I have to stop
	if (path->depth >= MAX_PATH_DEPTH) {
		// Too depth, terminate the path
		return false;
	} else if (path->depth > 2) {

		// Russian Rulette, maximize cos
		const float p = min(1.f, triInterpCol.filter() * AbsDot(shadeN, path->pathRay.d));

		if (p > getFloatRNG(&path->seed))
			path->throughput /= p;
		else {
			// Terminate the path
			return false;
		}
	}

	//--------------------------------------------------------------------------
	// Build the shadow ray
	//--------------------------------------------------------------------------

	// Check if it is a light source
	float RdotShadeN = Dot(path->pathRay.d, shadeN);
	if (geometry->IsLight(currentTriangleIndex)) {
		// Check if we are on the right side of the light source
		if ((path->depth == 1) && (RdotShadeN < 0.f))
			path->radiance += triInterpCol * path->throughput;

		// Terminate the path
		return false;
	}

	if (RdotShadeN > 0.f) {
		// Flip shade  normal
		shadeN = -shadeN;
	} else
		RdotShadeN = -RdotShadeN;

	path->throughput *= RdotShadeN * triInterpCol;

	// Trace shadow rays
	const Point hitPoint = path->pathRay(rayHit.t);

	tracedShadowRayCount = 0;
	const float lightStrategyPdf = static_cast<float> (SHADOWRAY)
			/ static_cast<float> (geometry->nLights);

	float lightPdf[SHADOWRAY];
	RGB lightColor[SHADOWRAY];
	Ray shadowRay[SHADOWRAY];

	for (unsigned int i = 0; i < SHADOWRAY; ++i) {
		// Select the light to sample
		const unsigned int currentLightIndex = geometry->SampleLights(getFloatRNG(&path->seed));
		//	const TriangleLight &light = scene->lights[currentLightIndex];

		// Select a point on the surface
		lightColor[tracedShadowRayCount] = Sample_L(currentLightIndex, geometry, hitPoint, shadeN,
				getFloatRNG(&path->seed), getFloatRNG(&path->seed),
				&lightPdf[tracedShadowRayCount], &shadowRay[tracedShadowRayCount]);

		// Scale light pdf for ONE_UNIFORM strategy
		lightPdf[tracedShadowRayCount] *= lightStrategyPdf;

		// Using 0.1 instead of 0.0 to cut down fireflies
		if (lightPdf[tracedShadowRayCount] > 0.1f)
			tracedShadowRayCount++;
	}

	RayHit* rh = new RayHit[tracedShadowRayCount];

	for (unsigned int i = 0; i < tracedShadowRayCount; ++i)
		Intersect(shadowRay[i],  rh[i], bvh->bvhTree, geometry->triangles, geometry->vertices);

	if ((tracedShadowRayCount > 0)) {
		for (unsigned int i = 0; i < tracedShadowRayCount; ++i) {
			const RayHit *shadowRayHit = &rh[i];
			if (shadowRayHit->index == 0xffffffffu) {
				// Nothing was hit, light is visible
				path->radiance += path->throughput * lightColor[i] / lightPdf[i];
			}
		}
	}

	//--------------------------------------------------------------------------
	// Build the next vertex path ray
	//--------------------------------------------------------------------------

	// Calculate exit direction

	float r1 = 2.f * M_PI * getFloatRNG(&path->seed);
	float r2 = getFloatRNG(&path->seed);
	float r2s = sqrt(r2);
	const Vector w(shadeN);

	Vector u;
	if (fabsf(shadeN.x) > .1f) {
		const Vector a(0.f, 1.f, 0.f);
		u = Cross(a, w);
	} else {
		const Vector a(1.f, 0.f, 0.f);
		u = Cross(a, w);
	}
	u = Normalize(u);

	Vector v = Cross(w, u);

	Vector newDir = u * (cosf(r1) * r2s) + v * (sinf(r1) * r2s) + w * sqrtf(1.f - r2);
	newDir = Normalize(newDir);

	path->pathRay.o = hitPoint;
	path->pathRay.d = newDir;

	return true;
}
コード例 #13
0
Point GetLineIntersection(const Point& P, const Point& v, const Point& Q, const Point& w) {
  Vector u = P-Q;
  double t = Cross(w, u) / Cross(v, w);
  return P+v*t;
}
コード例 #14
0
void Extrude(const Vec3* points, int numPoints, std::vector<Vec3>& vertices, std::vector<Vec3>& normals, std::vector<int>& triangles, float radius, int resolution, int smoothing)
{
	if (numPoints < 2)
		return;

	Vec3 u, v;
	Vec3 w = SafeNormalize(Vec3(points[1])-Vec3(points[0]), Vec3(0.0f, 1.0f, 0.0f));

	BasisFromVector(w, &u, &v);

	Matrix44 frame;
	frame.SetCol(0, Vec4(u.x, u.y, u.z, 0.0f));
	frame.SetCol(1, Vec4(v.x, v.y, v.z, 0.0f));
	frame.SetCol(2, Vec4(w.x, w.y, w.z, 0.0f));
	frame.SetCol(3, Vec4(0.0f, 0.0f, 0.0f, 1.0f));	

	for (int i=0; i < numPoints -1; ++i)
	{
		Vec3 next;

		if (i < numPoints -1)			
			next = Normalize(Vec3(points[i+1])-Vec3(points[i-1]));
		else
			next = Normalize(Vec3(points[i])-Vec3(points[i-1]));

		int a = Max(i-1, 0);
		int b = i;
		int c = Min(i+1, numPoints -1);
		int d = Min(i+2, numPoints -1);

		Vec3 p1 = Vec3(points[b]);
		Vec3 p2 = Vec3(points[c]);
		Vec3 m1 = 0.5f*(Vec3(points[c]) - Vec3(points[a]));
		Vec3 m2 = 0.5f*(Vec3(points[d]) - Vec3(points[b]));		

		// ensure last segment handled correctly
		int segments = (i < numPoints-2)?smoothing:smoothing+1;

		for (int s=0; s < segments; ++s)
		{
			Vec3 pos = HermiteInterpolate(p1, p2, m1, m2, s/float(smoothing));
			Vec3 dir = Normalize(HermiteTangent(p1, p2, m1, m2, s/float(smoothing)));

			Vec3 cur = frame.GetAxis(2);
			const float angle = acosf(Dot(cur, dir));

			// if parallel then don't need to do anything
			if (fabsf(angle) > 0.001f)
				frame = RotationMatrix(angle, SafeNormalize(Cross(cur, dir)))*frame;

			int startIndex = vertices.size();

			for (int c=0; c < resolution; ++c)
			{			
				float angle = k2Pi / resolution;

				// transform position and normal to world space
				Vec4 v = frame*Vec4(cosf(angle*c), sinf(angle*c), 0.0f, 0.0f);
			
				vertices.push_back(Vec3(v)*radius + pos);
				normals.push_back(Vec3(v));
			}

			// output triangles
			if (startIndex != 0)
			{
				for (int i=0; i < resolution; ++i)
				{
					int curIndex = startIndex + i;
					int nextIndex = startIndex + (i+1)%resolution; 

					triangles.push_back(curIndex);
					triangles.push_back(curIndex-resolution);
					triangles.push_back(nextIndex-resolution);
				
					triangles.push_back(nextIndex-resolution);
					triangles.push_back(nextIndex);
					triangles.push_back(curIndex);
				}	
			}
		}
	}
}
コード例 #15
0
void
InitLists( )
{
    glutSetWindow( MainWindow );

    // Create the helicopter:

    HeliList = glGenLists( 1 );
    glNewList( HeliList, GL_COMPILE );
        if(!HELI_SOLID){
            int i;
            struct edge *ep;
            struct point *p0, *p1;

            glPushMatrix( );
            glTranslatef( 0., -1., 0. );
            glRotatef(  97.,   0., 1., 0. );
            glRotatef( -15.,   0., 0., 1. );
            glBegin( GL_LINES );
                for( i=0, ep = Heliedges; i < Helinedges; i++, ep++ )
                {
                    p0 = &Helipoints[ ep->p0 ];
                    p1 = &Helipoints[ ep->p1 ];
                    glVertex3f( p0->x, p0->y, p0->z );
                    glVertex3f( p1->x, p1->y, p1->z );
                }
            glEnd( );
            glPopMatrix( );
        }else{
            int i;
            struct point *p0, *p1, *p2;
            struct tri *tp;
            float p01[3], p02[3], n[3];

            glPushMatrix( );
            glTranslatef( 0., -1., 0. );
            glRotatef(  97.,   0., 1., 0. );
            glRotatef( -15.,   0., 0., 1. );
            glBegin( GL_TRIANGLES );
                for( i=0, tp = Helitris; i < Helintris; i++, tp++ )
                {
                    p0 = &Helipoints[ tp->p0 ];
                    p1 = &Helipoints[ tp->p1 ];
                    p2 = &Helipoints[ tp->p2 ];

                    /* fake "lighting" from above:                  */

                    p01[0] = p1->x - p0->x;
                    p01[1] = p1->y - p0->y;
                    p01[2] = p1->z - p0->z;
                    p02[0] = p2->x - p0->x;
                    p02[1] = p2->y - p0->y;
                    p02[2] = p2->z - p0->z;
                    Cross( p01, p02, n );
                    Unit( n, n );
                    n[1] = fabs( n[1] );
                    n[1] += .25;
                    if( n[1] > 1. )
                        n[1] = 1.;
                    glColor3f( 0., n[1], 0. );

                    glVertex3f( p0->x, p0->y, p0->z );
                    glVertex3f( p1->x, p1->y, p1->z );
                    glVertex3f( p2->x, p2->y, p2->z );
                }
            glEnd( );
            glPopMatrix( );
        }
    glEndList( );

    // draw the helicopter blade with radius BLADE_RADIUS and
    //      width BLADE_WIDTH centered at (0.,0.,0.) in the XY plane

    BladeList = glGenLists( 1 );
    glNewList( BladeList, GL_COMPILE );
        glPushMatrix( );
        glBegin( GL_TRIANGLES );
            glVertex2f(  BLADE_RADIUS,  BLADE_WIDTH/2. );
            glVertex2f(  0., 0. );
            glVertex2f(  BLADE_RADIUS, -BLADE_WIDTH/2. );

            glVertex2f( -BLADE_RADIUS, -BLADE_WIDTH/2. );
            glVertex2f(  0., 0. );
            glVertex2f( -BLADE_RADIUS,  BLADE_WIDTH/2. );
        glEnd( );
        glPopMatrix( );
    glEndList( );

    // Draw the world
    WorldList = glGenLists( 1 );
    glNewList( WorldList, GL_COMPILE );
        glPushMatrix( );
        glColor3f( 0.2, 0.2, 1. );
        glBegin( GL_QUADS );
            glVertex3f(WORLD_APOTHEM, WORLD_HEIGHT, WORLD_APOTHEM);
            glVertex3f(WORLD_APOTHEM, WORLD_HEIGHT, -WORLD_APOTHEM);
            glVertex3f(-WORLD_APOTHEM, WORLD_HEIGHT, -WORLD_APOTHEM);
            glVertex3f(-WORLD_APOTHEM, WORLD_HEIGHT, WORLD_APOTHEM);
        glEnd( );
        glPopMatrix( );
    glEndList( );

    // Draw the object
    ObjectList = glGenLists( 1 );
    glNewList( ObjectList, GL_COMPILE );
        int rotations = 6; 
        float length = PI*2*rotations;
        int steps = 200; 
        float start_r = 0.25, start_g = 0., start_b = 0.25;
        float end_r = 0., end_g = 1., end_b = 0.75;

        // Draw the helix
        glPushMatrix( );
        glBegin( GL_TRIANGLE_STRIP );
            // Rotate in a circle
            for(float s; s < steps; s++){
                float p = s / steps;
                float r = (start_r * (1-p)) + (end_r * p);
                float g = (start_g * (1-p)) + (end_g * p);
                float b = (start_b * (1-p)) + (end_b * p);
                glColor3f(r, g, b);

                float a = (s - steps/2) * (length / steps);
                glVertex3f(cos(a), a/10 + WORLD_HEIGHT+2, sin(a) - OBJECT_DISTANCE);
                glVertex3f(cos(a), a/10 + WORLD_HEIGHT+2+0.2, sin(a) - OBJECT_DISTANCE);
            }
        glEnd( );
        glPopMatrix( );
    glEndList( );

    // create the axes:

    AxesList = glGenLists( 1 );
    glNewList( AxesList, GL_COMPILE );
        glLineWidth( AXES_WIDTH );
            Axes( 3. );
        glLineWidth( 1. );
    glEndList( );
}
コード例 #16
0
ファイル: triangle.cpp プロジェクト: Graphics3D/pbrt-v3
std::vector<std::shared_ptr<Shape>> CreateTriangleMeshShape(
    const Transform *o2w, const Transform *w2o, bool reverseOrientation,
    const ParamSet &params,
    std::map<std::string, std::shared_ptr<Texture<Float>>> *floatTextures) {
    int nvi, npi, nuvi, nsi, nni;
    const int *vi = params.FindInt("indices", &nvi);
    const Point3f *P = params.FindPoint3f("P", &npi);
    const Point2f *uvs = params.FindPoint2f("uv", &nuvi);
    if (!uvs) uvs = params.FindPoint2f("st", &nuvi);
    std::vector<Point2f> tempUVs;
    if (!uvs) {
        const Float *fuv = params.FindFloat("uv", &nuvi);
        if (!fuv) fuv = params.FindFloat("st", &nuvi);
        if (fuv) {
            nuvi /= 2;
            tempUVs.reserve(nuvi);
            for (int i = 0; i < nuvi; ++i)
                tempUVs.push_back(Point2f(fuv[2 * i], fuv[2 * i + 1]));
            uvs = &tempUVs[0];
        }
    }
    bool discardDegenerateUVs =
        params.FindOneBool("discarddegenerateUVs", false);
    if (uvs) {
        if (nuvi < npi) {
            Error(
                "Not enough of \"uv\"s for triangle mesh.  Expencted %d, "
                "found %d.  Discarding.",
                npi, nuvi);
            uvs = nullptr;
        } else if (nuvi > npi)
            Warning(
                "More \"uv\"s provided than will be used for triangle "
                "mesh.  (%d expcted, %d found)",
                npi, nuvi);
    }
    if (!vi) {
        Error(
            "Vertex indices \"indices\" not provided with triangle mesh shape");
        return std::vector<std::shared_ptr<Shape>>();
    }
    if (!P) {
        Error("Vertex positions \"P\" not provided with triangle mesh shape");
        return std::vector<std::shared_ptr<Shape>>();
    }
    const Vector3f *S = params.FindVector3f("S", &nsi);
    if (S && nsi != npi) {
        Error("Number of \"S\"s for triangle mesh must match \"P\"s");
        S = nullptr;
    }
    const Normal3f *N = params.FindNormal3f("N", &nni);
    if (N && nni != npi) {
        Error("Number of \"N\"s for triangle mesh must match \"P\"s");
        N = nullptr;
    }
    if (discardDegenerateUVs && uvs && N) {
        // if there are normals, check for bad uv's that
        // give degenerate mappings; discard them if so
        const int *vp = vi;
        for (int i = 0; i < nvi; i += 3, vp += 3) {
            Float area =
                .5f * Cross(P[vp[0]] - P[vp[1]], P[vp[2]] - P[vp[1]]).Length();
            if (area < 1e-7) continue;  // ignore degenerate tris.
            if ((uvs[vp[0]].x == uvs[vp[1]].x &&
                 uvs[vp[0]].y == uvs[vp[1]].y) ||
                (uvs[vp[1]].x == uvs[vp[2]].x &&
                 uvs[vp[1]].y == uvs[vp[2]].y) ||
                (uvs[vp[2]].x == uvs[vp[0]].x &&
                 uvs[vp[2]].y == uvs[vp[0]].y)) {
                Warning(
                    "Degenerate uv coordinates in triangle mesh.  Discarding "
                    "all uvs.");
                uvs = nullptr;
                break;
            }
        }
    }
    for (int i = 0; i < nvi; ++i)
        if (vi[i] >= npi) {
            Error(
                "trianglemesh has out of-bounds vertex index %d (%d \"P\" "
                "values were given",
                vi[i], npi);
            return std::vector<std::shared_ptr<Shape>>();
        }

    std::shared_ptr<Texture<Float>> alphaTex;
    std::string alphaTexName = params.FindTexture("alpha");
    if (alphaTexName != "") {
        if (floatTextures->find(alphaTexName) != floatTextures->end())
            alphaTex = (*floatTextures)[alphaTexName];
        else
            Error("Couldn't find float texture \"%s\" for \"alpha\" parameter",
                  alphaTexName.c_str());
    } else if (params.FindOneFloat("alpha", 1.f) == 0.f)
        alphaTex.reset(new ConstantTexture<Float>(0.f));

    std::shared_ptr<Texture<Float>> shadowAlphaTex;
    std::string shadowAlphaTexName = params.FindTexture("shadowalpha");
    if (shadowAlphaTexName != "") {
        if (floatTextures->find(shadowAlphaTexName) != floatTextures->end())
            shadowAlphaTex = (*floatTextures)[shadowAlphaTexName];
        else
            Error(
                "Couldn't find float texture \"%s\" for \"shadowalpha\" "
                "parameter",
                shadowAlphaTexName.c_str());
    } else if (params.FindOneFloat("shadowalpha", 1.f) == 0.f)
        shadowAlphaTex.reset(new ConstantTexture<Float>(0.f));

    return CreateTriangleMesh(o2w, w2o, reverseOrientation, nvi / 3, vi, npi, P,
                              S, N, uvs, alphaTex, shadowAlphaTex);
}
コード例 #17
0
ファイル: meshtool.cpp プロジェクト: SangitaSingh/elmerfem
  double CalcTetBadnessGrad (const Point3d & p1, const Point3d & p2,
			     const Point3d & p3, const Point3d & p4, double h,
			     int pi, Vec<3> & grad)
  {
    double vol, l, ll, lll;
    double err;

    const Point3d *pp1, *pp2, *pp3, *pp4;

    pp1 = &p1;
    pp2 = &p2;
    pp3 = &p3;
    pp4 = &p4;
  
    switch (pi)
      {
      case 2:
	{
	  swap (pp1, pp2);
	  swap (pp3, pp4);
	  break;
	}
      case 3:
	{
	  swap (pp1, pp3);
	  swap (pp2, pp4);
	  break;
	}
      case 4:
	{
	  swap (pp1, pp4);
	  swap (pp3, pp2);
	  break;
	}
      }
  

    Vec3d v1 (*pp1, *pp2);
    Vec3d v2 (*pp1, *pp3);
    Vec3d v3 (*pp1, *pp4);

    Vec3d v4 (*pp2, *pp3);
    Vec3d v5 (*pp2, *pp4);
    Vec3d v6 (*pp3, *pp4);

    vol = -Determinant (v1, v2, v3) / 6;  

    Vec3d gradvol;
    Cross (v5, v4, gradvol);
    gradvol *= (-1.0/6.0);


    double ll1 = v1.Length2();
    double ll2 = v2.Length2();
    double ll3 = v3.Length2();
    double ll4 = v4.Length2();
    double ll5 = v5.Length2();
    double ll6 = v6.Length2();

    ll = ll1 + ll2 + ll3 + ll4 + ll5 + ll6;
    l = sqrt (ll);
    lll = l * ll;

    if (vol <= 1e-24 * lll)
      { 
	grad = Vec3d (0, 0, 0);
	return 1e24;
      }



    Vec3d gradll1 (*pp2, *pp1);
    Vec3d gradll2 (*pp3, *pp1);
    Vec3d gradll3 (*pp4, *pp1);
    gradll1 *= 2;
    gradll2 *= 2;
    gradll3 *= 2;

    Vec3d gradll (gradll1);
    gradll += gradll2;
    gradll += gradll3;

    /*
    Vec3d gradll;
    gradll = v1+v2+v3;
    gradll *= -2;
    */

    err = 0.0080187537 * lll / vol; 


    gradll *= (0.0080187537 * 1.5 * l / vol);
    Vec3d graderr(gradll);
    gradvol *= ( -0.0080187537 * lll / (vol * vol) );
    graderr += gradvol;
  
    if (h > 0)
      {
	/*
	Vec3d gradll1 (*pp2, *pp1);
	Vec3d gradll2 (*pp3, *pp1);
	Vec3d gradll3 (*pp4, *pp1);
	gradll1 *= 2;
	gradll2 *= 2;
	gradll3 *= 2;
	*/
	err += ll / (h*h) + 
	  h*h * ( 1 / ll1 + 1 / ll2 + 1 / ll3 + 
		  1 / ll4 + 1 / ll5 + 1 / ll6 ) - 12;

	graderr += (1/(h*h) - h*h/(ll1*ll1)) * gradll1;
	graderr += (1/(h*h) - h*h/(ll2*ll2)) * gradll2;
	graderr += (1/(h*h) - h*h/(ll3*ll3)) * gradll3;
	cout << "?";
      }


    double errpow;
    if (teterrpow == 2)
      {
        errpow = err*err;   
        grad = (2 * err) * graderr;
      }
    else
      {
        errpow = pow (err, teterrpow);
        grad = (teterrpow * errpow / err) * graderr;
      }
    return errpow;
  }
コード例 #18
0
ファイル: curve.cpp プロジェクト: Drooids/pbrt-v3
bool Curve::recursiveIntersect(const Ray &ray, Float *tHit,
                               SurfaceInteraction *isect, const Point3f cp[4],
                               const Transform &rayToObject, Float u0, Float u1,
                               int depth) const {
    // Try to cull curve segment versus ray

    // Compute bounding box of curve segment, _curveBounds_
    Bounds3f curveBounds =
        Union(Bounds3f(cp[0], cp[1]), Bounds3f(cp[2], cp[3]));
    Float maxWidth = std::max(Lerp(u0, common->width[0], common->width[1]),
                              Lerp(u1, common->width[0], common->width[1]));
    curveBounds = Expand(curveBounds, 0.5 * maxWidth);

    // Compute bounding box of ray, _rayBounds_
    Float rayLength = ray.d.Length();
    Float zMax = rayLength * ray.tMax;
    Bounds3f rayBounds(Point3f(0, 0, 0), Point3f(0, 0, zMax));
    if (Overlaps(curveBounds, rayBounds) == false) return false;
    if (depth > 0) {
        // Split curve segment into sub-segments and test for intersection
        Float uMid = 0.5f * (u0 + u1);
        Point3f cpSplit[7];
        SubdivideBezier(cp, cpSplit);
        return (recursiveIntersect(ray, tHit, isect, &cpSplit[0], rayToObject,
                                   u0, uMid, depth - 1) ||
                recursiveIntersect(ray, tHit, isect, &cpSplit[3], rayToObject,
                                   uMid, u1, depth - 1));
    } else {
        // Intersect ray with curve segment

        // Test ray against segment endpoint boundaries

        // Test sample point against tangent perpendicular at curve start
        Float edge =
            (cp[1].y - cp[0].y) * -cp[0].y + cp[0].x * (cp[0].x - cp[1].x);
        if (edge < 0) return false;

        // Test sample point against tangent perpendicular at curve end
        edge = (cp[2].y - cp[3].y) * -cp[3].y + cp[3].x * (cp[3].x - cp[2].x);
        if (edge < 0) return false;

        // Compute line $w$ that gives minimum distance to sample point
        Vector2f segmentDirection = Point2f(cp[3]) - Point2f(cp[0]);
        Float denom = segmentDirection.LengthSquared();
        if (denom == 0) return false;
        Float w = Dot(-Vector2f(cp[0]), segmentDirection) / denom;

        // Compute $u$ coordinate of curve intersection point and _hitWidth_
        Float u = Clamp(Lerp(w, u0, u1), u0, u1);
        Float hitWidth = Lerp(u, common->width[0], common->width[1]);
        Normal3f nHit;
        if (common->type == CurveType::Ribbon) {
            // Scale _hitWidth_ based on ribbon orientation
            Float sin0 = std::sin((1 - u) * common->normalAngle) *
                         common->invSinNormalAngle;
            Float sin1 =
                std::sin(u * common->normalAngle) * common->invSinNormalAngle;
            nHit = sin0 * common->n[0] + sin1 * common->n[1];
            hitWidth *= AbsDot(nHit, ray.d) / rayLength;
        }

        // Test intersection point against curve width
        Vector3f dpcdw;
        Point3f pc = EvalBezier(cp, Clamp(w, 0, 1), &dpcdw);
        Float ptCurveDist2 = pc.x * pc.x + pc.y * pc.y;
        if (ptCurveDist2 > hitWidth * hitWidth * .25) return false;
        if (pc.z < 0 || pc.z > zMax) return false;

        // Compute $v$ coordinate of curve intersection point
        Float ptCurveDist = std::sqrt(ptCurveDist2);
        Float edgeFunc = dpcdw.x * -pc.y + pc.x * dpcdw.y;
        Float v = (edgeFunc > 0) ? 0.5f + ptCurveDist / hitWidth
                                 : 0.5f - ptCurveDist / hitWidth;

        // Compute hit _t_ and partial derivatives for curve intersection
        if (tHit != nullptr) {
            // FIXME: this tHit isn't quite right for ribbons...
            *tHit = pc.z / rayLength;
            // Compute error bounds for curve intersection
            Vector3f pError(2 * hitWidth, 2 * hitWidth, 2 * hitWidth);

            // Compute $\dpdu$ and $\dpdv$ for curve intersection
            Vector3f dpdu, dpdv;
            EvalBezier(common->cpObj, u, &dpdu);
            if (common->type == CurveType::Ribbon)
                dpdv = Normalize(Cross(nHit, dpdu)) * hitWidth;
            else {
                // Compute curve $\dpdv$ for flat and cylinder curves
                Vector3f dpduPlane = (Inverse(rayToObject))(dpdu);
                Vector3f dpdvPlane =
                    Normalize(Vector3f(-dpduPlane.y, dpduPlane.x, 0)) *
                    hitWidth;
                if (common->type == CurveType::Cylinder) {
                    // Rotate _dpdvPlane_ to give cylindrical appearance
                    Float theta = Lerp(v, -90., 90.);
                    Transform rot = Rotate(-theta, dpduPlane);
                    dpdvPlane = rot(dpdvPlane);
                }
                dpdv = rayToObject(dpdvPlane);
            }
            *isect = (*ObjectToWorld)(SurfaceInteraction(
                ray(pc.z), pError, Point2f(u, v), -ray.d, dpdu, dpdv,
                Normal3f(0, 0, 0), Normal3f(0, 0, 0), ray.time, this));
        }
        ++nHits;
        return true;
    }
}
コード例 #19
0
ファイル: naiadmesh.cpp プロジェクト: karlssonper/cs348b
bool NaiadTriangle::IntersectP(const Ray &ray) const {
    PBRT_RAY_TRIANGLE_INTERSECTIONP_TEST(const_cast<Ray *>(&ray), const_cast<NaiadTriangle *>(this));
    // Compute $\VEC{s}_1$

    // Get NaiadTriangle vertices in _p1_, _p2_, and _p3_
    const Point &p1 = mesh->p[v[0]];
    const Point &p2 = mesh->p[v[1]];
    const Point &p3 = mesh->p[v[2]];
    Vector e1 = p2 - p1;
    Vector e2 = p3 - p1;
    Vector s1 = Cross(ray.d, e2);
    float divisor = Dot(s1, e1);
    
    if (divisor == 0.)
        return false;
    float invDivisor = 1.f / divisor;

    // Compute first barycentric coordinate
    Vector d = ray.o - p1;
    float b1 = Dot(d, s1) * invDivisor;
    if (b1 < 0. || b1 > 1.)
        return false;

    // Compute second barycentric coordinate
    Vector s2 = Cross(d, e1);
    float b2 = Dot(ray.d, s2) * invDivisor;
    if (b2 < 0. || b1 + b2 > 1.)
        return false;

    // Compute _t_ to intersection point
    float t = Dot(e2, s2) * invDivisor;
    if (t < ray.mint || t > ray.maxt)
        return false;

    // Test shadow ray intersection against alpha texture, if present
    if (ray.depth != -1 && mesh->alphaTexture) {
        // Compute NaiadTriangle partial derivatives
        Vector dpdu, dpdv;
        float uvs[3][2];
        GetUVs(uvs);

        // Compute deltas for NaiadTriangle partial derivatives
        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];
        Vector dp1 = p1 - p3, dp2 = p2 - p3;
        float determinant = du1 * dv2 - dv1 * du2;
        if (determinant == 0.f) {
            // Handle zero determinant for NaiadTriangle partial derivative matrix
            CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
        }
        else {
            float invdet = 1.f / determinant;
            dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
            dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
        }

        // Interpolate $(u,v)$ NaiadTriangle parametric coordinates
        float b0 = 1 - b1 - b2;
        float tu = b0*uvs[0][0] + b1*uvs[1][0] + b2*uvs[2][0];
        float tv = b0*uvs[0][1] + b1*uvs[1][1] + b2*uvs[2][1];
        DifferentialGeometry dgLocal(ray(t), dpdu, dpdv,
                                     Normal(0,0,0), Normal(0,0,0),
                                     tu, tv, this);
        if (mesh->alphaTexture->Evaluate(dgLocal) == 0.f)
            return false;
    }
    PBRT_RAY_TRIANGLE_INTERSECTIONP_HIT(const_cast<Ray *>(&ray), t);
    return true;
}
コード例 #20
0
bool Heightfield2::TriangleIntersect(const Ray &ray, float *tHit, float *rayEpsilon, DifferentialGeometry *dg, int index[]) const{
    PBRT_RAY_TRIANGLE_INTERSECTION_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this));

    // Get triangle vertices in _p1_, _p2_, and _p3_
    const Point &p1o = point[index[0]];
    const Point &p2o = point[index[1]];
    const Point &p3o = point[index[2]];
    const Point &p1 = (*ObjectToWorld)(p1o);
    const Point &p2 = (*ObjectToWorld)(p2o);
    const Point &p3 = (*ObjectToWorld)(p3o);
    Vector e1 = p2 - p1;
    Vector e2 = p3 - p1;
    Vector s1 = Cross(ray.d, e2);
    float divisor = Dot(s1, e1);
    
    if (divisor == 0.)
        return false;
    float invDivisor = 1.f / divisor;

    // Compute first barycentric coordinate
    Vector s = ray.o - p1;
    float b1 = Dot(s, s1) * invDivisor;
    if (b1 < 0. || b1 > 1.)
        return false;

    // Compute second barycentric coordinate
    Vector s2 = Cross(s, e1);
    float b2 = Dot(ray.d, s2) * invDivisor;
    if (b2 < 0. || b1 + b2 > 1.)
        return false;

    // Compute _t_ to intersection point
    float t = Dot(e2, s2) * invDivisor;
    if (t < ray.mint || t > ray.maxt)
        return false;

    // Compute triangle partial derivatives
    Vector dpdu, dpdv;

    // Compute deltas for triangle partial derivatives
    float du1 = p1o.x - p3o.x;
    float du2 = p2o.x - p3o.x;
    float dv1 = p1o.y - p3o.y;
    float dv2 = p2o.y - p3o.y;

    Vector dp1 = p1 - p3, dp2 = p2 - p3;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f) {
        // Handle zero determinant for triangle partial derivative matrix
        CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv);
    }
    else {
        float invdet = 1.f / determinant;
        dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet;
        dpdv = (-du2 * dp1 + du1 * dp2) * invdet;
    }

    // Interpolate $(u,v)$ triangle parametric coordinates
    float b0 = 1 - b1 - b2;
    float tu = b0*p1o.x + b1*p2o.x + b2*p3o.x;
    float tv = b0*p1o.y + b1*p2o.y + b2*p3o.y;

    // Fill in _DifferentialGeometry_ from triangle hit
    *dg = DifferentialGeometry(ray(t), dpdu, dpdv,
                               Normal(0,0,0), Normal(0,0,0),
                               tu, tv, this);
    *tHit = t;
    *rayEpsilon = 1e-3f * *tHit;
    ray.maxt = t;
    PBRT_RAY_TRIANGLE_INTERSECTION_HIT(const_cast<Ray *>(&ray), t);
    return true;
}
コード例 #21
0
ファイル: Spline.cpp プロジェクト: Gary1234567/ppsspp
void TesselateSplinePatch(u8 *&dest, int &count, const SplinePatch &spatch, u32 origVertType) {
	const float third = 1.0f / 3.0f;

	if (g_Config.bLowQualitySplineBezier) {
		// Fast and easy way - just draw the control points, generate some very basic normal vector substitutes.
		// Very inaccurate but okay for Loco Roco. Maybe should keep it as an option because it's fast.

		const int tile_min_u = (spatch.type_u & START_OPEN) ? 0 : 1;
		const int tile_min_v = (spatch.type_v & START_OPEN) ? 0 : 1;
		const int tile_max_u = (spatch.type_u & END_OPEN) ? spatch.count_u - 1 : spatch.count_u - 2;
		const int tile_max_v = (spatch.type_v & END_OPEN) ? spatch.count_v - 1 : spatch.count_v - 2;

		for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
			for (int tile_u = tile_min_u; tile_u < tile_max_u; ++tile_u) {
				int point_index = tile_u + tile_v * spatch.count_u;

				SimpleVertex v0 = *spatch.points[point_index];
				SimpleVertex v1 = *spatch.points[point_index+1];
				SimpleVertex v2 = *spatch.points[point_index+spatch.count_u];
				SimpleVertex v3 = *spatch.points[point_index+spatch.count_u+1];

				// Generate UV. TODO: Do this even if UV specified in control points?
				if ((origVertType & GE_VTYPE_TC_MASK) == 0) {
					float u = tile_u * third;
					float v = tile_v * third;
					v0.uv[0] = u;
					v0.uv[1] = v;
					v1.uv[0] = u + third;
					v1.uv[1] = v;
					v2.uv[0] = u;
					v2.uv[1] = v + third;
					v3.uv[0] = u + third;
					v3.uv[1] = v + third;
				}

				// Generate normal if lighting is enabled (otherwise there's no point).
				// This is a really poor quality algorithm, we get facet normals.
				if (gstate.isLightingEnabled()) {
					Vec3f norm = Cross(v1.pos - v0.pos, v2.pos - v0.pos);
					norm.Normalize();
					if (gstate.patchfacing & 1)
						norm *= -1.0f;
					v0.nrm = norm;
					v1.nrm = norm;
					v2.nrm = norm;
					v3.nrm = norm;
				}

				CopyQuad(dest, &v0, &v1, &v2, &v3);
				count += 6;
			}
		}
	} else {
		// Full correct tessellation of spline patches.
		// Does not yet generate normals and is atrociously slow (see spline_s...)

		// First, generate knot vectors.
		int n = spatch.count_u - 1;
		int m = spatch.count_v - 1;

		float *knot_u = new float[n + 5];
		float *knot_v = new float[m + 5];
		spline_knot(n, spatch.type_u, knot_u);
		spline_knot(m, spatch.type_v, knot_v);

		int patch_div_s = gstate.getPatchDivisionU();
		int patch_div_t = gstate.getPatchDivisionV();

		// Increase tesselation based on the size. Should be approximately right?
		// JPCSP is wrong at least because their method results in square loco roco.
		patch_div_s = (spatch.count_u - 3) * patch_div_s / 3;
		patch_div_t = (spatch.count_v - 3) * patch_div_t / 3;
		if (patch_div_s == 0) patch_div_s = 1;
		if (patch_div_t == 0) patch_div_t = 1;

		// TODO: Remove this cap when spline_s has been optimized. 
		if (patch_div_s > 64) patch_div_s = 64;
		if (patch_div_t > 64) patch_div_t = 64;

		// First compute all the vertices and put them in an array
		SimpleVertex *vertices = new SimpleVertex[(patch_div_s + 1) * (patch_div_t + 1)];

		float tu_width = 1.0f + (spatch.count_u - 4) * 1.0f/3.0f;
		float tv_height = 1.0f + (spatch.count_v - 4) * 1.0f/3.0f;

		bool computeNormals = gstate.isLightingEnabled();
		for (int tile_v = 0; tile_v < patch_div_t + 1; tile_v++) {
			float v = ((float)tile_v * (float)(m - 2) / (float)(patch_div_t + 0.00001f));  // epsilon to prevent division by 0 in spline_s
			for (int tile_u = 0; tile_u < patch_div_s + 1; tile_u++) {
				float u = ((float)tile_u * (float)(n - 2) / (float)(patch_div_s + 0.00001f));

				SimpleVertex *vert = &vertices[tile_v * (patch_div_s + 1) + tile_u];
				vert->pos.SetZero();
				if (origVertType & GE_VTYPE_NRM_MASK) {
					vert->nrm.SetZero();
				} else {
					vert->nrm.SetZero();
					vert->nrm.z = 1.0f;
				}
				if (origVertType & GE_VTYPE_COL_MASK) {
					memset(vert->color, 0, 4);
				} else {
					memcpy(vert->color, spatch.points[0]->color, 4);
				}
				if (origVertType & GE_VTYPE_TC_MASK) {
					vert->uv[0] = 0.0f;
					vert->uv[1] = 0.0f;
				} else {
					vert->uv[0] = tu_width * ((float)tile_u / (float)patch_div_s);
					vert->uv[1] = tv_height * ((float)tile_v / (float)patch_div_t);
				}

				// Collect influences from surrounding control points.
				float u_weights[4];
				float v_weights[4];
				
				int iu = (int)u;
				int iv = (int)v;
				spline_n_4(iu, u, knot_u, u_weights);
				spline_n_4(iv, v, knot_v, v_weights);

				for (int ii = 0; ii < 4; ++ii) {
					for (int jj = 0; jj < 4; ++jj) {
						float u_spline = u_weights[ii];
						float v_spline = v_weights[jj];
						float f = u_spline * v_spline;
						
						if (f > 0.0f) {
							SimpleVertex *a = spatch.points[spatch.count_u * (iv + jj) + (iu + ii)];
							vert->pos += a->pos * f;
							if (origVertType & GE_VTYPE_TC_MASK) {
								vert->uv[0] += a->uv[0] * f;
								vert->uv[1] += a->uv[1] * f;
							}
							if (origVertType & GE_VTYPE_COL_MASK) {
								vert->color[0] += a->color[0] * f;
								vert->color[1] += a->color[1] * f;
								vert->color[2] += a->color[2] * f;
								vert->color[3] += a->color[3] * f;
							}
							if (origVertType & GE_VTYPE_NRM_MASK) {
								vert->nrm += a->nrm * f;
							}
						}
					}
				}
				if (origVertType & GE_VTYPE_NRM_MASK) {
					vert->nrm.Normalize();
				}
			}
		}

		delete [] knot_u;
		delete [] knot_v;

		// Hacky normal generation through central difference.
		if (gstate.isLightingEnabled() && (origVertType & GE_VTYPE_NRM_MASK) == 0) {
			for (int v = 0; v < patch_div_t + 1; v++) {
				for (int u = 0; u < patch_div_s + 1; u++) {
					int l = std::max(0, u - 1);
					int t = std::max(0, v - 1);
					int r = std::min(patch_div_s, u + 1);
					int b = std::min(patch_div_t, v + 1);

					const Vec3f &right = vertices[v * (patch_div_s + 1) + r].pos - vertices[v * (patch_div_s + 1) + l].pos;
					const Vec3f &down = vertices[b * (patch_div_s + 1) + u].pos - vertices[t * (patch_div_s + 1) + u].pos;

					vertices[v * (patch_div_s + 1) + u].nrm = Cross(right, down).Normalized();
					if (gstate.patchfacing & 1) {
						vertices[v * (patch_div_s + 1) + u].nrm *= -1.0f;
					}
				}
			}
		}

		// Tesselate. TODO: Use indices so we only need to emit 4 vertices per pair of triangles instead of six.
		for (int tile_v = 0; tile_v < patch_div_t; ++tile_v) {
			for (int tile_u = 0; tile_u < patch_div_s; ++tile_u) {
				float u = ((float)tile_u / (float)patch_div_s);
				float v = ((float)tile_v / (float)patch_div_t);

				SimpleVertex *v0 = &vertices[tile_v * (patch_div_s + 1) + tile_u];
				SimpleVertex *v1 = &vertices[tile_v * (patch_div_s + 1) + tile_u + 1];
				SimpleVertex *v2 = &vertices[(tile_v + 1) * (patch_div_s + 1) + tile_u];
				SimpleVertex *v3 = &vertices[(tile_v + 1) * (patch_div_s + 1) + tile_u + 1];

				CopyQuad(dest, v0, v1, v2, v3);
				count += 6;
			}
		}

		delete [] vertices;
	}
}
コード例 #22
0
void Heightfield2::GetShadingGeometry(const Transform &obj2world, const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const {
    // Initialize _Triangle_ shading geometry with _n_ and _s_

    // *dgShading = dg;
    // return;

    Point p = Point(dg.u, dg.v, 0);
    int x = posToVoxel(p, 0);
    int y = posToVoxel(p, 1);
    int index1 = x + y*nx;
    int index2, index3;

    const Point &p1o = point[index1];
    if((dg.u-p1o.x)*width[1] > (dg.v-p1o.y)*width[0]){
        index2 = x+1 + y*nx;
        index3 = x+1 + (y+1)*nx;
    }else{
        index2 = x+1 + (y+1)*nx;
        index3 = x + (y+1)*nx;
    }
    const Point &p2o = point[index2];
    const Point &p3o = point[index3];
    const Normal &normal0 = normal[index1];
    const Normal &normal1 = normal[index2];
    const Normal &normal2 = normal[index3];

    // Compute barycentric coordinates for point
    float b[3];

    // Initialize _A_ and _C_ matrices for barycentrics
    float A[2][2] =
        { { p2o.x - p1o.x, p3o.x - p1o.x },
          { p2o.y - p1o.y, p3o.y - p1o.y } };
    float C[2] = { dg.u - p1o.x, dg.v - p1o.y };
    if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) {
        // Handle degenerate parametric mapping
        b[0] = b[1] = b[2] = 1.f/3.f;
    }
    else
        b[0] = 1.f - b[1] - b[2];

    // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_
    Normal ns;
    Vector ss, ts;
    ns = Normalize(obj2world(b[0] * normal0 + b[1] * normal1 + b[2] * normal2));
    ss = Normalize(dg.dpdu);
    
    ts = Cross(ss, ns);
    if (ts.LengthSquared() > 0.f) {
        ts = Normalize(ts);
        ss = Cross(ts, ns);
    }
    else
        CoordinateSystem((Vector)ns, &ss, &ts);
    Normal dndu, dndv;

    // Compute $\dndu$ and $\dndv$ for triangle shading geometry
    // Compute deltas for triangle partial derivatives of normal
    float du1 = p1o.x - p3o.x;
    float du2 = p2o.x - p3o.x;
    float dv1 = p1o.y - p3o.y;
    float dv2 = p2o.y - p3o.y;
    Normal dn1 = normal0 - normal2;
    Normal dn2 = normal1 - normal2;
    float determinant = du1 * dv2 - dv1 * du2;
    if (determinant == 0.f)
        dndu = dndv = Normal(0,0,0);
    else {
        float invdet = 1.f / determinant;
        dndu = ( dv2 * dn1 - dv1 * dn2) * invdet;
        dndv = (-du2 * dn1 + du1 * dn2) * invdet;
    }

    *dgShading = DifferentialGeometry(dg.p, ss, ts, obj2world(dndu), obj2world(dndv), dg.u, dg.v, dg.shape);
    dgShading->dudx = dg.dudx;  dgShading->dvdx = dg.dvdx;
    dgShading->dudy = dg.dudy;  dgShading->dvdy = dg.dvdy;
    dgShading->dpdx = dg.dpdx;  dgShading->dpdy = dg.dpdy;
}
コード例 #23
0
ファイル: Hull.cpp プロジェクト: Belxjander/Asuna
void Hull::ComputeInertia(const Transform& transform, Point3& centerOfMass, Matrix33& inertia, float totalMass) const
{
	assert(totalMass > 0.0f);

	// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
	float integral[10] = {0,0,0,0,0,0,0,0,0,0};

	// for each triangle
	for (short face = 0; face < m_numFaces; face++)
	{
		short edge = GetFaceFirstEdge(face);
		Point3 v0 = m_pVerts[ GetEdgeVertex0(face, edge) ] * transform;

		edge = GetFaceNextEdge(face, edge);
		Point3 v1 = m_pVerts[ GetEdgeVertex0(face, edge) ] * transform;

		for (edge = GetFaceNextEdge(face, edge); edge != -1; edge = GetFaceNextEdge(face, edge))
		{
			Point3 v2 = m_pVerts[ GetEdgeVertex0(face, edge) ] * transform;

			// get cross product of triangle edges
			Vector3 d = Cross(v2 - v0, v1 - v0);

			// compute integral terms
			Vector3 w0 = Vector3(v0);
			Vector3 w1 = Vector3(v1);
			Vector3 w2 = Vector3(v2);

			Vector3 temp0 = w0 + w1;
			Vector3 f1 = temp0 + w2;
			Vector3 temp1 = w0 * w0;
			Vector3 temp2 = temp1 + w1 * temp0;
			Vector3 f2 = temp2 + w2 * f1;
			Vector3 f3 = w0 * temp1 + w1 * temp2 + w2 * f2;
			Vector3 g0 = f2 + w0 * (f1 + w0);
			Vector3 g1 = f2 + w1 * (f1 + w1);
			Vector3 g2 = f2 + w2 * (f1 + w2);

			// update integrals
			integral[0] += d[0] * f1[0];
			integral[1] += d[0] * f2[0];
			integral[2] += d[1] * f2[1];
			integral[3] += d[2] * f2[2];
			integral[4] += d[0] * f3[0];
			integral[5] += d[1] * f3[1];
			integral[6] += d[2] * f3[2];
			integral[7] += d[0] * (v0[1] * g0[0] + v1[1] * g1[0] + v2[1] * g2[0]);
			integral[8] += d[1] * (v0[2] * g0[1] + v1[2] * g1[1] + v2[2] * g2[1]);
			integral[9] += d[2] * (v0[0] * g0[2] + v1[0] * g1[2] + v2[0] * g2[2]);

			// next edge
			v1 = v2;
		}
	}

	integral[0] *= 1.0f / 6.0f;
	integral[1] *= 1.0f / 24.0f;
	integral[2] *= 1.0f / 24.0f;
	integral[3] *= 1.0f / 24.0f;
	integral[4] *= 1.0f / 60.0f;
	integral[5] *= 1.0f / 60.0f;
	integral[6] *= 1.0f / 60.0f;
	integral[7] *= 1.0f / 120.0f;
	integral[8] *= 1.0f / 120.0f;
	integral[9] *= 1.0f / 120.0f;

	// scale all integrals to get desired total mass
	assert(integral[0] > 0.0f);

	float invMassRatio = totalMass / integral[0];
	for (int i = 0; i < 10; i++)
		integral[i] *= invMassRatio;

	// center of mass
	centerOfMass = Point3(integral[1] / totalMass, integral[2] / totalMass, integral[3] / totalMass);

	// inertia relative to world
	inertia[0][0] = integral[5] + integral[6];
	inertia[0][1] = -integral[7];
	inertia[0][2] = -integral[9];

	inertia[1][0] = -integral[7];
	inertia[1][1] = integral[4] + integral[6];
	inertia[1][2] = -integral[8];

	inertia[2][0] = -integral[9];
	inertia[2][1] = -integral[8];
	inertia[2][2] = integral[5] + integral[5];

	// inertia relative to center of mass
	inertia[0][0] -= totalMass * (centerOfMass[1] * centerOfMass[1] + centerOfMass[2] * centerOfMass[2]);
	inertia[0][1] += totalMass * centerOfMass[0] * centerOfMass[1];
	inertia[0][2] += totalMass * centerOfMass[2] * centerOfMass[0];

	inertia[1][0] += totalMass * centerOfMass[0] * centerOfMass[1];
	inertia[1][1] -= totalMass * (centerOfMass[2] * centerOfMass[2] + centerOfMass[0] * centerOfMass[0]);
	inertia[1][2] += totalMass * centerOfMass[1] * centerOfMass[2];

	inertia[2][0] += totalMass * centerOfMass[2] * centerOfMass[0];
	inertia[2][1] += totalMass * centerOfMass[1] * centerOfMass[2];
	inertia[2][2] -= totalMass * (centerOfMass[0] * centerOfMass[0] + centerOfMass[1] * centerOfMass[1]);
}
コード例 #24
0
// Heightfield2 Method Definitions
Heightfield2::Heightfield2(const Transform *o2w, const Transform *w2o,
        bool ro, int x, int y, const float *zs)
    : Shape(o2w, w2o, ro) {
    nx = x;
    ny = y;
    z = new float[nx*ny];
    point = new Point[nx*ny];
    normal = new Normal[nx * ny];
    memcpy(z, zs, nx*ny*sizeof(float));

    nVoxels[0] = x-1;
    nVoxels[1] = y-1;
    bounds = ObjectBound();
    for (int axis = 0; axis < 2; ++axis) {
        width[axis] = 1.f / nVoxels[axis];
        invWidth[axis] = (width[axis] == 0.f) ? 0.f : 1.f / width[axis];
    }

    int index = 0;
    for(int _y = 0; _y < y; _y++){
        for(int _x = 0; _x < x; _x++){
            point[index] = Point(_x * width[0], _y * width[1], z[index]);
            normal[index] = Normal(0, 0, 0);
            index++;
        }
    }

    for (int _y = 0; _y < nVoxels[1]; _y++) {
        for (int _x = 0; _x < nVoxels[0]; _x++) {
            int index1 = _x + _y*nx;
            int index2 = _x+1 + _y*nx;
            int index3 = _x+1 + (_y+1)*nx;
            int index4 = _x + (_y+1)*nx;

            const Point &p1 = point[index1];
            const Point &p2 = point[index2];
            const Point &p3 = point[index3];
            const Point &p4 = point[index4];
            
            Normal &normal1 = normal[index1];
            Normal &normal2 = normal[index2];
            Normal &normal3 = normal[index3];
            Normal &normal4 = normal[index4];
            Normal normal;

            normal = Normal(Normalize(Cross(p2 - p1, p3 - p1)));
            normal1 += normal;
            normal2 += normal;
            normal3 += normal;

            normal = Normal(Normalize(Cross(p3 - p1, p4 - p1)));
            normal1 += normal;
            normal3 += normal;
            normal4 += normal;
        }
    }

    for (int i = 0; i < nx*ny; i++) {
        normal[i] = Normalize(normal[i]);
    }
}
コード例 #25
0
ファイル: PlayerMC.cpp プロジェクト: norrischiu/DEngine
void PlayerMC::Dispatch()
{
	// set player to look at boss
	DE::Vector3 direction = ((Player*)m_pOwner)->GetBoss()->GetPosition() - m_pOwner->GetPosition();
	if (!direction.iszero())
	{
		float length = direction.Length();
		DE::Vector3 cross = Cross(m_pOwner->GetTransform()->GetForward().Normal(), direction.Normal());
		float dot = cross.Dot(DE::Vector3::UnitY);
		float theta = asinf(cross.Length());
		int y = 1;
		if (dot < 0.0f)
		{
			y = -1;
		}
		float speedUp = (theta > PI) ? 3.0f : 1.0f;
		DE::Quaternion quat(DE::Vector3(0, y, 0), theta * m_fDeltaTime * speedUp);
		m_pOwner->TransformBy(quat.GetRotationMatrix());
	}

	// only send new animation event when player is not being impacted
	if (((Player*)m_pOwner)->GetState() != Player::IMPACTING)
	{
		if (m_vTrans.iszero() && ((Player*)m_pOwner)->GetState() == Player::LOCOMOTION && m_bWalk)
		{
			DE::Handle h(sizeof(Player_Walk_END_Event));
			new (h) Player_Walk_END_Event;
			DE::EventQueue::GetInstance()->Add(h, DE::GAME_EVENT);
			m_bWalk = false;
		}
		else if (m_bDodge && !m_vTrans.iszero() && ((Player*)m_pOwner)->GetStamina() >= 20.0f)
		{
			m_vDodgeDir = m_vTrans.Normal();
			m_bDodge = false;

			((Player*)m_pOwner)->SetState(Player::DOGDING);
			((Player*)m_pOwner)->AddStamina(-20.0f);
			DE::Handle h(sizeof(Player_Dodge_START_Event));
			new (h) Player_Dodge_START_Event;
			((Player_Dodge_START_Event*)h.Raw())->m_vDir = m_vTrans.Normal();
			DE::EventQueue::GetInstance()->Add(h, DE::GAME_EVENT);
		}
		else if (!m_vTrans.iszero() && ((Player*)m_pOwner)->GetState() == Player::LOCOMOTION)
		{
			Move(m_vTrans);
			m_bWalk = true;
			if (m_bRun)
			{
				if (!m_bRunLock && ((Player*)m_pOwner)->GetStamina() >= 4.0f)
				{
					((Player*)m_pOwner)->AddStamina(-2.0f);
				}
				else
				{
					m_bRunLock = true;
					m_bRun = false;
				}
			}

			DE::Handle h(sizeof(Player_Walk_PLAYING_Event));
			new (h) Player_Walk_PLAYING_Event;
			((Player_Walk_PLAYING_Event*)h.Raw())->m_vDir = m_vTrans.Normal();
			((Player_Walk_PLAYING_Event*)h.Raw())->m_bRun = m_bRun;
			DE::EventQueue::GetInstance()->Add(h, DE::GAME_EVENT);
		}
		if (((Player*)m_pOwner)->GetState() == Player::DOGDING)
		{
			Move(m_vDodgeDir * m_fSpeed * m_fDeltaTime * 3.0f);
		}
		if (m_ComboSequence[0] || m_ComboSequence[1])
		{
			m_fComboTime += m_fDeltaTime;
		}
		if (m_ComboSequence[2])
		{
			DE::Vector3 vForward = DE::Vector3::UnitZ;
			Move(vForward * m_fSpeed * m_fDeltaTime * 0.5f);
		}
	}
	m_vTrans = DE::Vector3::Zero;
	m_bDodge = false;
	m_bRun = false;
}
コード例 #26
0
ファイル: Loader3ds.c プロジェクト: deweerdt/TSP
void ComputeNormals(Loader3ds *pt3ds) 
{ 
 int i,j,index; 
 int shared=0; 
	float	v1x=0.0,v1y=0.0,v1z=0.0, 
			v2x=0.0,v2y=0.0,v2z=0.0, 
			vnx=0.0,vny=0.0,vnz=0.0, 
			vp0x=0.0,vp0y=0.0,vp0z=0.0, 
			vp1x=0.0,vp1y=0.0,vp1z=0.0, 
			vp2x=0.0,vp2y=0.0,vp2z=0.0, 
			*pNormals=NULL, 
			*pTempNormals=NULL, 
			vSumx = 0.0,vSumy = 0.0,vSumz = 0.0;	 
 	Objects *cur_obj; 

	// If there are no objects, we can skip this part 
	if(pt3ds->NBobjects <= 0) 
		return; 
 
	// Go through each of the objects to calculate their normals 
	cur_obj = pt3ds->objects; 
	for(index = 0; index < pt3ds->NBobjects; index++) 
	{ 
		pNormals		= (float*)malloc(sizeof(float) *(3*cur_obj->NBFaces)); 
		pTempNormals	= (float*)malloc(sizeof(float) * (3*cur_obj->NBFaces)); 
		cur_obj->Normal = (float*)malloc(sizeof(float) * (3*cur_obj->NBvert)); 
 
 
		// Go though all of the faces of this object 
		for(i=0; i < cur_obj->NBFaces; i++) 
		  {
			vp0x=cur_obj->vert[0+3*cur_obj->Faces[i*3]]; 
			vp0y=cur_obj->vert[1+3*cur_obj->Faces[i*3]]; 
			vp0z=cur_obj->vert[2+3*cur_obj->Faces[i*3]]; 
 
			vp1x=cur_obj->vert[0+3*cur_obj->Faces[i*3+1]]; 
			vp1y=cur_obj->vert[1+3*cur_obj->Faces[i*3+1]]; 
			vp1z=cur_obj->vert[2+3*cur_obj->Faces[i*3+1]]; 
 
			vp2x=cur_obj->vert[0+3*cur_obj->Faces[i*3+2]]; 
			vp2y=cur_obj->vert[1+3*cur_obj->Faces[i*3+2]]; 
			vp2z=cur_obj->vert[2+3*cur_obj->Faces[i*3+2]]; 
  
			Vector(	vp0x,vp0y,vp0z, 
					vp2x,vp2y,vp2z, 
					&v1x,&v1y,&v1z);		// Get the vector of the polygon (we just need 2 sides for the normal) 
 
			Vector(	vp2x,vp2y,vp2z, 
					vp1x,vp1y,vp1z, 
					&v2x,&v2y,&v2z);		// Get a second vector of the polygon 
			 
			Cross(	v1x,v1y,v1z, 
					v2x,v2y,v2z, 
					&vnx,&vny,&vnz);		// Return the cross product of the 2 vectors (normalize vector, but not a unit vector) 
 
			pTempNormals[3*i] = vnx;					// Save the un-normalized normal for the vertex normals 
			pTempNormals[3*i+1] = vny;					// Save the un-normalized normal for the vertex normals 
			pTempNormals[3*i+2] = vnz;					// Save the un-normalized normal for the vertex normals 
 
			Normalize(&vnx,&vny,&vnz);				// Normalize the cross product to give us the polygons normal 
 
			pNormals[3*i] = vnx;						// Assign the normal to the list of normals 
			pNormals[3*i+1] = vny;						// Assign the normal to the list of normals 
			pNormals[3*i+2] = vnz;						// Assign the normal to the list of normals 
		} 
 
		//////////////// Now Get The Vertex Normals ///////////////// 
 
		vSumx = 0.0;vSumy = 0.0;vSumz = 0.0;		 
		shared=0; 
 
		for (i = 0; i < cur_obj->NBvert; i++)			// Go through all of the vertices 
		{ 
			for (j = 0; j < cur_obj->NBFaces; j++)	// Go through all of the triangles 
			{												// Check if the vertex is shared by another face 
				if (cur_obj->Faces[j*3]   == i ||  
					cur_obj->Faces[j*3+1] == i ||  
					cur_obj->Faces[j*3+2] == i) 
				{ 
					AddVector(	vSumx,vSumy,vSumz, 
								pTempNormals[j*3],pTempNormals[j*3+1],pTempNormals[j*3+2], 
								&vSumx,&vSumy,&vSumz);// Add the un-normalized normal of the shared face 
					shared++;								// Increase the number of shared triangles 
				} 
			}       
			 
			// Get the normal by dividing the sum by the shared.  We negate the shared so it has the normals pointing out. 
			 DivideVectorByScaler(	vSumx,vSumy,vSumz, 
									&(cur_obj->Normal[i*3]), 
									&(cur_obj->Normal[i*3+1]), 
									&(cur_obj->Normal[i*3+2]), 
									-(float)shared); 
 
			// Normalize the normal for the final vertex normal 
			Normalize(	&(cur_obj->Normal[i*3]), 
						&(cur_obj->Normal[i*3+1]), 
						&(cur_obj->Normal[i*3+2]));	 
 
			vSumx = 0.0;vSumy = 0.0;vSumz = 0.0;			// Reset the sum 
			shared = 0;										// Reset the shared 
		} 
		 
	if (pNormals) free(pNormals); 
	if (pTempNormals) free(pTempNormals); 
	cur_obj=cur_obj->next; 
	}//end for index 
} 
コード例 #27
0
ファイル: Polygon.cpp プロジェクト: Mars999/MathGeoLib
float3 Polygon::BasisV() const
{
	if (p.size() < 2)
		return float3::unitY;
	return Cross(BasisU(), PlaneCCW().normal).Normalized();
}
コード例 #28
0
ファイル: demo.cpp プロジェクト: icharlie/glui-cs553
void
Arrow( float tail[3], float head[3] )
{
	float u[3], v[3], w[3];		// arrow coordinate system

	// set w direction in u-v-w coordinate system:

	w[0] = head[0] - tail[0];
	w[1] = head[1] - tail[1];
	w[2] = head[2] - tail[2];


	// determine major direction:

	int axis = X;
	float mag = fabs( w[0] );
	if(  fabs( w[1] )  > mag  )
	{
		axis = Y;
		mag = fabs( w[1] );
	}
	if(  fabs( w[2] )  > mag  )
	{
		axis = Z;
		mag = fabs( w[2] );
	}


	// set size of wings and turn w into a Unit vector:

	float d = WINGS * Unit( w, w );


	// draw the shaft of the arrow:

	glBegin( GL_LINE_STRIP );
		glVertex3fv( tail );
		glVertex3fv( head );
	glEnd( );

	// draw two sets of wings in the non-major directions:

	float x, y, z;

	if( axis != X )
	{
		Cross( w, axx, v );
		(void) Unit( v, v );
		Cross( v, w, u  );
		x = head[0] + d * ( u[0] - w[0] );
		y = head[1] + d * ( u[1] - w[1] );
		z = head[2] + d * ( u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
		x = head[0] + d * ( -u[0] - w[0] );
		y = head[1] + d * ( -u[1] - w[1] );
		z = head[2] + d * ( -u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
	}


	if( axis != Y )
	{
		Cross( w, ayy, v );
		(void) Unit( v, v );
		Cross( v, w, u  );
		x = head[0] + d * ( u[0] - w[0] );
		y = head[1] + d * ( u[1] - w[1] );
		z = head[2] + d * ( u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
		x = head[0] + d * ( -u[0] - w[0] );
		y = head[1] + d * ( -u[1] - w[1] );
		z = head[2] + d * ( -u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
	}



	if( axis != Z )
	{
		Cross( w, azz, v );
		(void) Unit( v, v );
		Cross( v, w, u  );
		x = head[0] + d * ( u[0] - w[0] );
		y = head[1] + d * ( u[1] - w[1] );
		z = head[2] + d * ( u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
		x = head[0] + d * ( -u[0] - w[0] );
		y = head[1] + d * ( -u[1] - w[1] );
		z = head[2] + d * ( -u[2] - w[2] );
		glBegin( GL_LINE_STRIP );
			glVertex3fv( head );
			glVertex3f( x, y, z );
		glEnd( );
	}
}
コード例 #29
0
ファイル: terrain.cpp プロジェクト: alexgaiv/terrain
bool Terrain::LoadHeightmap(const char *filename, float heightScale)
{
	img.LoadTga(filename);
	if (!img) return false;

	this->heightScale = heightScale;
	int w = img.GetWidth();
	int h = img.GetHeight();
	indicesCount = (w-1)*(h-1)*6;

	Vector3f *verts = new Vector3f[w * h];
	Vector3f *norms = new Vector3f[w * h];
	Vector2f *texs = new Vector2f[w * h];
	UINT *inds = new UINT[indicesCount];
	Vector3f *polygonNormals[2];

	for (int i = 0; i < 2; i++)
		polygonNormals[i] = new Vector3f[(w-1)*(h-1)*2];

	float hw = w * 0.5f;
	float hh = h * 0.5f;
	float k = 1.0f / 255.0f * heightScale;

	for (int i = 0; i < w; i++)
		for (int j = 0; j < h; j++)
		{
			int idx = i * h + j;
			verts[idx].x = i - hw;
			verts[idx].z = j - hh;
			verts[idx].y = img.GetPixel(i, j).r * k;

			texs[idx].x = i*0.3f;
			texs[idx].y = j*0.3f;
		}

	int n = 0;
	for (int i = 0; i < w - 1; i++)
		for (int j = 0; j < h - 1; j++)
		{
			inds[n] = i*h + j;
			inds[n+1] = i*h + (j+1);
			inds[n+2] = (i+1)*h + (j+1);

			inds[n+3] = inds[n];
			inds[n+4] = inds[n+2];
			inds[n+5] = (i+1)*h + j;

			Vector3f t1[3] = {
				verts[inds[n]],
				verts[inds[n+1]],
				verts[inds[n+2]]
			};

			Vector3f t2[3] = {
				verts[inds[n+3]],
				verts[inds[n+4]],
				verts[inds[n+5]]
			};

			polygonNormals[0][i*h + j] = Normalize(Cross(t1[0] - t1[1], t1[1] - t1[2]));
			polygonNormals[1][i*h + j] = Normalize(Cross(t2[0] - t2[1], t2[1] - t2[2]));

			n += 6;
		}

	for (int i = 0; i < w; i++)
		for (int j = 0; j < h; j++)
		{
			Vector3f &normal = norms[i*h + j];

			if (i != 0 && j != 0) {
				for (int k = 0; k < 2; k++)
					normal += polygonNormals[k][(i-1)*h + (j-1)];
			}

			if (i != w - 1 && j != h - 1) {
				for (int k = 0; k < 2; k++)
					normal += polygonNormals[k][i*h + j];
			}

			if (i != 0 && j != h - 1)
				normal += polygonNormals[1][(i-1)*h + j];
			if (j != 0 && i != w - 1)
				normal += polygonNormals[0][i*h + (j-1)];

			normal.Normalize();
		}

	vertices.SetData(w * h * sizeof(Vector3f), verts, GL_STATIC_DRAW);
	normals.SetData(w * h * sizeof(Vector3f), norms, GL_STATIC_DRAW);
	texCoords.SetData(w * h * sizeof(Vector2f), texs, GL_STATIC_DRAW);
	indices.SetData(indicesCount * sizeof(UINT), inds, GL_STATIC_DRAW);

	delete [] polygonNormals[0];
	delete [] polygonNormals[1];

	delete [] verts;
	delete [] norms;
	delete [] texs;
	delete [] inds;
	return true;
}
コード例 #30
0
	// compute polygon list of edge plane intersections
	//
	// This is never called externally and could be private.
	//
	// The representation returned is not efficient, but it appears a
	// typical rendering only contains about 1k triangles.
	void TextureBrick::compute_polygons(Ray& view,
		double tmin, double tmax, double dt,
		vector<float>& vertex, vector<uint32_t>& index,
		vector<uint32_t>& size)
	{
		if (dt <= 0.0)
			return;

		Vector vv[12], tt[12]; // temp storage for vertices and texcoords

		uint32_t degree = 0;

		// find up and right vectors
		Vector vdir = view.direction();
		view_vector_ = vdir;
		Vector up;
		Vector right;
		switch (MinIndex(fabs(vdir.x()),
			fabs(vdir.y()),
			fabs(vdir.z())))
		{
		case 0:
			up.x(0.0); up.y(-vdir.z()); up.z(vdir.y());
			break;
		case 1:
			up.x(-vdir.z()); up.y(0.0); up.z(vdir.x());
			break;
		case 2:
			up.x(-vdir.y()); up.y(vdir.x()); up.z(0.0);
			break;
		}
		up.normalize();
		right = Cross(vdir, up);
		bool order = TextureRenderer::get_update_order();
		size_t vert_count = 0;
		for (double t = order ? tmin : tmax;
		order ? (t < tmax) : (t > tmin);
			t += order ? dt : -dt)
		{
			// we compute polys back to front
			// find intersections
			degree = 0;
			for (size_t j = 0; j < 12; j++)
			{
				double u;

				FLIVR::Vector vec = -view.direction();
				FLIVR::Point pnt = view.parameter(t);
				bool intersects = edge_[j].planeIntersectParameter
					(vec, pnt, u);
				if (intersects && u >= 0.0 && u <= 1.0)
				{
					Point p;
					p = edge_[j].parameter(u);
					vv[degree] = (Vector)p;
					p = tex_edge_[j].parameter(u);
					tt[degree] = (Vector)p;
					degree++;
				}
			}

			if (degree < 3 || degree >6) continue;
			bool sorted = degree > 3;
			uint32_t idx[6];
			if (sorted) {
				// compute centroids
				Vector vc(0.0, 0.0, 0.0), tc(0.0, 0.0, 0.0);
				for (int j = 0; j < degree; j++)
				{
					vc += vv[j]; tc += tt[j];
				}
				vc /= (double)degree; tc /= (double)degree;

				// sort vertices
				double pa[6];
				for (uint32_t i = 0; i < degree; i++)
				{
					double vx = Dot(vv[i] - vc, right);
					double vy = Dot(vv[i] - vc, up);

					// compute pseudo-angle
					pa[i] = vy / (fabs(vx) + fabs(vy));
					if (vx < 0.0) pa[i] = 2.0 - pa[i];
					else if (vy < 0.0) pa[i] = 4.0 + pa[i];
					// init idx
					idx[i] = i;
				}
				Sort(pa, idx, degree);
			}
			// save all of the indices
			for (uint32_t j = 1; j < degree - 1; j++) {
				index.push_back(vert_count);
				index.push_back(vert_count + j);
				index.push_back(vert_count + j + 1);
			}
			// save all of the verts
			for (uint32_t j = 0; j < degree; j++)
			{
				vertex.push_back((sorted ? vv[idx[j]] : vv[j]).x());
				vertex.push_back((sorted ? vv[idx[j]] : vv[j]).y());
				vertex.push_back((sorted ? vv[idx[j]] : vv[j]).z());
				vertex.push_back((sorted ? tt[idx[j]] : tt[j]).x());
				vertex.push_back((sorted ? tt[idx[j]] : tt[j]).y());
				vertex.push_back((sorted ? tt[idx[j]] : tt[j]).z());
				vert_count++;
			}

			size.push_back(degree);
		}
	}