コード例 #1
0
Point3 *CalcSphereCenter(Point3 *v0, Point3 *v1, Point3 *v2, Point3 *v3,Point3 *c)
{
 Vector3 d1, d2, d3;

 Plane p1,p2,p3;

 V3Add(v0, v1, &d1);
 V3Add(v0, v2, &d2);
 V3Add(v0, v3, &d3);

 d1.x/=2; d1.y/=2; d1.z/=2;
 d2.x/=2; d2.y/=2; d2.z/=2;
 d3.x/=2; d3.y/=2; d3.z/=2;

 V3Sub(v0, v1, &(p1.N));
 V3Sub(v0, v2, &(p2.N));
 V3Sub(v0, v3, &(p3.N));

 V3Normalize(&(p1.N));
 V3Normalize(&(p2.N));
 V3Normalize(&(p3.N));

 p1.off = V3Dot(&(p1.N), &d1);
 p2.off = V3Dot(&(p2.N), &d2);
 p3.off = V3Dot(&(p3.N), &d3);


 if(CalcPlaneInter(&p1, &p2, &p3, c)) return c;
				else  return NULL;

}
コード例 #2
0
Point3 *NormalToFace(Face *f, Point3 *n)
{
 Point3 t1,t2;

 V3Sub(f->v[1],f->v[0],&t1);
 V3Sub(f->v[2],f->v[0],&t2);
 V3Cross(&t1,&t2,n);

 return n;
}
コード例 #3
0
Point3 *NormalToFace(Point3 *v, Face *f, Point3 *n)
{
    Point3 t1,t2;

    V3Sub(&(v[f->v[1]]),&(v[f->v[0]]),&t1);
    V3Sub(&(v[f->v[2]]),&(v[f->v[0]]),&t2);
    V3Cross(&t1,&t2,n);

    return n;
}
コード例 #4
0
Plane *CalcPlane(Vector3 *p0, Vector3 *p1, Vector3 *p2, Plane *p )
{
 Vector3 v1,v2;
 Vector3 *N;
 N=&(p->N);


 V3Sub(p1,p0,&v1);
 V3Sub(p2,p0,&v2);
 V3Cross(&v1,&v2,N);
 if(N->x==0.0 && N->y==0.0 && N->z==0.0) return NULL;

 V3Normalize(N);

 p->off=V3Dot(N,p0);

 return p;
}
コード例 #5
0
Plane *CalcMiddlePlane(Point3 *p1, Point3 *p2, Plane *p)
{Point3 m0;

 V3Add(p1,p2,&m0);
 m0.x/=2;m0.y/=2;m0.z/=2;
 V3Sub(p1,p2,&(p->N));
 V3Normalize(&(p->N));
 p->off = V3Dot(&m0,&(p->N));

 return p;
}
コード例 #6
0
PX_FORCE_INLINE PxcSIMDSpatial propagateDrivenImpulse(const PxcFsRow& row, 
													  const PxcFsJointVectors& jv,
													  Vec3V& SZMinusQ, 
													  const PxcSIMDSpatial& Z,
													  const Vec3V& Q)
{
	typedef PxcArticulationFnsSimd<PxcArticulationFnsSimdBase> Fns;

	SZMinusQ = V3Sub(V3Add(Z.angular, V3Cross(Z.linear,jv.jointOffset)), Q);
	PxcSIMDSpatial result = Fns::translateForce(jv.parentOffset, Z - Fns::axisMultiply(row.DSI, SZMinusQ));

	return result;
}
コード例 #7
0
boolean PointBelongtoLine(Point3 *p, Line *l)
{
 Point3 temp;
 double t;

 V3Sub(p,&(l->Lu),&temp);

 t=temp.x/l->Lv.x;

 if(fabs(l->Lv.y*t-temp.y) <= EPSILON) return 1;

 return 0;
}
コード例 #8
0
ファイル: quad_gg.c プロジェクト: EduardMe/GraphicsGems
/*
** Search for an intersection between a facet and a ray
*/
boolean hit_ray_quad_gg(RAY *Ray, QUAD *Quad, HIT *Hit)
{
    Point3     Point;

    /* if the ray is parallel to the facet, there is no intersection */
    Hit->Distance = V3Dot (&(Ray->Vector), &(Quad->Normal));
    if (ABS(Hit->Distance) < EPSILON) return (FALSE);

    /* compute ray intersection with the plane of the facet */
    V3Sub (&(Quad->A), &(Ray->Point), &Point);
    Hit->Distance = V3Dot (&Point, &(Quad->Normal)) / Hit->Distance;
    V3_LIN (Hit->Point, Ray->Point, Hit->Distance, Ray->Vector);

    /* is the intersection point inside the facet */
    return (point_in_quad(Quad, Hit));
}
コード例 #9
0
void PxcLtbComputeJv(Vec3V* jv, const PxcFsData& m, const PxcSIMDSpatial* velocity)
{
	typedef PxcArticulationFnsSimd<PxcArticulationFnsSimdBase> Fns;
	const PxcLtbRow* rows = getLtbRows(m);
	const PxcFsRow* fsRows = getFsRows(m);
	const PxcFsJointVectors* jointVectors = getJointVectors(m);

	PX_UNUSED(rows);
	PX_UNUSED(fsRows);

	for(PxU32 i=1;i<m.linkCount;i++)
	{
		PxcSIMDSpatial pv = velocity[m.parent[i]], v = velocity[i];

		Vec3V parentOffset = V3Add(jointVectors[i].jointOffset, jointVectors[i].parentOffset);

		Vec3V k0v = V3Add(pv.linear, V3Cross(pv.angular, parentOffset)),
			  k1v = V3Add(v.linear,  V3Cross(v.angular,jointVectors[i].jointOffset));
		jv[i] = V3Sub(k0v, k1v);
	}
}
コード例 #10
0
ファイル: writerad.c プロジェクト: gmischler/Dxf2rad-Radout
extern int WriteCyl(FILE *fp, char *matName,
					int id, Cyl3 *cyls)
{
    int cylCnt = 0;
    Cyl3 *cyl;
    Vector3 dir;
	char *material = matName;

#ifdef DEBUG
    fprintf(stderr, "WriteCyl(%p, %p)\n", contblks, cyls);
#endif
    if (cyls == NULL)
        return 1;
    for (cyl = cyls; cyl; cyl = cyl->next) {
		if(matName == NULL) material = cyl->material;
		if(cyl->erad == 0.0) { /* it's a point/sphere */
			int sign;
			sign = (cyl->srad > 0 ? 1 : -1);
			if (sign > 0) {
				fprintf(fp, "\n%s sphere %s.%d.%d\n",
					material, material, id, cylCnt++);
			} else {
				fprintf(fp, "\n%s bubble %s.%d.%d\n",
					material, material, id, cylCnt++);
			}
			fprintf(fp, "0\n0\n4");
			fprintf(fp, "\t%.8g\t%.8g\t%.8g\t%.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z,
				fabs(cyl->srad));
		} else if (cyl->length != 0.0) { /* it's a cylinder or tube */
			if(cyl->length >= 0.0) {
				fprintf(fp, "\n%s cylinder %s.%d.%d\n",
					material, material, id, cylCnt++);
			} else {
				fprintf(fp, "\n%s tube %s.%d.%d\n",
					material, material, id, cylCnt++);
			}
            fprintf(fp, "0\n0\n7");
            fprintf(fp, "\t%.8g %.8g %.8g\n", cyl->svert.x,
                    cyl->svert.y, cyl->svert.z);
            fprintf(fp, "\t%.8g %.8g %.8g\n", cyl->evert.x,
                    cyl->evert.y, cyl->evert.z);
            fprintf(fp, "\t%.8g\n", cyl->srad);
            /* bottom cap */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z);
			if(cyl->length >= 0.0) {
	            (void)V3Normalize(V3Sub(&cyl->svert, &cyl->evert, &dir));
			} else {
	            (void)V3Normalize(V3Sub(&cyl->evert, &cyl->svert, &dir));
			}
            fprintf(fp, "\t%.8g %.8g %.8g\n", dir.x, dir.y, dir.z);
            fprintf(fp, "\t0 %.8g\n", cyl->srad);
			/* top cap */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->evert.x, cyl->evert.y, cyl->evert.z);
			if(cyl->length >= 0.0) {
	            (void)V3Normalize(V3Sub(&cyl->evert, &cyl->svert, &dir));
			} else {
	            (void)V3Normalize(V3Sub(&cyl->svert, &cyl->evert, &dir));
			}
            fprintf(fp, "\t%.8g %.8g %.8g\n", dir.x, dir.y, dir.z);
            fprintf(fp, "\t0 %.8g\n", cyl->srad);
        } else {            /* it's a ring */
            fprintf(fp, "\n%s ring %s.%d.%d\n",
				material, material, id, cylCnt++);
            fprintf(fp, "0\n0\n8");
            fprintf(fp, "\t%.8g %.8g %.8g\n",
				cyl->svert.x, cyl->svert.y, cyl->svert.z);
            (void)V3Normalize(&cyl->normal);
            fprintf(fp, "\t%.8g %.8g %.8g\n",
					cyl->normal.x, cyl->normal.y, cyl->normal.z);

            fprintf(fp, "\t0 %.8g\n", cyl->srad);
        }
    }
	Cyl3FreeList(cyls);
    return 1;
}
コード例 #11
0
void PxcArticulationHelper::getImpulseSelfResponse(const PxcFsData& matrix,
												   PxU32 linkID0,
												   const PxcSIMDSpatial& impulse0,
												   PxcSIMDSpatial& deltaV0,
												   PxU32 linkID1,
												   const PxcSIMDSpatial& impulse1,
												   PxcSIMDSpatial& deltaV1)
{
	PX_ASSERT(linkID0 != linkID1);

	const PxcFsRow* rows = getFsRows(matrix);
	const PxcFsRowAux* aux = getAux(matrix);
	const PxcFsJointVectors* jointVectors = getJointVectors(matrix);

	PX_UNUSED(aux);

	PxcSIMDSpatial& dV0 = deltaV0, 
				  & dV1 = deltaV1;

	// standard case: parent-child limit
	if(matrix.parent[linkID1] == linkID0)
	{
		const PxcFsRow& r = rows[linkID1];
		const PxcFsJointVectors& j = jointVectors[linkID1];

		Vec3V lZ = V3Neg(impulse1.linear),
			  aZ = V3Neg(impulse1.angular);

		Vec3V sz = V3Add(aZ, V3Cross(lZ, j.jointOffset));
		
		lZ = V3Sub(lZ, V3ScaleAdd(r.DSI[0].linear, V3GetX(sz), V3ScaleAdd(r.DSI[1].linear, V3GetY(sz), V3Scale(r.DSI[2].linear, V3GetZ(sz)))));
		aZ = V3Sub(aZ, V3ScaleAdd(r.DSI[0].angular, V3GetX(sz), V3ScaleAdd(r.DSI[1].angular, V3GetY(sz), V3Scale(r.DSI[2].angular, V3GetZ(sz)))));

		aZ = V3Add(aZ, V3Cross(j.parentOffset, lZ));

		lZ = V3Sub(impulse0.linear, lZ);
		aZ = V3Sub(impulse0.angular, aZ);

		dV0 = getImpulseResponseSimd(matrix, linkID0, lZ, aZ);

		Vec3V aV = dV0.angular;
		Vec3V lV = V3Sub(dV0.linear, V3Cross(j.parentOffset, aV));

		Vec3V n = V3Add(V3Merge(V3Dot(r.DSI[0].linear, lV),  V3Dot(r.DSI[1].linear, lV),  V3Dot(r.DSI[2].linear, lV)),
						V3Merge(V3Dot(r.DSI[0].angular, aV), V3Dot(r.DSI[1].angular, aV), V3Dot(r.DSI[2].angular, aV)));

		n = V3Add(n, M33MulV3(r.D, sz));
		lV = V3Sub(lV, V3Cross(j.jointOffset, n));
		aV = V3Sub(aV, n);

		dV1 = PxcSIMDSpatial(lV, aV);
	}
	else
		getImpulseResponseSlow(matrix, linkID0, impulse0, deltaV0, linkID1, impulse1, deltaV1);

#if PXC_ARTICULATION_DEBUG_VERIFY
	PxcSIMDSpatial dV0_, dV1_;
	PxcFsGetImpulseSelfResponse(matrix, linkID0, impulse0, dV0_, linkID1, impulse1, dV1_);

	PX_ASSERT(almostEqual(dV0_, dV0, 1e-3f));
	PX_ASSERT(almostEqual(dV1_, dV1, 1e-3f));
#endif
}
コード例 #12
0
ファイル: demo-TextGrid.c プロジェクト: AleDel/recipes
static MeshPod CreateTrefoil()
{
    const int Slices = 256;
    const int Stacks = 32;
    const int VertexCount = Slices * Stacks;
    const int IndexCount = VertexCount * 6;

    MeshPod mesh;
    glGenVertexArrays(1, &mesh.Vao);
    glBindVertexArray(mesh.Vao);

    // Create a buffer with interleaved positions and normals
    if (true) {
        Vertex verts[VertexCount];
        Vertex* pVert = &verts[0];
        float ds = 1.0f / Slices;
        float dt = 1.0f / Stacks;

        // The upper bounds in these loops are tweaked to reduce the
        // chance of precision error causing an incorrect # of iterations.
        for (float s = 0; s < 1 - ds / 2; s += ds) {
            for (float t = 0; t < 1 - dt / 2; t += dt) {
                const float E = 0.01f;
                Vector3 p = EvaluateTrefoil(s, t);
                Vector3 u = V3Sub(EvaluateTrefoil(s + E, t), p);
                Vector3 v = V3Sub(EvaluateTrefoil(s, t + E), p);
                Vector3 n = V3Normalize(V3Cross(u, v));
                pVert->Position = p;
                pVert->Normal = n;
                ++pVert;
            }
        }

        pezCheck(pVert - &verts[0] == VertexCount, "Tessellation error.");

        GLuint vbo;
        GLsizeiptr size = sizeof(verts);
        const GLvoid* data = &verts[0].Position.x;
        GLenum usage = GL_STATIC_DRAW;
        glGenBuffers(1, &vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferData(GL_ARRAY_BUFFER, size, data, usage);
    }

    // Create a buffer of 16-bit indices
    if (true) {
        GLushort inds[IndexCount];
        GLushort* pIndex = &inds[0];
        GLushort n = 0;
        for (GLushort i = 0; i < Slices; i++) {
            for (GLushort j = 0; j < Stacks; j++) {
                *pIndex++ = (n + j + Stacks) % VertexCount;
                *pIndex++ = n + (j + 1) % Stacks;
                *pIndex++ = n + j;
                
                *pIndex++ = (n + (j + 1) % Stacks + Stacks) % VertexCount;
                *pIndex++ = (n + (j + 1) % Stacks) % VertexCount;
                *pIndex++ = (n + j + Stacks) % VertexCount;
            }
            n += Stacks;
        }

        pezCheck(n == VertexCount, "Tessellation error.");
        pezCheck(pIndex - &inds[0] == IndexCount, "Tessellation error.");

        GLuint handle;
        GLsizeiptr size = sizeof(inds);
        const GLvoid* data = &inds[0];
        GLenum usage = GL_STATIC_DRAW;
        glGenBuffers(1, &handle);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, usage);
    }

    mesh.VertexCount = VertexCount;
    mesh.IndexCount = IndexCount;

    glVertexAttribPointer(a("Position"), 3, GL_FLOAT, GL_FALSE, 24, 0);
    glVertexAttribPointer(a("Normal"), 3, GL_FLOAT, GL_FALSE, 24, offset(12));
    glEnableVertexAttribArray(a("Position"));
    glEnableVertexAttribArray(a("Normal"));

    pezCheck(OpenGLError);
    return mesh;
}
コード例 #13
0
bool pcmContactCapsuleConvex(GU_CONTACT_METHOD_ARGS)
{
	PX_UNUSED(renderOutput);


	const PxConvexMeshGeometryLL& shapeConvex = shape1.get<const PxConvexMeshGeometryLL>();
	const PxCapsuleGeometry& shapeCapsule = shape0.get<const PxCapsuleGeometry>();

	PersistentContactManifold& manifold = cache.getManifold();

	Ps::prefetchLine(shapeConvex.hullData);

		
	PX_ASSERT(transform1.q.isSane());
	PX_ASSERT(transform0.q.isSane());

	const Vec3V zeroV = V3Zero();

	const Vec3V vScale = V3LoadU_SafeReadW(shapeConvex.scale.scale);	// PT: safe because 'rotation' follows 'scale' in PxMeshScale

	const FloatV contactDist = FLoad(params.mContactDistance);
	const FloatV capsuleHalfHeight = FLoad(shapeCapsule.halfHeight);
	const FloatV capsuleRadius = FLoad(shapeCapsule.radius);
	const ConvexHullData* hullData =shapeConvex.hullData;
	
	//Transfer A into the local space of B
	const PsTransformV transf0 = loadTransformA(transform0);
	const PsTransformV transf1 = loadTransformA(transform1);
	const PsTransformV curRTrans(transf1.transformInv(transf0));
	const PsMatTransformV aToB(curRTrans);
	

	const FloatV convexMargin = Gu::CalculatePCMConvexMargin(hullData, vScale);
	const FloatV capsuleMinMargin = Gu::CalculateCapsuleMinMargin(capsuleRadius);
	const FloatV minMargin = FMin(convexMargin, capsuleMinMargin);
	
	const PxU32 initialContacts = manifold.mNumContacts;
	const FloatV projectBreakingThreshold = FMul(minMargin, FLoad(1.25f));
	const FloatV refreshDist = FAdd(contactDist, capsuleRadius);

	manifold.refreshContactPoints(aToB,  projectBreakingThreshold, refreshDist);

	//ML: after refreshContactPoints, we might lose some contacts
	const bool bLostContacts = (manifold.mNumContacts != initialContacts);

	GjkStatus status = manifold.mNumContacts > 0 ? GJK_UNDEFINED : GJK_NON_INTERSECT;

	Vec3V closestA(zeroV), closestB(zeroV), normal(zeroV); // from a to b
	const FloatV zero = FZero();
	FloatV penDep = zero;

	PX_UNUSED(bLostContacts);
	if(bLostContacts || manifold.invalidate_SphereCapsule(curRTrans, minMargin))
	{
		const bool idtScale = shapeConvex.scale.isIdentity();

		manifold.setRelativeTransform(curRTrans);
		const QuatV vQuat = QuatVLoadU(&shapeConvex.scale.rotation.x);  
		ConvexHullV convexHull(hullData, zeroV, vScale, vQuat, idtScale);
		convexHull.setMargin(zero);
	
		//transform capsule(a) into the local space of convexHull(b)
		CapsuleV capsule(aToB.p, aToB.rotate(V3Scale(V3UnitX(), capsuleHalfHeight)), capsuleRadius);
	
		LocalConvex<CapsuleV> convexA(capsule);
		const Vec3V initialSearchDir = V3Sub(capsule.getCenter(), convexHull.getCenter());
		if(idtScale)
		{
			LocalConvex<ConvexHullNoScaleV> convexB(*PX_CONVEX_TO_NOSCALECONVEX(&convexHull));

			status = gjkPenetration<LocalConvex<CapsuleV>, LocalConvex<ConvexHullNoScaleV> >(convexA, convexB, initialSearchDir, contactDist, closestA, closestB, normal, penDep, 
				manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, true);
		}
		else
		{
			LocalConvex<ConvexHullV> convexB(convexHull);
			status = gjkPenetration<LocalConvex<CapsuleV>, LocalConvex<ConvexHullV> >(convexA, convexB, initialSearchDir, contactDist, closestA, closestB, normal, penDep, 
				manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, true);

		}     

		Gu::PersistentContact* manifoldContacts = PX_CP_TO_PCP(contactBuffer.contacts);
		bool doOverlapTest = false;
		if(status == GJK_NON_INTERSECT)
		{
			return false;
		}
		else if(status == GJK_DEGENERATE)
		{
			return fullContactsGenerationCapsuleConvex(capsule, convexHull, aToB, transf0, transf1, manifoldContacts, contactBuffer, idtScale, manifold, normal, 
				closestB, convexHull.getMargin(), contactDist, true, renderOutput, FLoad(params.mToleranceLength));
		}
		else 
		{
			const FloatV replaceBreakingThreshold = FMul(minMargin, FLoad(0.05f));

			if(status == GJK_CONTACT)
			{
				const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
				const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
				//Add contact to contact stream
				manifoldContacts[0].mLocalPointA = localPointA;
				manifoldContacts[0].mLocalPointB = closestB;
				manifoldContacts[0].mLocalNormalPen = localNormalPen;

				//Add contact to manifold
				manifold.addManifoldPoint2(localPointA, closestB, localNormalPen, replaceBreakingThreshold);
			}
			else
			{
				PX_ASSERT(status == EPA_CONTACT);
				
				if(idtScale)
				{
					LocalConvex<ConvexHullNoScaleV> convexB(*PX_CONVEX_TO_NOSCALECONVEX(&convexHull));

					status= Gu::epaPenetration(convexA, convexB, manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,
					closestA, closestB, normal, penDep, true);
				}
				else
				{
					LocalConvex<ConvexHullV> convexB(convexHull);
					status= Gu::epaPenetration(convexA, convexB,  manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,
					closestA, closestB, normal, penDep, true);
				}
				
				
				if(status == EPA_CONTACT)
				{
					const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
					const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
					//Add contact to contact stream
					manifoldContacts[0].mLocalPointA = localPointA;
					manifoldContacts[0].mLocalPointB = closestB;
					manifoldContacts[0].mLocalNormalPen = localNormalPen;

					//Add contact to manifold
					manifold.addManifoldPoint2(localPointA, closestB, localNormalPen, replaceBreakingThreshold);
					

				}
				else
				{
					doOverlapTest = true;   
				}
			}

		
			if(initialContacts == 0 || bLostContacts || doOverlapTest)
			{
				return fullContactsGenerationCapsuleConvex(capsule, convexHull, aToB, transf0, transf1, manifoldContacts, contactBuffer, idtScale, manifold, normal, 
					closestB, convexHull.getMargin(), contactDist, doOverlapTest, renderOutput, FLoad(params.mToleranceLength));
			}
			else
			{
				//This contact is either come from GJK or EPA
				normal = transf1.rotate(normal);
				manifold.addManifoldContactsToContactBuffer(contactBuffer, normal, transf0, capsuleRadius, contactDist);
#if	PCM_LOW_LEVEL_DEBUG
				manifold.drawManifold(*renderOutput, transf0, transf1);
#endif
				return true;
			}
		}	
	}
	else if (manifold.getNumContacts() > 0)
	{
		normal = manifold.getWorldNormal(transf1);
		manifold.addManifoldContactsToContactBuffer(contactBuffer, normal, transf0, capsuleRadius, contactDist);
#if	PCM_LOW_LEVEL_DEBUG
		manifold.drawManifold(*renderOutput, transf0, transf1);
#endif
		return true;
	}
	return false;
}
コード例 #14
0
ファイル: Blob.c プロジェクト: oleavitt/gem
Object *Ray_MakeBlob(PARAMS *par)
{
	Object *obj;
	int token, num_elems, i;
	PARAMS *p;
	BlobData *b;
	Bloblet *be, *new_be, *hemi1, *hemi2, *cyl;
	static Vec3 pt;


	if((obj = NewObject()) == NULL)
		return NULL;

	/* evaluate parameters */
	p = par;
	while(1)
	{
		Eval_Params(p);
		for(i = p->more; i >= 0; i--)
			p = p->next;
		if(p == NULL)
			break;
		p = p->next;   /* skip element type delimiter */
	}

	/* Allocate the main blob data structure... */
	b = (BlobData *)Malloc(sizeof(BlobData));
	b->nrefs = 1;

	/* Get threshold... */
	b->threshold = par->V.x;
	b->solver = 0;
	b->bound = NULL;

	/* Get blob elements... */
	be = NULL;
	num_elems = 0;
	while((par = par->next) != NULL)
	{
		token = par->type;
		/* Get blob element... */
		switch(token)
		{
			case BLOB_SPHERE:
			case BLOB_PLANE:
			case BLOB_CYLINDER:
				for(i = 0; i < 3; i++)
				{
					/* Allocate a "Bloblet" structure. */
					new_be = (Bloblet *)Malloc(sizeof(Bloblet));
					new_be->next = NULL;
					new_be->field = 1.0; /* Default field strength, if not given. */
					if(be == NULL)  /* First one, start the list. */
					{
						be = new_be;
						b->elems = be;
					}
					else   /* Add to the list. */
					{
						be->next = new_be;
						be = be->next;
					}
					num_elems++;

					if(token != BLOB_CYLINDER)
						break;

					/* Save references to the hemisphere sub-elements for cylinder. */
					if(i == 0) cyl = new_be;
					else if(i == 1) hemi1 = new_be;
					else hemi2 = new_be;
				}
				par = par->next;
				break;
			default:
				break;
		}

		/* Get parameters... */
		switch(token)
		{
			case BLOB_SPHERE:
				V3Copy(&be->loc, &par->V);
				par = par->next;
				be->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					be->field = par->V.x;
				}

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				be->rsq = be->rad * be->rad;
				be->r2 = - (2.0 * be->field) / be->rsq;
				be->r4 = be->field / (be->rsq * be->rsq);
				be->type = BLOB_SPHERE;
				continue;

			case BLOB_PLANE:
				V3Copy(&be->loc, &par->V);
				par = par->next;
				V3Copy(&be->dir, &par->V);
				par = par->next;
				be->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					be->field = par->V.x;
				}

				/* Normalize the normal vector. */
				/* Invalid normals should be checked for during parse. */
				V3Normalize(&be->dir);

				/* Get "d" coeff. for plane that bounds plane's interval. */
				pt.x = be->dir.x * be->rad;
				pt.y = be->dir.y * be->rad;
				pt.z = be->dir.z * be->rad;
				be->d1 = -V3Dot(&be->dir, &pt);

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				be->rsq = be->rad * be->rad;
				be->r2 = - (2.0 * be->field) / be->rsq;
				be->r4 = be->field / (be->rsq * be->rsq);
				be->type = BLOB_PLANE;
				continue;

			case BLOB_CYLINDER:
				V3Copy(&cyl->loc, &par->V);
				par = par->next;
				V3Copy(&pt, &par->V);   /* end point for cylinder */
				par = par->next;
				cyl->rad = par->V.x;
				if(par->more) /* Optional field strength was specified, also. */
				{
					par = par->next;
					cyl->field = par->V.x;
				}

				/* Pre-compute constants for the density eq. in standard form. */
				/* Radii that are too small shoud be checked for during parse. */
				cyl->rsq = cyl->rad * cyl->rad;
				cyl->r2 = -( 2.0 * cyl->field) / cyl->rsq;
				cyl->r4 = cyl->field / (cyl->rsq * cyl->rsq);

				/* Get offset vector of cylinder. */
				V3Sub(&cyl->d, &pt, &cyl->loc);
				/* Get cylinder length squared & length, while we're at it... */
				/* Zero length offset vectors shoud be checked for during parse. */
				cyl->lsq = V3Dot(&cyl->d, &cyl->d);
				cyl->len = sqrt(cyl->lsq);
				V3Copy(&cyl->dir, &cyl->d);
				V3Normalize(&cyl->dir);

				/* Get "d" coeffs. for planes at cylinder ends. */
				cyl->d1 = -V3Dot(&cyl->dir, &cyl->loc);
				cyl->d2 = -V3Dot(&cyl->dir, &pt);

				/* Precompute location dot offset_vector constant. */
				cyl->l_dot_d = V3Dot(&cyl->loc, &cyl->d);

				cyl->type = BLOB_CYLINDER;

				/* Set up the hemispheres for the ends of the cylinder. */
				V3Copy(&hemi1->loc, &cyl->loc);
				V3Sub(&hemi1->dir, &pt, &hemi1->loc);
				V3Normalize(&hemi1->dir);
				hemi1->rad = cyl->rad;
				hemi1->rsq = cyl->rsq;
				hemi1->field = cyl->field;
				hemi1->r2 = cyl->r2;
				hemi1->r4 = cyl->r4;
				hemi1->type = BLOB_HEMISPHERE;

				V3Copy(&hemi2->loc, &pt);
				V3Sub(&hemi2->dir, &cyl->loc, &hemi2->loc);
				V3Normalize(&hemi2->dir);
				hemi2->rad = cyl->rad;
				hemi2->rsq = cyl->rsq;
				hemi2->field = cyl->field;
				hemi2->r2 = cyl->r2;
				hemi2->r4 = cyl->r4;
				hemi2->type = BLOB_HEMISPHERE;
				continue;

			default:
				break;
		}
		break;
	}

	/*
	 * Blobs must have at least one element, this should be checked
	 * for during parse.
	 */
	/* Some assembly required... */
	b->hits = (BlobHit **)Malloc(sizeof(BlobHit *) * num_elems * 2);
	for (i = 0; i < num_elems * 2; i++)
		b->hits[i] = (BlobHit *)Malloc(sizeof(BlobHit));

	obj->data.blob = b;
	obj->procs = &blob_procs;

	return obj;
}
コード例 #15
0
ファイル: Blob.c プロジェクト: oleavitt/gem
int Ray_BlobAddCylinder(Object *obj, Vec3 *pt1, Vec3 *pt2,
	double radius, double field)
{
	Bloblet *hemi1, *hemi2, *cyl;
	BlobData *blob = obj->data.blob;

	assert(obj != NULL);
	assert(blob != NULL);

	/*
	 * Cylindrical fields consist of three Bloblet elements.
	 * A cylinder and two hemispheres.
	 */						 

	/* Allocate the elements. */
	if ((cyl = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
		return 0;
	if ((hemi1 = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
	{
		Free(cyl, sizeof(Bloblet));
		return 0;
	}
	if ((hemi2 = (Bloblet *)Malloc(sizeof(Bloblet))) == NULL)
	{
		Free(hemi1, sizeof(Bloblet));
		Free(cyl, sizeof(Bloblet));
		return 0;
	}

	/* Link them together. */
	cyl->next = hemi1;
	hemi1->next = hemi2;
	hemi2->next = NULL;

	/* Store the origin point, radius and field strength for cylinder. */
	V3Copy(&cyl->loc, pt1);
	cyl->rad = radius;
	cyl->field = field;

	/*
	 * Pre-compute constants for the density eq. in standard form.
	 * Radii that are too small should be checked for during parse.
	 */
	cyl->rsq = cyl->rad * cyl->rad;
	cyl->r2 = -( 2.0 * cyl->field) / cyl->rsq;
	cyl->r4 = cyl->field / (cyl->rsq * cyl->rsq);

	/* Get offset vector of cylinder from the given end point. */
	V3Sub(&cyl->d, pt2, &cyl->loc);

	/*
	 * Get cylinder length squared & length, while we're at it...
	 * Zero length offset vectors should be checked for during parse.
	 */
	cyl->lsq = V3Dot(&cyl->d, &cyl->d);
	cyl->len = sqrt(cyl->lsq);
	V3Copy(&cyl->dir, &cyl->d);
	V3Normalize(&cyl->dir);

	/* Get "d" coeffs. for planes at cylinder ends. */
	cyl->d1 = -V3Dot(&cyl->dir, &cyl->loc);
	cyl->d2 = -V3Dot(&cyl->dir, pt2);

	/* Precompute location dot offset_vector constant. */
	cyl->l_dot_d = V3Dot(&cyl->loc, &cyl->d);

	cyl->type = BLOB_CYLINDER;

	/* Set up the hemispheres for the ends of the cylinder. */
	V3Copy(&hemi1->loc, &cyl->loc);
	V3Sub(&hemi1->dir, pt2, &hemi1->loc);
	V3Normalize(&hemi1->dir);
	hemi1->rad = cyl->rad;
	hemi1->rsq = cyl->rsq;
	hemi1->field = cyl->field;
	hemi1->r2 = cyl->r2;
	hemi1->r4 = cyl->r4;
	hemi1->type = BLOB_HEMISPHERE;

	V3Copy(&hemi2->loc, pt2);
	V3Sub(&hemi2->dir, &cyl->loc, &hemi2->loc);
	V3Normalize(&hemi2->dir);
	hemi2->rad = cyl->rad;
	hemi2->rsq = cyl->rsq;
	hemi2->field = cyl->field;
	hemi2->r2 = cyl->r2;
	hemi2->r4 = cyl->r4;
	hemi2->type = BLOB_HEMISPHERE;

	/*
	 * Finally, add the three new elements that make up the cylinder
	 * element to the blob.
	 */
	if (blob->elems != NULL)
	{
		Bloblet *lastbe;
		for (lastbe = blob->elems; lastbe->next != NULL; lastbe = lastbe->next)
			; /* Seek last element added to list. */
		/* Append our new one. */
		lastbe->next = cyl;
	}
	else
		blob->elems = cyl;

	return 1;
}