Example #1
0
File: mmgs1.c Project: XL64/mmg
/* check if splitting edge i of k is ok */
int chkspl(pMesh mesh,pSol met,int k,int i) {
    pTria    pt,pt1;
    pPoint   ppt;
    pGeom    go;
    Bezier   b;
    double   s,uv[2],o[3],no[3],to[3];
    int     *adja,jel,ip,ier;
    char     i1,i2,j,jj,j2;

    if ( mesh->ng > mesh->ngmax-2 )  return(0);
    pt = &mesh->tria[k];
    i1 = inxt[i];
    i2 = iprv[i];
    if ( MS_SIN(pt->tag[i1]) || MS_SIN(pt->tag[i2]) )  return(0);
    adja = &mesh->adja[3*(k-1)+1];
    jel  = adja[i] / 3;
    if ( jel ) {
        j   = adja[i] % 3;
        jj  = inxt[j];
        j2  = iprv[j];
        pt1 = &mesh->tria[jel];
        if ( MS_SIN(pt1->tag[jj]) || MS_SIN(pt1->tag[j2]) )  return(0);
    }

    ier = bezierCP(mesh,k,&b);
    assert(ier);

    /* create midedge point */
    uv[0] = 0.5;
    uv[1] = 0.5;
    if (i == 1)         uv[0] = 0.0;
    else if ( i == 2 )  uv[1] = 0.0;

    ier = bezierInt(&b,uv,o,no,to);
    assert(ier);
    ip = newPt(mesh,o,MS_EDG(pt->tag[i]) ? to : no);
    assert(ip);

    if ( MS_EDG(pt->tag[i]) ) {
        ++mesh->ng;
        ppt = &mesh->point[ip];
        ppt->ig  = mesh->ng;
        go = &mesh->geom[mesh->ng];
        memcpy(go->n1,no,3*sizeof(double));
    }
    s = 0.5;

    intmet(mesh,met,k,i,ip,s);

    return(ip);
}
Example #2
0
void JSpline::GeneratePixels()
{
	float x, y;

	float inc = SMALL_NUMBER;

	mPixels.clear();

	x = mMidPoints[1].x;
	y = mMidPoints[1].y;

	Point newPt(x, y);
	Point extraPt;

	mPixels.push_back(newPt);

	for (int n=0; n < (int)mMidPoints.size()-3; n++)
	{
		float t = inc;
		while (t <= 1.0f)
		{
			PointOnCurve(newPt, t, mMidPoints[n], mMidPoints[n+1], mMidPoints[n+2], mMidPoints[n+3]);

			float dx = newPt.x-x;
			float dy = newPt.y-y;

			float dist = sqrtf(dx*dx + dy*dy);
			if (dist >= MID_POINT_THRESHOLD)
			{
				//
				//extraPt.x = (newPt.x+x)/2;
				//extraPt.y = (newPt.y+y)/2;
				//mPixels.push_back(extraPt);
				//
				mPixels.push_back(newPt);
				x = newPt.x;
				y = newPt.y;
			}

			t += inc;
		}
	}


	mCount = mPixels.size();

}
Example #3
0
particle *floodfill(matrix *mat, int id, int x, int y){

	particle *newparticle;
	int *current_id;
	if((current_id = calloc(1,sizeof(int)))==NULL){
		fprintf(stderr, "Out of memory error\n");
		exit(1);
	}
	*current_id = 1;
	newparticle = newParticle(id);
	pt *newpt;
	newpt = newPt(*current_id,x,y);
	newparticle->spt = newpt;
	newparticle->ept = newpt;
	newparticle->size++;
	floodfill_work(mat,newparticle,x,y,current_id);
	free(current_id);
	return newparticle;
}
Example #4
0
void ManifoldContactAddResult::AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
{
	if (depth > m_manifoldPtr->GetContactBreakingTreshold())
		return;


	SimdVector3 pointA = pointInWorld + normalOnBInWorld * depth;
	SimdVector3 localA = m_transAInv(pointA );
	SimdVector3 localB = m_transBInv(pointInWorld);
	ManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);

	int insertIndex = m_manifoldPtr->GetCacheEntry(newPt);
	if (insertIndex >= 0)
	{
		m_manifoldPtr->ReplaceContactPoint(newPt,insertIndex);
	} else
	{
		m_manifoldPtr->AddManifoldPoint(newPt);
	}
}
Example #5
0
	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
	{
		bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
		btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
		btVector3 localA;
		btVector3 localB;
		if (isSwapped)
		{
			localA = m_rootTransB.invXform(pointA );
			localB = m_rootTransA.invXform(pointInWorld);
		} else
		{
			localA = m_rootTransA.invXform(pointA );
			localB = m_rootTransB.invXform(pointInWorld);
		}
		
		btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
		newPt.m_positionWorldOnA = pointA;
		newPt.m_positionWorldOnB = pointInWorld;
		
	   //BP mod, store contact triangles.
		if (isSwapped)
		{
			newPt.m_partId0 = m_partId1;
			newPt.m_partId1 = m_partId0;
			newPt.m_index0  = m_index1;
			newPt.m_index1  = m_index0;
		} else
		{
			newPt.m_partId0 = m_partId0;
			newPt.m_partId1 = m_partId1;
			newPt.m_index0  = m_index0;
			newPt.m_index1  = m_index1;
		}

		//experimental feature info, for per-triangle material etc.
		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
		m_resultCallback.addSingleResult(newPt,obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);

	}
Example #6
0
void floodfill_work(matrix *mat, particle *part, int x, int y, int *id){
	
	
	if(mat->vals[x][y]==0){
		return;
	}
	
	pt *newpt;
	(*id)++;
	newpt = newPt(*id,x,y);
	pushPt(newpt, part);
	part->size++;
	
	mat->vals[x][y] = 0;
	if(!(x==0) && !(y==0)){
		floodfill_work( mat, part, x-1, y-1, id);
	}
	if(!(x==mat->width-1) && !(y==mat->height-1)){
		floodfill_work( mat, part, x+1, y+1, id);
	}
	if(!(x==0) && !(y==mat->height-1)){
		floodfill_work( mat, part, x-1, y+1, id);
	}
	if(!(x==(mat->width-1)) && !(y==0)){
		floodfill_work( mat, part, x+1, y-1, id);
	}
	if(!(x==0)){
		floodfill_work( mat, part,x-1, y, id);
	}
	if(!(x==mat->width-1)){
		floodfill_work( mat, part,x+1,y, id);
	}
	if(!(y==0)){
		floodfill_work( mat, part,x,y-1, id);
	}
	if(!(y==mat->height-1)){
		floodfill_work( mat, part,x, y+1, id);
	}
	return;

}
Example #7
0
vector<margBlob> margBlobInterpolator::interpolate(margBlob& blob1, margBlob& blob2) {
	
	//  Calculate path's function
    
	int delta_x = (blob2.centroid.x-blob1.centroid.x);
	int delta_y = (blob2.centroid.y-blob1.centroid.y);
	
	double path_angle = (double)delta_y/(double)delta_x;
	double path_orig = (double)blob1.centroid.y - ((double)path_angle * (double)blob1.centroid.x);
	
	int numSteps = ofDist(blob1.centroid.x, blob1.centroid.y, blob2.centroid.x, blob2.centroid.y);
	double step_x = (double)delta_x/(double)numSteps;
	double step_y = (double)delta_y/(double)numSteps;
	
	vector<margBlob> interBlobs(numSteps+2);
	vector< vector<float> > transPts;
	
	
	//  Normalize shape coordinates
	
	vector<ofPoint> blob1_normPts(blob1.nPts);
	vector<ofPoint> blob2_normPts(blob2.nPts);
	
	for(int p = 0; p < blob1.nPts; p++) {
		blob1_normPts[p] = normCart(blob1.pts[p].x, blob1.pts[p].y, blob1.centroid.x, blob1.centroid.y); 
	}
	
	for(int p = 0; p < blob2.nPts; p++) {
		blob2_normPts[p] = normCart(blob2.pts[p].x, blob2.pts[p].y, blob2.centroid.x, blob2.centroid.y);
	}
	
	//  Compare number of vertices and trigger the appropriate methods in each case
	
	// If both shapes have the same number of vertices
	
	if(blob1.nPts == blob2.nPts) {
		
		//  Set transformation paths
		
		for(int p = 0; p < blob1.nPts; p++) {
			int delta_pt_x = round(blob2_normPts[p].x-blob1_normPts[p].x);
			int delta_pt_y = round(blob2_normPts[p].y-blob1_normPts[p].y);
			float step_pt_x= (float)((double)delta_pt_x/(double)numSteps);
			float step_pt_y= (float)((double)delta_pt_y/(double)numSteps);
			float curPts[] = {blob1_normPts[p].x, blob1_normPts[p].y, step_pt_x, step_pt_y};
			vector<float> newPt (curPts, curPts + sizeof(curPts) / sizeof(float));
			transPts.push_back(newPt);
			newPt.clear();
		}
	}
	
	else if (blob1.nPts > blob2.nPts) {
		
		int diff = blob1.nPts - blob2.nPts;
		int aver_diff = 0;
		int amt_aver  = 1;
		
		if (diff <= blob2.nPts) {
			aver_diff = floor((float)blob2.nPts / (float)diff);
		}
		else {
			aver_diff = 1;
			amt_aver = ceil((float)diff / (float)blob2.nPts);      
		}
		
		int addedExtraPts = 0;
		
		for(int p = 0; p < blob2.nPts; p++) {      
			
			int curSh1Pt = p + addedExtraPts;
			
			int curSh2Pt = p;
			if(curSh2Pt >= blob2.nPts) { curSh2Pt -= blob2.nPts; }
			
			int prevSh2Pt = curSh2Pt - 1;
			if(prevSh2Pt < 0) { prevSh2Pt += blob2.nPts; }
			
			if((p+1) % aver_diff == 0 && addedExtraPts < diff) {
				for(int amt = 0; amt < amt_aver; amt ++) {
					if (addedExtraPts < diff) {
						int final_pt_x = round(((blob2_normPts[curSh2Pt].x - blob2_normPts[prevSh2Pt].x) / 2.0) + blob2_normPts[prevSh2Pt].x);  //Stablish final coord for extra point in shape 1
						int final_pt_y = round(((blob2_normPts[curSh2Pt].y - blob2_normPts[prevSh2Pt].y) / 2.0) + blob2_normPts[prevSh2Pt].y);  //as the middle of one of the sides of shape 2
						int delta_pt_x = round(final_pt_x - blob1_normPts[curSh1Pt].x);
						int delta_pt_y = round(final_pt_y - blob1_normPts[curSh1Pt].y);
						float step_pt_x = (float)((double)delta_pt_x/(double)numSteps);
						float step_pt_y = (float)((double)delta_pt_y/(double)numSteps);
						float curPts[] = {blob1_normPts[curSh1Pt].x, blob1_normPts[curSh1Pt].y, step_pt_x, step_pt_y};
						vector<float> newPt (curPts, curPts + sizeof(curPts) / sizeof(float));
						transPts.push_back(newPt);
						newPt.clear();
						addedExtraPts ++;
						curSh1Pt ++;
					}
				}
			}
			
			if (curSh1Pt < blob1.nPts) {
				int delta_pt_x = round(blob2_normPts[curSh2Pt].x-blob1_normPts[curSh1Pt].x);
				int delta_pt_y = round(blob2_normPts[curSh2Pt].y-blob1_normPts[curSh1Pt].y);
				float step_pt_x= (float)((double)delta_pt_x/(double)numSteps);
				float step_pt_y= (float)((double)delta_pt_y/(double)numSteps);
				float curPts[] = {blob1_normPts[curSh1Pt].x, blob1_normPts[curSh1Pt].y, step_pt_x, step_pt_y};
				vector<float> newPt (curPts, curPts + sizeof(curPts) / sizeof(float));
				transPts.push_back(newPt);
				newPt.clear();
			}
		}  
	}
	
	else if (blob1.nPts < blob2.nPts) {
		
		int diff = blob2.nPts - blob1.nPts;
		int aver_diff = 0;
		int amt_aver = 1;
		
		if (diff <= blob1.nPts) {
			aver_diff = floor((float)blob1.nPts / (float)diff);      
		}
		else {
			aver_diff = 1;
			amt_aver = ceil((float)diff / (float)blob1.nPts);  
		}
		
		int removedExtraPts = 0;
		
		for(int p = 0; p < blob1.nPts; p++) { 
			
			int curSh2Pt = p + removedExtraPts;
			if(curSh2Pt >= blob2.nPts) { curSh2Pt -= blob2.nPts;}
			
			int curSh1Pt = p;
			
			int prevSh1Pt = curSh1Pt - 1;
			if(prevSh1Pt < 0) { prevSh1Pt += blob1.nPts;}
			
			if((p+1) % aver_diff == 0 && removedExtraPts < diff) { 
				for(int amt = 0; amt < amt_aver; amt++) {
					if (removedExtraPts < diff) {
						int init_pt_x = round((blob1_normPts[curSh1Pt].x - blob1_normPts[prevSh1Pt].x)/2.0 + blob1_normPts[prevSh1Pt].x);  //Stablish initial coord for extra point of shape 2
						int init_pt_y = round((blob1_normPts[curSh1Pt].y - blob1_normPts[prevSh1Pt].y)/2.0 + blob1_normPts[prevSh1Pt].y);   //as the middle of one of the sides of shape 1
						int delta_pt_x = round(blob2_normPts[curSh2Pt].x-init_pt_x);
						int delta_pt_y = round(blob2_normPts[curSh2Pt].y-init_pt_y);
						float step_pt_x= (float)((double)delta_pt_x/(double)numSteps);
						float step_pt_y= (float)((double)delta_pt_y/(double)numSteps);
						float curPts[] = {init_pt_x, init_pt_y, step_pt_x, step_pt_y};
						vector<float> newPt (curPts, curPts + sizeof(curPts) / sizeof(float));
						transPts.push_back(newPt);
						newPt.clear();
						removedExtraPts ++;
						curSh2Pt++;
						if(curSh2Pt >= blob2.pts.size()) { curSh2Pt -= blob2.pts.size();}
					}
				}
			}
			if (curSh2Pt < blob2.nPts) {
				int delta_pt_x = round(blob2_normPts[curSh2Pt].x-blob1_normPts[curSh1Pt].x);
				int delta_pt_y = round(blob2_normPts[curSh2Pt].y-blob1_normPts[curSh1Pt].y);
				float step_pt_x= (float)((double)delta_pt_x/(double)numSteps);
				float step_pt_y= (float)((double)delta_pt_y/(double)numSteps);
				float curPts[] = {blob1_normPts[curSh1Pt].x, blob1_normPts[curSh1Pt].y, step_pt_x, step_pt_y};
				vector<float> newPt (curPts, curPts + sizeof(curPts) / sizeof(float));
				transPts.push_back(newPt);
				newPt.clear();
			}      
		}
	}
	
	float exposureLev = 1;
	
	//if (numSteps > 0) { exposureLev = 1 / numSteps; }
	
	blob1.exposure = exposureLev;
	blob2.exposure = exposureLev;
	
	interBlobs.push_back(blob1);
	
	for(int i = 0; i < numSteps; i++) {
		margBlob newBlob;
		newBlob.centroid.x=round(blob1.centroid.x+(i*(float)step_x));
		newBlob.centroid.y=round(blob1.centroid.y+(i*(float)step_y));
		newBlob.exposure = exposureLev;
		float minX = -1;
		float minY = -1;
		float maxX = -1;
		float maxY = -1;
		int nTransPts = transPts.size();
		for(int p = 0; p < nTransPts; p++) {
			float x = newBlob.centroid.x + transPts[p][0] + (i * transPts[p][2]);
			float y = newBlob.centroid.y + transPts[p][1] + (i * transPts[p][3]);
			if (x < minX || minX == -1) {
				minX = x;
			}
			if (x > maxX || maxX == -1) {
				maxX = x;
			}
			if (y < minY || minY == -1) {
				minY = y;
			}
			if (y > maxY || maxY == -1) {
				maxY = y;
			}
			newBlob.pts.push_back(ofPoint(x, y));
		}
		newBlob.boundingRect.x = minX;
		newBlob.boundingRect.y = minY;
		newBlob.boundingRect.width = (maxX - minX);
		newBlob.boundingRect.height = (maxY - minY);
		interBlobs.push_back(newBlob);
	}
	
	interBlobs.push_back(blob2);
	
	blob1_normPts.clear();
	blob2_normPts.clear();
	transPts.clear();
	
	return interBlobs;

}
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
{
	assert(m_manifoldPtr);
	//order in manifold needs to match
	
	if (depth > m_manifoldPtr->getContactBreakingThreshold())
		return;

	bool isSwapped = m_manifoldPtr->getBody0() != m_body0;

	btVector3 pointA = pointInWorld + normalOnBInWorld * depth;

	btVector3 localA;
	btVector3 localB;
	
	if (isSwapped)
	{
		localA = m_rootTransB.invXform(pointA );
		localB = m_rootTransA.invXform(pointInWorld);
	} else
	{
		localA = m_rootTransA.invXform(pointA );
		localB = m_rootTransB.invXform(pointInWorld);
	}

	btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
	newPt.m_positionWorldOnA = pointA;
	newPt.m_positionWorldOnB = pointInWorld;
	
	int insertIndex = m_manifoldPtr->getCacheEntry(newPt);

	newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
	newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);

   //BP mod, store contact triangles.
   newPt.m_partId0 = m_partId0;
   newPt.m_partId1 = m_partId1;
   newPt.m_index0  = m_index0;
   newPt.m_index1  = m_index1;
	
	///todo, check this for any side effects
	if (insertIndex >= 0)
	{
		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
		m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
	} else
	{
		m_manifoldPtr->AddManifoldPoint(newPt);
	}

	//User can override friction and/or restitution
	if (gContactAddedCallback &&
		//and if either of the two bodies requires custom material
		 ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
		   (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
	{
		//experimental feature info, for per-triangle material etc.
		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
		(*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1);
	}

}
void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
{
    btAssert(m_manifoldPtr);
    //order in manifold needs to match

    if (depth > m_manifoldPtr->getContactBreakingThreshold())
//	if (depth > m_manifoldPtr->getContactProcessingThreshold())
        return;

    bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();

    btVector3 pointA = pointInWorld + normalOnBInWorld * depth;

    btVector3 localA;
    btVector3 localB;

    if (isSwapped)
    {
        localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
        localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
    } else
    {
        localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA );
        localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
    }

    btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
    newPt.m_positionWorldOnA = pointA;
    newPt.m_positionWorldOnB = pointInWorld;

    int insertIndex = m_manifoldPtr->getCacheEntry(newPt);

    newPt.m_combinedFriction = calculateCombinedFriction(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
    newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
    newPt.m_combinedRollingFriction = calculateCombinedRollingFriction(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
    btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);



    //BP mod, store contact triangles.
    if (isSwapped)
    {
        newPt.m_partId0 = m_partId1;
        newPt.m_partId1 = m_partId0;
        newPt.m_index0  = m_index1;
        newPt.m_index1  = m_index0;
    } else
    {
        newPt.m_partId0 = m_partId0;
        newPt.m_partId1 = m_partId1;
        newPt.m_index0  = m_index0;
        newPt.m_index1  = m_index1;
    }

    //printf("depth=%f\n", depth);
    ///@todo, check this for any side effects
    if (insertIndex >= 0)
    {
        //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
        m_manifoldPtr->replaceContactPoint(newPt, insertIndex);
    } else
    {
        insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
    }

    //User can override friction and/or restitution
    // DrChat: Removed for multithreading version
    /*
    if (gContactAddedCallback &&
    	//and if either of the two bodies requires custom material
    	 ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
    	   (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
    {
    	//experimental feature info, for per-triangle material etc.
    	const btCollisionObjectWrapper* obj0Wrap = isSwapped? m_body1Wrap : m_body0Wrap;
    	const btCollisionObjectWrapper* obj1Wrap = isSwapped? m_body0Wrap : m_body1Wrap;
    	(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
    }
    */
}
Example #10
0
File: mmgs1.c Project: XL64/mmg
/* analyze triangles and split if needed */
static int anaelt(pMesh mesh,pSol met,char typchk) {
    pTria    pt;
    pPoint   ppt,p1,p2;
    Hash     hash;
    Bezier   pb;
    pGeom    go;
    double   s,o[3],no[3],to[3],dd,len;
    int      vx[3],i,j,ip,ip1,ip2,ier,k,ns,nc,nt;
    char     i1,i2;
    static double uv[3][2] = { {0.5,0.5}, {0.,0.5}, {0.5,0.} };

    hashNew(&hash,mesh->np);
    ns = 0;
    s  = 0.5;
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        if ( MS_SIN(pt->tag[0]) || MS_SIN(pt->tag[1]) || MS_SIN(pt->tag[2]) )  continue;

        /* check element cut */
        pt->flag = 0;
        if ( typchk == 1 ) {
            if ( !chkedg(mesh,k) )  continue;
        }
        else if ( typchk == 2 ) {
            for (i=0; i<3; i++) {
                i1 = inxt[i];
                i2 = iprv[i];
                len = lenedg(mesh,met,pt->v[i1],pt->v[i2],0);
                if ( len > LLONG )  MS_SET(pt->flag,i);
            }
            if ( !pt->flag )  continue;
        }
        ns++;

        /* geometric support */
        ier = bezierCP(mesh,k,&pb);
        assert(ier);

        /* scan edges to split */
        for (i=0; i<3; i++) {
            if ( !MS_GET(pt->flag,i) )  continue;
            i1  = inxt[i];
            i2  = iprv[i];
            ip1 = pt->v[i1];
            ip2 = pt->v[i2];
            ip = hashGet(&hash,ip1,ip2);
            if ( !MS_EDG(pt->tag[i]) && ip > 0 )  continue;

            /* new point along edge */
            ier = bezierInt(&pb,uv[i],o,no,to);
            if ( !ip ) {
                ip = newPt(mesh,o,MS_EDG(pt->tag[i]) ? to : no);
                assert(ip);
                hashEdge(&hash,ip1,ip2,ip);
                p1  = &mesh->point[ip1];
                p2  = &mesh->point[ip2];
                ppt = &mesh->point[ip];

                if ( MS_EDG(pt->tag[i]) ) {
                    ++mesh->ng;
                    assert(mesh->ng < mesh->ngmax);
                    ppt->tag = pt->tag[i];
                    if ( p1->ref == pt->edg[i] || p2->ref == pt->edg[i] )
                        ppt->ref = pt->edg[i];
                    ppt->ig  = mesh->ng;
                    go = &mesh->geom[mesh->ng];
                    memcpy(go->n1,no,3*sizeof(double));

                    dd = go->n1[0]*ppt->n[0] + go->n1[1]*ppt->n[1] + go->n1[2]*ppt->n[2];
                    ppt->n[0] -= dd*go->n1[0];
                    ppt->n[1] -= dd*go->n1[1];
                    ppt->n[2] -= dd*go->n1[2];
                    dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                    if ( dd > EPSD2 ) {
                        dd = 1.0 / sqrt(dd);
                        ppt->n[0] *= dd;
                        ppt->n[1] *= dd;
                        ppt->n[2] *= dd;
                    }
                }
                if ( met->m ) {
                    if ( typchk == 1 )
                        intmet33(mesh,met,ip1,ip2,ip,s);
                    else
                        intmet(mesh,met,k,i,ip,s);
                }
            }
            else if ( pt->tag[i] & MS_GEO ) {
                ppt = &mesh->point[ip];
                go  = &mesh->geom[ppt->ig];
                memcpy(go->n2,no,3*sizeof(double));

                /* a computation of the tangent with respect to these two normals is possible */
                ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
                ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
                ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
                dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                if ( dd > EPSD2 ) {
                    dd = 1.0 / sqrt(dd);
                    ppt->n[0] *= dd;
                    ppt->n[1] *= dd;
                    ppt->n[2] *= dd;
                }
            }
        }
    }
    if ( !ns ) {
        free(hash.item);
        return(ns);
    }

    /* step 2. checking if split by adjacent */
    for (k=1; k<=mesh->nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        else if ( pt->flag == 7 )  continue;

        /* geometric support */
        ier = bezierCP(mesh,k,&pb);
        assert(ier);
        nc = 0;

        for (i=0; i<3; i++) {
            i1 = inxt[i];
            i2 = inxt[i1];
            if ( !MS_GET(pt->flag,i) && !MS_SIN(pt->tag[i]) ) {
                ip = hashGet(&hash,pt->v[i1],pt->v[i2]);
                if ( ip > 0 ) {
                    MS_SET(pt->flag,i);
                    nc++;
                    if ( pt->tag[i] & MS_GEO ) {
                        /* new point along edge */
                        ier = bezierInt(&pb,uv[i],o,no,to);
                        assert(ier);

                        ppt = &mesh->point[ip];
                        go  = &mesh->geom[ppt->ig];
                        memcpy(go->n2,no,3*sizeof(double));

                        /* a computation of the tangent with respect to these two normals is possible */
                        ppt->n[0] = go->n1[1]*go->n2[2] - go->n1[2]*go->n2[1];
                        ppt->n[1] = go->n1[2]*go->n2[0] - go->n1[0]*go->n2[2];
                        ppt->n[2] = go->n1[0]*go->n2[1] - go->n1[1]*go->n2[0];
                        dd = ppt->n[0]*ppt->n[0] + ppt->n[1]*ppt->n[1] + ppt->n[2]*ppt->n[2];
                        if ( dd > EPSD2 ) {
                            dd = 1.0 / sqrt(dd);
                            ppt->n[0] *= dd;
                            ppt->n[1] *= dd;
                            ppt->n[2] *= dd;
                        }
                    }
                }
            }
        }
        if ( nc > 0 )  ++ns;
    }
    if ( info.ddebug && ns ) {
        fprintf(stdout,"     %d analyzed  %d proposed\n",mesh->nt,ns);
        fflush(stdout);
    }

    /* step 3. splitting */
    ns = 0;
    nt = mesh->nt;
    for (k=1; k<=nt; k++) {
        pt = &mesh->tria[k];
        if ( !MS_EOK(pt) || pt->ref < 0 )  continue;
        else if ( pt->flag == 0 )  continue;

        j  = -1;
        vx[0] = vx[1] = vx[2] = 0;
        for (i=0; i<3; i++) {
            i1 = inxt[i];
            i2 = inxt[i1];
            if ( MS_GET(pt->flag,i) ) {
                vx[i] = hashGet(&hash,pt->v[i1],pt->v[i2]);
                assert(vx[i]);
                j = i;
            }
        }
        if ( pt->flag == 1 || pt->flag == 2 || pt->flag == 4 ) {
            ier = split1(mesh,met,k,j,vx);
            assert(ier);
            ns++;
        }
        else if ( pt->flag == 7 ) {
            ier = split3(mesh,met,k,vx);
            assert(ier);
            ns++;
        }
        else {
            ier = split2(mesh,met,k,vx);
            assert(ier);
            ns++;
        }
    }
    if ( (info.ddebug || abs(info.imprim) > 5) && ns > 0 )
        fprintf(stdout,"     %7d splitted\n",ns);
    free(hash.item);

    return(ns);
}
Example #11
0
 ///return true if it requires a dma transfer back
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
								   const btVector3& pointInWorld,
								   float depth,
								   btPersistentManifold* manifoldPtr,
								   btTransform& transA,
								   btTransform& transB,
									btScalar	combinedFriction,
									btScalar	combinedRestitution,
								   bool isSwapped)
{
	
//	float contactTreshold = manifoldPtr->getContactBreakingThreshold();

	//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);

#ifdef DEBUG_SPU_COLLISION_DETECTION
	spu_printf("SPU: contactTreshold %f\n",contactTreshold);
#endif //DEBUG_SPU_COLLISION_DETECTION
	//if (depth > manifoldPtr->getContactBreakingThreshold())
	//	return false;

	if (depth > manifoldPtr->getContactProcessingThreshold())
		return false;



	btVector3 pointA;
	btVector3 localA;
	btVector3 localB;
	btVector3 normal;


	if (isSwapped)
	{
		normal = normalOnBInWorld * -1;
		pointA = pointInWorld + normal * depth;
		localA = transA.invXform(pointA );
		localB = transB.invXform(pointInWorld);
	}
	else
	{
		normal = normalOnBInWorld;
		pointA = pointInWorld + normal * depth;
		localA = transA.invXform(pointA );
		localB = transB.invXform(pointInWorld);
	}

	btManifoldPoint newPt(localA,localB,normal,depth);
	newPt.m_positionWorldOnA = pointA;
	newPt.m_positionWorldOnB = pointInWorld;

	newPt.m_combinedFriction = combinedFriction;
	newPt.m_combinedRestitution = combinedRestitution;


	int insertIndex = manifoldPtr->getCacheEntry(newPt);
	if (insertIndex >= 0)
	{
		// we need to replace the current contact point, otherwise small errors will accumulate (spheres start rolling etc)
		manifoldPtr->replaceContactPoint(newPt,insertIndex);
		return true;
		
	} else
	{

		/*
		///@todo: SPU callbacks, either immediate (local on the SPU), or deferred
		//User can override friction and/or restitution
		if (gContactAddedCallback &&
			//and if either of the two bodies requires custom material
			 ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
			   (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
		{
			//experimental feature info, for per-triangle material etc.
			(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
		}
		*/

		manifoldPtr->addManifoldPoint(newPt);
		return true;

	}
	return false;
	
}
Example #12
0
//create the mesh for edges based on variable size from SizingFunction (var)
void EdgeMesher::VariableMeshing(ModelEnt *ent, int &num_edges, std::vector<double> &coords)
{
  double umin, umax, measure;
  (void) measure;
  // because of that, keep track of the first node position and last node position
  // first node position does not change, but the last node position do change
  // coords will contain all nodes, including umax in Urecord!

  SizingFunction *sf = mk_core()->sizing_function(ent->sizing_function_index());
  //get the u range for the edge
  iGeom::EntityHandle edge = ent->geom_handle();
  iGeom::Error gerr = ent->igeom_instance() ->getEntURange(edge, umin, umax);
  IBERRCHK(gerr, "Trouble get parameter range for edge.");

  if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");

  //get the arc length
  measure = ent -> measure();

  // start advancing for each edge mesh, from the first point position
  double currentPar = umin;
  double currentPosition[3];
  gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umin, currentPosition[0],
      currentPosition[1], currentPosition[2] );

  double endPoint[3];
  gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umax, endPoint[0],
      endPoint[1], endPoint[2] );
  Vector<3> endpt(endPoint);

  double targetSize = sf->size(currentPosition);
  double startSize = targetSize;

  double endSize = sf->size(endPoint);
  // advance u such that the next point is at "currentSize" distance
  // or close to it
  // try first with a u that is coming from the (umax-umin)/number of edges
  double deltaU = (umax-umin)/num_edges;
  //coords.clear(); we do not want to clear, as the first node is still fine
  std::vector<double> URecord;    //record the values for u; we may have to adjust all
  // of them accordingly, and even add one more if we have some evenify problems.
  // keep in mind that size is just a suggestion, number of intervals is more important for
  // paver mesher
  Vector<3> pt(currentPosition);

  //bool notDone = true;
  double prevU = umin;
  while (currentPar + 1.1*deltaU < umax)
  {
    // do some binary search; actually, better, do Newton-Raphson, which should converge
    // faster
    //
    prevU = currentPar;
    currentPar += deltaU;
    // adjust current par, such that
    double point[3];
    gerr=ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2] );
    IBERRCHK(gerr, "Trouble getting position at parameter u.");
    Vector<3> ptCandidate(point);
    double compSize = length(ptCandidate-pt);
    int nit = 0;

    while ( (fabs(1.-compSize/targetSize)> 0.02 ) && (nit < 5))// 2% of the target size
    {
      // do Newton iteration
      double tangent[3];
      gerr=ent->igeom_instance() ->getEntTgntU(edge, currentPar, tangent[0], tangent[1], tangent[2] );
      IBERRCHK(gerr, "Trouble getting tangent at parameter u.");
      Vector<3> tang(tangent);
      double dldu = 1./compSize * ((ptCandidate-pt )%tang);
      nit++;// increase iteration count
      if (dldu!=0.)
      {
        double deu= (targetSize-compSize)/dldu;
        currentPar+=deu;
        if (prevU>currentPar)
        {
          break; // something is wrong
        }
        if (umax < currentPar)
        {
          currentPar = umax;
          break;
        }
        ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2]);
        Vector<3> newPt(point);
        compSize = length(newPt-pt);
        ptCandidate = newPt;
      }

    }
    // we have found an acceptable point/param
    URecord.push_back(currentPar);
    deltaU = currentPar-prevU;// should be greater than 0
    pt = ptCandidate;
    targetSize = sf->size(pt.data());// a new target size, at the current point



  }
  // when we are out of here, we need to adjust the URecords, to be more nicely
  // distributed; also, look at the evenify again
  int sizeU = (int)URecord.size();
  if ((sizeU%2==0) && ent->constrain_even() )
  {
    // add one more
    if (sizeU==0)
    {
      // just add one in the middle, and call it done
      URecord.push_back( (umin+umax)/2);
    }
    else
    {
      //at least 2 (maybe 4)
      double lastDelta = URecord[sizeU-1]-URecord[sizeU-2];
      URecord.push_back(URecord[sizeU-1]+lastDelta );
    }
  }
  // now, we have to redistribute, such as the last 2 deltas are about the same
  // so, we should have after a little work,
  // umin, umin+c*(URecord[0]-umin), ... umin+c*(URecord[size-1]-umin), umax
  // what we have now is
  // umin, URecord[0], ... ,URecord[size-1], and umax could be even outside or inside
  // keep the last sizes equal
  //  umin+c(UR[size-2]-umin) + umax = 2*( umin+c*(UR[size-1]-umin))
  //  c ( 2*(UR[size-1]-umin) -(UR[size-2]-umin) ) = umax - umin
  // c ( 2*UR[size-1] - UR[size-2] - umin ) = umax - umin
  // c = (umax-umin)/( 2*UR[size-1] - UR[size-2] - umin)
  sizeU = (int)URecord.size();// it may be bigger by one than the last time
  if (sizeU == 0)
  {
    // nothing to do, only one edge to generate
  }
  else if (sizeU == 1)
  {
    // put it according to the sizes at ends, and assume a nice variation for u
    // (u-umin) / (umax-u) = startSize / endSize
    // (u-umin)*endSize = (umax-u) * startSize
    // u(endSize+startSize)=(umax*startSize+umin*endSize)
    URecord[0] = (umax*startSize+umin*endSize)/(startSize+endSize);

  }
  else // sizeU>=2, so we can spread the param a little more, assuming nice
    // uniform mapping
  {
    double c =  (umax-umin)/( 2*URecord[sizeU-1] - URecord[sizeU-2] - umin);
    for (int i=0; i<sizeU; i++)
      URecord[i] = umin + c*(URecord[i] -umin);// some spreading out
  }
  // now, we can finally get the points for each U, U's should be spread out nicely
  URecord.push_back(umax); // just add the last u, for the end point
  //
  sizeU = (int) URecord.size(); // new size, after pushing the last u, umax
  num_edges = sizeU;// this is the new number of edges; the last one will be the end point
  // of the edge, corresponding to umax
  coords.resize(3*sizeU+3);
  // we already know that at i=0 is the first node, start vertex of edge
  // the rest will be computed from u
  // even the last one, which is an overkill
  for (int i = 1; i <= num_edges; i++)
  {
    double u = URecord[i-1];
    gerr = ent->igeom_instance()->getEntUtoXYZ(edge, u, coords[3*i], coords[3*i+1], coords[3*i+2]);
    IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
  }
  return;

}
Example #13
0
 ///return true if it requires a dma transfer back
bool ManifoldResultAddContactPoint(const btVector3& normalOnBInWorld,
								   const btVector3& pointInWorld,
								   float depth,
								   btPersistentManifold* manifoldPtr,
								   btTransform& transA,
								   btTransform& transB,
									btScalar	combinedFriction,
									btScalar	combinedRestitution,
								   bool isSwapped)
{
	
	float contactTreshold = manifoldPtr->getContactBreakingThreshold();

	//spu_printf("SPU: add contactpoint, depth:%f, contactTreshold %f, manifoldPtr %llx\n",depth,contactTreshold,manifoldPtr);

#ifdef DEBUG_SPU_COLLISION_DETECTION
	spu_printf("SPU: contactTreshold %f\n",contactTreshold);
#endif //DEBUG_SPU_COLLISION_DETECTION
	if (depth > manifoldPtr->getContactBreakingThreshold())
		return false;

	//provide inverses or just calculate?
	btTransform transAInv = transA.inverse();//m_body0->m_cachedInvertedWorldTransform;
	btTransform transBInv= transB.inverse();//m_body1->m_cachedInvertedWorldTransform;

	btVector3 pointA;
	btVector3 localA;
	btVector3 localB;
	btVector3 normal;

	if (isSwapped)
	{
		normal = normalOnBInWorld * -1;
		pointA = pointInWorld + normal * depth;
		localA = transAInv(pointA );
		localB = transBInv(pointInWorld);
		/*localA = transBInv(pointA );
		localB = transAInv(pointInWorld);*/
	}
	else
	{
		normal = normalOnBInWorld;
		pointA = pointInWorld + normal * depth;
		localA = transAInv(pointA );
		localB = transBInv(pointInWorld);
	}

	btManifoldPoint newPt(localA,localB,normal,depth);

	int insertIndex = manifoldPtr->getCacheEntry(newPt);
	if (insertIndex >= 0)
	{
//		manifoldPtr->replaceContactPoint(newPt,insertIndex);
//		return true;

#ifdef DEBUG_SPU_COLLISION_DETECTION
		spu_printf("SPU: same contact detected, nothing done\n");
#endif //DEBUG_SPU_COLLISION_DETECTION
		// This is not needed, just use the old info! saves a DMA transfer as well
	} else
	{

		newPt.m_combinedFriction = combinedFriction;
		newPt.m_combinedRestitution = combinedRestitution;

		/*
		///@todo: SPU callbacks, either immediate (local on the SPU), or deferred
		//User can override friction and/or restitution
		if (gContactAddedCallback &&
			//and if either of the two bodies requires custom material
			 ((m_body0->m_collisionFlags & btCollisionObject::customMaterialCallback) ||
			   (m_body1->m_collisionFlags & btCollisionObject::customMaterialCallback)))
		{
			//experimental feature info, for per-triangle material etc.
			(*gContactAddedCallback)(newPt,m_body0,m_partId0,m_index0,m_body1,m_partId1,m_index1);
		}
		*/
		manifoldPtr->addManifoldPoint(newPt);
		return true;

	}
	return false;
	
}