Esempio n. 1
4
File: smoke.c Progetto: jinjoh/NOOR
/*! init triangle divisions */
void calcTriangleDivs(Object *ob, MVert *verts, int numverts, MFace *faces, int numfaces, int numtris, int **tridivs, float cell_len) 
{
	// mTriangleDivs1.resize( faces.size() );
	// mTriangleDivs2.resize( faces.size() );
	// mTriangleDivs3.resize( faces.size() );

	size_t i = 0, facecounter = 0;
	float maxscale[3] = {1,1,1}; // = channelFindMaxVf(mcScale);
	float maxpart = ABS(maxscale[0]);
	float scaleFac = 0;
	float fsTri = 0;
	if(ABS(maxscale[1])>maxpart) maxpart = ABS(maxscale[1]);
	if(ABS(maxscale[2])>maxpart) maxpart = ABS(maxscale[2]);
	scaleFac = 1.0 / maxpart;
	// featureSize = mLevel[mMaxRefine].nodeSize
	fsTri = cell_len * 0.5 * scaleFac;

	if(*tridivs)
		MEM_freeN(*tridivs);

	*tridivs = MEM_callocN(sizeof(int) * numtris * 3, "Smoke_Tridivs");

	for(i = 0, facecounter = 0; i < numfaces; i++) 
	{
		float p0[3], p1[3], p2[3];
		float side1[3];
		float side2[3];
		float side3[3];
		int divs1=0, divs2=0, divs3=0;

		VECCOPY(p0, verts[faces[i].v1].co);
		Mat4MulVecfl (ob->obmat, p0);
		VECCOPY(p1, verts[faces[i].v2].co);
		Mat4MulVecfl (ob->obmat, p1);
		VECCOPY(p2, verts[faces[i].v3].co);
		Mat4MulVecfl (ob->obmat, p2);

		VECSUB(side1, p1, p0);
		VECSUB(side2, p2, p0);
		VECSUB(side3, p1, p2);

		if(INPR(side1, side1) > fsTri*fsTri) 
		{ 
			float tmp = Normalize(side1);
			divs1 = (int)ceil(tmp/fsTri); 
		}
		if(INPR(side2, side2) > fsTri*fsTri) 
		{ 
			float tmp = Normalize(side2);
			divs2 = (int)ceil(tmp/fsTri); 
			
			/*
			// debug
			if(i==0)
				printf("b tmp: %f, fsTri: %f, divs2: %d\n", tmp, fsTri, divs2);
			*/
		}

		(*tridivs)[3 * facecounter + 0] = divs1;
		(*tridivs)[3 * facecounter + 1] = divs2;
		(*tridivs)[3 * facecounter + 2] = divs3;

		// TODO quad case
		if(faces[i].v4)
		{
			divs1=0, divs2=0, divs3=0;

			facecounter++;
			
			VECCOPY(p0, verts[faces[i].v3].co);
			Mat4MulVecfl (ob->obmat, p0);
			VECCOPY(p1, verts[faces[i].v4].co);
			Mat4MulVecfl (ob->obmat, p1);
			VECCOPY(p2, verts[faces[i].v1].co);
			Mat4MulVecfl (ob->obmat, p2);

			VECSUB(side1, p1, p0);
			VECSUB(side2, p2, p0);
			VECSUB(side3, p1, p2);

			if(INPR(side1, side1) > fsTri*fsTri) 
			{ 
				float tmp = Normalize(side1);
				divs1 = (int)ceil(tmp/fsTri); 
			}
			if(INPR(side2, side2) > fsTri*fsTri) 
			{ 
				float tmp = Normalize(side2);
				divs2 = (int)ceil(tmp/fsTri); 
			}

			(*tridivs)[3 * facecounter + 0] = divs1;
			(*tridivs)[3 * facecounter + 1] = divs2;
			(*tridivs)[3 * facecounter + 2] = divs3;
		}
		facecounter++;
	}
}
/* get a vector, vec, that points from v1->co to wherever makes sense to
 * the bevel operation as a whole based on the relationship between v1 and v2
 * (won't necessarily be a vec from v1->co to v2->co, though it probably will be);
 * the return value is -1 for failure, 0 if we used vert co's, and 1 if we used transform origins */
static int BME_bevel_get_vec(float *vec, BME_Vert *v1, BME_Vert *v2, BME_TransData_Head *td) {
	BME_TransData *vtd1, *vtd2;

	vtd1 = BME_get_transdata(td,v1);
	vtd2 = BME_get_transdata(td,v2);
	if (!vtd1 || !vtd2) {
		//printf("BME_bevel_get_vec() got called without proper BME_TransData\n");
		return -1;
	}

	/* compare the transform origins to see if we can use the vert co's;
	 * if they belong to different origins, then we will use the origins to determine
	 * the vector */
	if (compare_v3v3(vtd1->org,vtd2->org,0.000001f)) {
		VECSUB(vec,v2->co,v1->co);
		if (len_v3(vec) < 0.000001f) {
			mul_v3_fl(vec,0);
		}
		return 0;
	}
	else {
		VECSUB(vec,vtd2->org,vtd1->org);
		if (len_v3(vec) < 0.000001f) {
			mul_v3_fl(vec,0);
		}
		return 1;
	}
}
Esempio n. 3
0
/*  -------- pdDoEffectors() --------
	generic force/speed system, now used for particles and softbodies
	scene       = scene where it runs in, for time and stuff
	lb			= listbase with objects that take part in effecting
	opco		= global coord, as input
	force		= force accumulator
	speed		= actual current speed which can be altered
	cur_time	= "external" time in frames, is constant for static particles
	loc_time	= "local" time in frames, range <0-1> for the lifetime of particle
	par_layer	= layer the caller is in
	flags		= only used for softbody wind now
	guide		= old speed of particle

*/
void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse)
{
/*
	Modifies the force on a particle according to its
	relation with the effector object
	Different kind of effectors include:
		Forcefields: Gravity-like attractor
		(force power is related to the inverse of distance to the power of a falloff value)
		Vortex fields: swirling effectors
		(particles rotate around Z-axis of the object. otherwise, same relation as)
		(Forcefields, but this is not done through a force/acceleration)
		Guide: particles on a path
		(particles are guided along a curve bezier or old nurbs)
		(is independent of other effectors)
*/
	EffectorCache *eff;
	EffectorData efd;
	int p=0, tot = 1, step = 1;

	/* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
	/* Check for min distance here? (yes would be cool to add that, ton) */
	
	if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
		/* object effectors were fully checked to be OK to evaluate! */

		get_effector_tot(eff, &efd, point, &tot, &p, &step);

		for(; p<tot; p+=step) {
			if(get_effector_data(eff, &efd, point, 0)) {
				efd.falloff= effector_falloff(eff, &efd, point, weights);
				
				if(efd.falloff > 0.0f)
					efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);

				if(efd.falloff <= 0.0f)
					;	/* don't do anything */
				else if(eff->pd->forcefield == PFIELD_TEXTURE)
					do_texture_effector(eff, &efd, point, force);
				else {
					float temp1[3]={0,0,0}, temp2[3];
					copy_v3_v3(temp1, force);

					do_physical_effector(eff, &efd, point, force);
					
					// for softbody backward compatibility
					if(point->flag & PE_WIND_AS_SPEED && impulse){
						VECSUB(temp2, force, temp1);
						VECSUB(impulse, impulse, temp2);
					}
				}
			}
			else if(eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) {
				/* special case for harmonic effector */
				VECADD(impulse, impulse, efd.vel);
			}
		}
	}
}
Esempio n. 4
0
static int convex(float *p0, float *up, float *a, float *b)
{
	// Vec3 va = a-p0, vb = b-p0;
	float va[3], vb[3], tmp[3];
	VECSUB(va, a, p0);
	VECSUB(vb, b, p0);
	cross_v3_v3v3(tmp, va, vb);
	return INPR(up, tmp) >= 0;
}
Esempio n. 5
0
File: sss.c Progetto: jinjoh/NOOR
static void traverse_octree(ScatterTree *tree, ScatterNode *node, float *co, int self, ScatterResult *result)
{
	float sub[3], dist;
	int i, index = 0;

	if(node->totpoint > 0) {
		/* leaf - add radiance from all samples */
		for(i=0; i<node->totpoint; i++) {
			ScatterPoint *p= &node->points[i];

			VECSUB(sub, co, p->co);
			dist= INPR(sub, sub);

			if(p->back)
				add_radiance(tree, NULL, p->rad, 0.0f, p->area, dist, result);
			else
				add_radiance(tree, p->rad, NULL, p->area, 0.0f, dist, result);
		}
	}
	else {
		/* branch */
		if (self)
			index = SUBNODE_INDEX(co, node->split);

		for(i=0; i<8; i++) {
			if(node->child[i]) {
				ScatterNode *subnode= node->child[i];

				if(self && index == i) {
					/* always traverse node containing the point */
					traverse_octree(tree, subnode, co, 1, result);
				}
				else {
					/* decide subnode traversal based on maximum solid angle */
					VECSUB(sub, co, subnode->co);
					dist= INPR(sub, sub);

					/* actually area/dist > error, but this avoids division */
					if(subnode->area+subnode->backarea>tree->error*dist) {
						traverse_octree(tree, subnode, co, 0, result);
					}
					else {
						add_radiance(tree, subnode->rad, subnode->backrad,
							subnode->area, subnode->backarea, dist, result);
					}
				}
			}
		}
	}
}
Esempio n. 6
0
int playWave3DPitch(const char *fname, const double src[3], const double org[3], const double pyr[3], double vol, double attn, double delay, unsigned short pitch){
	extern double dwo;
	avec3_t delta, xhat;
	double sdist, dist;
	VECSUB(delta, src, org);
	sdist = VECSLEN(delta);
	dist = sqrt(sdist);
/*	xhat[0] = cos(pyr[1]);
	xhat[1] = 0;
	xhat[2] =- sin(pyr[1]);*/
/*	return playWaveCustom(fname, (size_t)(SAMPLERATE * (dist / wave_sonic_speed)), (unsigned char)(256 * vol / (1. + sdist / attn)), 0, 128 * VECSP(delta, xhat) / dist, 0, 0);*/
	return playWave3DCustom(fname, src, delay < dwo ? 0 : (size_t)(SAMPLERATE * (delay - dwo)), vol, attn, pitch);
}
Esempio n. 7
0
int playMemoryWave3D(const unsigned char *wav, size_t size, short pitch, const double src[3], const double org[3], const double pyr[3], double vol, double attn, double delay){
	extern double dwo;
	avec3_t delta, xhat;
	double sdist, dist;
	VECSUB(delta, src, org);
	sdist = VECSLEN(delta);
	dist = sqrt(sdist);
/*	xhat[0] = -cos(pyr[1]);
	xhat[1] = 0;
	xhat[2] =  sin(pyr[1]);*/
/*	return addsound(wav, size, (size_t)(SAMPLERATE * (dist / wave_sonic_speed)), (unsigned char)(256 * vol / (1. + sdist / attn)), pitch, -128 * VECSP(delta, xhat) / dist, 0, 0);*/
	return addsound3d(wav, size, delay < dwo ? 0 : (size_t)(SAMPLERATE * (delay - dwo/* + dist / wave_sonic_speed*/)), vol, attn, src, pitch + 256, 8000);
}
Esempio n. 8
0
// check whether a ship is in jump range of a stargate ------------------------
//
PRIVATE
int ShipInStargateJumpRange( Stargate *stargate, ShipObject *ship, geomv_t range )
{
	ASSERT( stargate != NULL );
	ASSERT( ship != NULL );

	//NOTE:
	// the ship is treated as a point for jump
	// range detection.

	Vector3 gatenormal;
	FetchZVector( stargate->ObjPosition, &gatenormal );

	Vertex3 gatepos;
	FetchTVector( stargate->ObjPosition, &gatepos );

	Vertex3 shippos;
	FetchTVector( ship->ObjPosition, &shippos );

	geomv_t shipdot  = -DOT_PRODUCT( &gatenormal, &shippos );
	geomv_t gatedot  = -DOT_PRODUCT( &gatenormal, &gatepos );
	geomv_t distance = shipdot - gatedot;

	// not in range if ship in wrong halfspace
	if ( GEOMV_NEGATIVE( distance ) ) {
		return FALSE;
	}

	// check whether inside of boundingsphere around stargate
	Vector3 stargate_ship;
	VECSUB( &stargate_ship, &shippos, &gatepos );

	geomv_t stargate_ship_len = VctLenX( &stargate_ship );
	if ( stargate_ship_len > stargate->BoundingSphere ) {
		return FALSE;
	}

	// inside the activation distance/range ?
	if ( distance < range ) {

		Vector3 shipnormal;
		FetchZVector( ship->ObjPosition, &shipnormal );

		// ship must be flying approximately head-on into the gate
		//FIXME: cone_angle like for teleporter
		geomv_t dirdot = DOT_PRODUCT( &gatenormal, &shipnormal );
		return ( dirdot > FLOAT_TO_GEOMV( 0.7f ) );
	}

	return FALSE;
}
static float BME_bevel_get_angle(BME_Mesh *UNUSED(bm), BME_Edge *e, BME_Vert *v) {
	BME_Vert *v1, *v2;
	BME_Loop *l1, *l2;
	float vec1[3], vec2[3], vec3[3], vec4[3];

	l1 = e->loop;
	l2 = e->loop->radial.next->data;
	if (l1->v == v) {
		v1 = l1->prev->v;
		v2 = l1->next->v;
	}
	else {
		v1 = l1->next->next->v;
		v2 = l1->v;
	}
	VECSUB(vec1,v1->co,v->co);
	VECSUB(vec2,v2->co,v->co);
	cross_v3_v3v3(vec3,vec1,vec2);

	l1 = l2;
	if (l1->v == v) {
		v1 = l1->prev->v;
		v2 = l1->next->v;
	}
	else {
		v1 = l1->next->next->v;
		v2 = l1->v;
	}
	VECSUB(vec1,v1->co,v->co);
	VECSUB(vec2,v2->co,v->co);
	cross_v3_v3v3(vec4,vec2,vec1);

	normalize_v3(vec3);
	normalize_v3(vec4);

	return dot_v3v3(vec3,vec4);
}
Esempio n. 10
0
// ----------------------------------------------------------------------------
//
void BOT_AI::_GoalCheck_AgentMode_Retreat()
{
    BOT_Goal* pGoal	= m_State.GetCurGoal();
	Vector3* pGoalPos = pGoal->GetGoalPosition();
	ExtraObject* pObject = NULL;
	ASSERT( pGoal != NULL );
    
	if(pGoal->GetTargetObject() == NULL) {
        if(m_pShip->CurDamage > (m_pShip->MaxDamage * 0.9)) {
	       pObject = m_Character.SelectRepairObject();
	    }
	    if(m_pShip->CurEnergy < (m_pShip->MaxEnergy * 0.1)) {
			pObject = m_Character.SelectEnergyObject();
			m_nAgentMode = AGENTMODE_RETREAT;
	    }
		if(pObject == NULL) {
            m_nAgentMode = AGENTMODE_IDLE;
            return;
         }
         pGoal->SetTargetObject(pObject);
         FetchTVector( pObject->ObjPosition, pGoalPos );
#ifdef BOT_LOGFILES
		 BOT_MsgOut("Retreat: Targetting Extra");
#endif
	}
	
	pGoalPos = pGoal->GetGoalPosition();

	// get vector to target
	Vector3 vec2Target;	
	VECSUB( &vec2Target, pGoalPos, &m_AgentPos );

	float len = VctLenX( &vec2Target );
#ifdef BOT_LOGFILES
	BOT_MsgOut( "BOT: distance to goal: %f", len );
#endif        
	if ( len < 100.0f )  {
#ifdef BOT_LOGFILES
	   BOT_MsgOut("Clearing Goal");
#endif
	   pGoal->SetTargetObject(NULL);
	   
	}

}
Esempio n. 11
0
/* tracing */
static float vol_get_shadow(ShadeInput *shi, LampRen *lar, float *co)
{
	float visibility = 1.f;
	
	if(lar->shb) {
		float dxco[3]={0.f, 0.f, 0.f}, dyco[3]={0.f, 0.f, 0.f};
		
		visibility = testshadowbuf(&R, lar->shb, co, dxco, dyco, 1.0, 0.0);		
	} else if (lar->mode & LA_SHAD_RAY) {
		/* trace shadow manually, no good lamp api atm */
		Isect is;
		
		copy_v3_v3(is.start, co);
		if(lar->type==LA_SUN || lar->type==LA_HEMI) {
			is.dir[0] = -lar->vec[0];
			is.dir[1] = -lar->vec[1];
			is.dir[2] = -lar->vec[2];
			is.dist = R.maxdist;
		} else {
			VECSUB( is.dir, lar->co, is.start );
			is.dist = normalize_v3( is.dir );
		}

		is.mode = RE_RAY_MIRROR;
		is.check = RE_CHECK_VLR_NON_SOLID_MATERIAL;
		is.skip = 0;
		
		if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW))
			is.lay= lar->lay;	
		else
			is.lay= -1;
			
		is.orig.ob = NULL;
		is.orig.face = NULL;
		is.last_hit = lar->last_hit[shi->thread];
		
		if(RE_rayobject_raycast(R.raytree,&is)) {
			visibility = 0.f;
		}
		
		lar->last_hit[shi->thread]= is.last_hit;
	}
	return visibility;
}
Esempio n. 12
0
File: smoke.c Progetto: jinjoh/NOOR
static void get_cell(float *p0, int res[3], float dx, float *pos, int *cell, int correct)
{
	float tmp[3];

	VECSUB(tmp, pos, p0);
	VecMulf(tmp, 1.0 / dx);

	if(correct)
	{
		cell[0] = MIN2(res[0] - 1, MAX2(0, (int)floor(tmp[0])));
		cell[1] = MIN2(res[1] - 1, MAX2(0, (int)floor(tmp[1])));
		cell[2] = MIN2(res[2] - 1, MAX2(0, (int)floor(tmp[2])));
	}
	else
	{
		cell[0] = (int)floor(tmp[0]);
		cell[1] = (int)floor(tmp[1]);
		cell[2] = (int)floor(tmp[2]);
	}
}
/* a wrapper for BME_SEMV that transfers element flags */ /*add custom data interpolation in here!*/
static BME_Vert *BME_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Edge *e, BME_Edge **ne, float percent) {
	BME_Vert *nv, *v2;
	float len;

	v2 = BME_edge_getothervert(e,v);
	nv = BME_SEMV(bm,v,e,ne);
	if (nv == NULL) return NULL;
	VECSUB(nv->co,v2->co,v->co);
	len = len_v3(nv->co);
	VECADDFAC(nv->co,v->co,nv->co,len*percent);
	nv->flag = v->flag;
	nv->bweight = v->bweight;
	if (ne) {
		(*ne)->flag = e->flag;
		(*ne)->h = e->h;
		(*ne)->crease = e->crease;
		(*ne)->bweight = e->bweight;
	}
	/*v->nv->v2*/
	BME_data_facevert_edgesplit(bm,v2, v, nv, e, 0.75);	
	return nv;
}
Esempio n. 14
0
// ----------------------------------------------------------------------------
//
void BOT_AI::_GoalCheck_AgentMode_Powerup()
{
    BOT_Goal* pGoal	= m_State.GetCurGoal();
	Vector3* pGoalPos = pGoal->GetGoalPosition();
	
	ASSERT( pGoal != NULL );
    if(pGoal->GetTargetObject() == NULL) {
        ExtraObject* pObject = FetchFirstExtra();
        if(pObject == NULL) {
            m_nAgentMode = AGENTMODE_IDLE;
            return;
         }
         pGoal->SetTargetObject(pObject);
         FetchTVector( pObject->ObjPosition, pGoalPos );
#ifdef BOT_LOGFILES
         BOT_MsgOut("Targetting Extra");
#endif
	}
	
	pGoalPos = pGoal->GetGoalPosition();

	// get vector to target
	Vector3 vec2Target;	
	VECSUB( &vec2Target, pGoalPos, &m_AgentPos );

	float len = VctLenX( &vec2Target );
#ifdef BOT_LOGFILES
	BOT_MsgOut( "BOT: distance to goal: %f", len );
#endif    
	if ( len < 100.0f )  {
#ifdef BOT_LOGFILES
	   BOT_MsgOut("Clearing Goal");
	   pGoal->SetTargetObject(NULL);
#endif	   
	}
  
}
Esempio n. 15
0
// ----------------------------------------------------------------------------
//
void BOT_AI::_SteerToPosition( Vector3* targetPos, object_control_s* pObjctl )
{
	// get vector to target
	Vector3 vec2Target;	
	VECSUB( &vec2Target, targetPos, &m_AgentPos );

	float oldaccel = pObjctl->accel;

	UTL_LocomotionController _LomoCtrl;
	_LomoCtrl.ControlOjbect( pObjctl, &vec2Target, pObjctl->pShip->MaxSpeed );

	if ( pObjctl->accel != oldaccel ) {
#ifdef BOT_LOGFILES
		BOT_AccelMode_MsgOut( "%f %f %f", m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z );
#endif // BOT_LOGFILES
	}

	Vector3 xDir, yDir, zDir;
	FetchXVector( m_pShip->ObjPosition, &xDir );
	FetchYVector( m_pShip->ObjPosition, &yDir );
	FetchZVector( m_pShip->ObjPosition, &zDir );

#ifdef BOT_LOGFILES
	BOT_MsgOut( "pos: %7.2f/%7.2f/%7.2f vec2target: %7.2f/%7.2f/%7.2f xDir: %7.2f/%7.2f/%7.2f yDir: %7.2f/%7.2f/%7.2f rot_x: %7.2f rot_y: %7.2f accel: %7.2f",
		m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z,
				vec2Target.X, vec2Target.Y, vec2Target.Z,
				xDir.X, xDir.Y, xDir.Z,
				yDir.X, yDir.Y, yDir.Z,
				pObjctl->rot_x, pObjctl->rot_y, pObjctl->accel );

	BOT_Pos_MsgOut ( "%f %f %f", m_AgentPos.X, m_AgentPos.Y, m_AgentPos.Z );
	BOT_XDir_MsgOut( "%f %f %f", xDir.X, xDir.Y, xDir.Z );
	BOT_ZDir_MsgOut( "%f %f %f", zDir.X, zDir.Y, zDir.Z );
#endif // BOT_LOGFILES

}
Esempio n. 16
0
static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, EditMesh *em, MTFace *activetf)
{
	EditFace *efa;
	MTFace *tf;
	Image *ima= sima->image;
	float aspx, aspy, col[4], tf_uv[4][2];
	
	ED_space_image_uv_aspect(sima, &aspx, &aspy);
	
	switch(sima->dt_uvstretch) {
		case SI_UVDT_STRETCH_AREA:
		{
			float totarea=0.0f, totuvarea=0.0f, areadiff, uvarea, area;
			
			for(efa= em->faces.first; efa; efa= efa->next) {
				tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
				uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);

				totarea += EM_face_area(efa);
				//totuvarea += tf_area(tf, efa->v4!=0);
				totuvarea += uv_area(tf_uv, efa->v4!=0);
				
				if(uvedit_face_visible(scene, ima, efa, tf)) {
					efa->tmp.p = tf;
				}
				else {
					if(tf == activetf)
						activetf= NULL;
					efa->tmp.p = NULL;
				}
			}
			
			if(totarea < FLT_EPSILON || totuvarea < FLT_EPSILON) {
				col[0] = 1.0;
				col[1] = col[2] = 0.0;
				glColor3fv(col);
				for(efa= em->faces.first; efa; efa= efa->next) {
					if((tf=(MTFace *)efa->tmp.p)) {
						glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
							glVertex2fv(tf->uv[0]);
							glVertex2fv(tf->uv[1]);
							glVertex2fv(tf->uv[2]);
							if(efa->v4) glVertex2fv(tf->uv[3]);
						glEnd();
					}
				}
			}
			else {
				for(efa= em->faces.first; efa; efa= efa->next) {
					if((tf=(MTFace *)efa->tmp.p)) {
						area = EM_face_area(efa) / totarea;
						uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
						//uvarea = tf_area(tf, efa->v4!=0) / totuvarea;
						uvarea = uv_area(tf_uv, efa->v4!=0) / totuvarea;
						
						if(area < FLT_EPSILON || uvarea < FLT_EPSILON)
							areadiff = 1.0;
						else if(area>uvarea)
							areadiff = 1.0-(uvarea/area);
						else
							areadiff = 1.0-(area/uvarea);
						
						weight_to_rgb(areadiff, col, col+1, col+2);
						glColor3fv(col);
						
						glBegin(efa->v4?GL_QUADS:GL_TRIANGLES);
							glVertex2fv(tf->uv[0]);
							glVertex2fv(tf->uv[1]);
							glVertex2fv(tf->uv[2]);
							if(efa->v4) glVertex2fv(tf->uv[3]);
						glEnd();
					}
				}
			}
			break;
		}
		case SI_UVDT_STRETCH_ANGLE:
		{
			float uvang1,uvang2,uvang3,uvang4;
			float ang1,ang2,ang3,ang4;
			float av1[3], av2[3], av3[3], av4[3]; /* use for 2d and 3d  angle vectors */
			float a;
			
			col[3] = 0.5; /* hard coded alpha, not that nice */
			
			glShadeModel(GL_SMOOTH);
			
			for(efa= em->faces.first; efa; efa= efa->next) {
				tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
				
				if(uvedit_face_visible(scene, ima, efa, tf)) {
					efa->tmp.p = tf;
					uv_copy_aspect(tf->uv, tf_uv, aspx, aspy);
					if(efa->v4) {
						
#if 0						/* Simple but slow, better reuse normalized vectors */
						uvang1 = RAD2DEG(Vec2Angle3(tf_uv[3], tf_uv[0], tf_uv[1]));
						ang1 = RAD2DEG(VecAngle3(efa->v4->co, efa->v1->co, efa->v2->co));
						
						uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2]));
						ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co));
						
						uvang3 = RAD2DEG(Vec2Angle3(tf_uv[1], tf_uv[2], tf_uv[3]));
						ang3 = RAD2DEG(VecAngle3(efa->v2->co, efa->v3->co, efa->v4->co));
						
						uvang4 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[3], tf_uv[0]));
						ang4 = RAD2DEG(VecAngle3(efa->v3->co, efa->v4->co, efa->v1->co));
#endif
						
						/* uv angles */
						VECSUB2D(av1, tf_uv[3], tf_uv[0]); Normalize2(av1);
						VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2);
						VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3);
						VECSUB2D(av4, tf_uv[2], tf_uv[3]); Normalize2(av4);
						
						/* This is the correct angle however we are only comparing angles
						 * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90);*/
						uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
						uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
						uvang3 = NormalizedVecAngle2_2D(av3, av4)*180.0/M_PI;
						uvang4 = NormalizedVecAngle2_2D(av4, av1)*180.0/M_PI;
						
						/* 3d angles */
						VECSUB(av1, efa->v4->co, efa->v1->co); Normalize(av1);
						VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
						VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
						VECSUB(av4, efa->v3->co, efa->v4->co); Normalize(av4);
						
						/* This is the correct angle however we are only comparing angles
						 * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90);*/
						ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
						ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
						ang3 = NormalizedVecAngle2(av3, av4)*180.0/M_PI;
						ang4 = NormalizedVecAngle2(av4, av1)*180.0/M_PI;
						
						glBegin(GL_QUADS);
						
						/* This simple makes the angles display worse then they really are ;)
						 * 1.0-pow((1.0-a), 2) */
						
						a = fabs(uvang1-ang1)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[0]);
						a = fabs(uvang2-ang2)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[1]);
						a = fabs(uvang3-ang3)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[2]);
						a = fabs(uvang4-ang4)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[3]);
						
					}
					else {
#if 0						/* Simple but slow, better reuse normalized vectors */
						uvang1 = RAD2DEG(Vec2Angle3(tf_uv[2], tf_uv[0], tf_uv[1]));
						ang1 = RAD2DEG(VecAngle3(efa->v3->co, efa->v1->co, efa->v2->co));
						
						uvang2 = RAD2DEG(Vec2Angle3(tf_uv[0], tf_uv[1], tf_uv[2]));
						ang2 = RAD2DEG(VecAngle3(efa->v1->co, efa->v2->co, efa->v3->co));
						
						uvang3 = M_PI-(uvang1+uvang2);
						ang3 = M_PI-(ang1+ang2);
#endif						
						
						/* uv angles */
						VECSUB2D(av1, tf_uv[2], tf_uv[0]); Normalize2(av1);
						VECSUB2D(av2, tf_uv[0], tf_uv[1]); Normalize2(av2);
						VECSUB2D(av3, tf_uv[1], tf_uv[2]); Normalize2(av3);
						
						/* This is the correct angle however we are only comparing angles
						 * uvang1 = 90-((NormalizedVecAngle2_2D(av1, av2) * 180.0/M_PI)-90); */
						uvang1 = NormalizedVecAngle2_2D(av1, av2)*180.0/M_PI;
						uvang2 = NormalizedVecAngle2_2D(av2, av3)*180.0/M_PI;
						uvang3 = NormalizedVecAngle2_2D(av3, av1)*180.0/M_PI;
						
						/* 3d angles */
						VECSUB(av1, efa->v3->co, efa->v1->co); Normalize(av1);
						VECSUB(av2, efa->v1->co, efa->v2->co); Normalize(av2);
						VECSUB(av3, efa->v2->co, efa->v3->co); Normalize(av3);
						/* This is the correct angle however we are only comparing angles
						 * ang1 = 90-((NormalizedVecAngle2(av1, av2) * 180.0/M_PI)-90); */
						ang1 = NormalizedVecAngle2(av1, av2)*180.0/M_PI;
						ang2 = NormalizedVecAngle2(av2, av3)*180.0/M_PI;
						ang3 = NormalizedVecAngle2(av3, av1)*180.0/M_PI;
						
						/* This simple makes the angles display worse then they really are ;)
						 * 1.0-pow((1.0-a), 2) */
						
						glBegin(GL_TRIANGLES);
						a = fabs(uvang1-ang1)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[0]);
						a = fabs(uvang2-ang2)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[1]);
						a = fabs(uvang3-ang3)/180.0;
						weight_to_rgb(1.0-pow((1.0-a), 2), col, col+1, col+2);
						glColor3fv(col);
						glVertex2fv(tf->uv[2]);
					}
					glEnd();
				}
				else {
					if(tf == activetf)
						activetf= NULL;
					efa->tmp.p = NULL;
				}
			}

			glShadeModel(GL_FLAT);
			break;
		}
	}
}
Esempio n. 17
0
// scan ship objects for radar ------------------------------------------------
//
INLINE
void RadarScanShipObjects()
{
	GenObject *targetobj = NULL;

	for ( GenObject *walkobjs = FetchFirstShip(); walkobjs; ) {

		// set color for normal objects
		int rocolor = NORMAL_RADAR_OBJ_COL2;

		if ( AUX_ENABLE_DEPTHCUED_RADAR_DOTS && !AUX_ENABLE_ELITE_RADAR ) {

			Vertex3 shippos;
			FetchTVector( walkobjs->ObjPosition, &shippos );

			Vertex3 myshippos;
			FetchTVector( MyShip->ObjPosition, &myshippos );

			Vector3 dist;
			VECSUB( &dist, &shippos, &myshippos );

			geomv_t vx = dist.X;
			geomv_t vy = dist.Y;
			geomv_t vz = dist.Z;

			ABS_GEOMV( vx );
			ABS_GEOMV( vy );
			ABS_GEOMV( vz );

			int distance = 0;
			if ( ( vx > GEOMV_VANISHING ) ||
		 		 ( vy > GEOMV_VANISHING ) ||
		 		 ( vz > GEOMV_VANISHING ) ) {
				distance = GEOMV_TO_INT( VctLenX( &dist ) );
			}

			if ( distance > 4096 ) {
				rocolor = NORMAL_RADAR_OBJ_COL3;
			} else if ( distance > 2048 ) {
				rocolor = NORMAL_RADAR_OBJ_COL2;
			} else {
				rocolor = NORMAL_RADAR_OBJ_COL1;
			}
		}

		// ensure that the target object is drawn last
		if ( walkobjs->HostObjNumber == TargetObjNumber ) {

			if ( targetobj == NULL ) {
				targetobj = walkobjs;
				
				if ( ( walkobjs = walkobjs->NextObj ) == NULL ) {
					walkobjs = targetobj;
				}
				
				continue;
			}

			rocolor = TARGET_RADAR_OBJ_COL;
		}

		// depict ship's position on radar
		if ( AUX_ENABLE_ELITE_RADAR ) {
			CalcDrawEliteRadarObj( walkobjs, rocolor );
		} else {
			CalcDrawRadarObj( walkobjs, rocolor );
		}

		if ( walkobjs == targetobj ) {
			break;
		}

		if ( ( walkobjs = walkobjs->NextObj ) == NULL ) {
			walkobjs = targetobj;
		}
	}
}
/* BME_bevel_split_edge() is the main math work-house; its responsibilities are:
 * using the vert and the loop passed, get or make the split vert, set its coordinates
 * and transform properties, and set the max limits.
 * Finally, return the split vert. */
static BME_Vert *BME_bevel_split_edge(BME_Mesh *bm, BME_Vert *v, BME_Vert *v1, BME_Loop *l, float *up_vec, float value, BME_TransData_Head *td) {
	BME_TransData *vtd, *vtd1, *vtd2;
	BME_Vert *sv, *v2, *v3, *ov;
	BME_Loop *lv1, *lv2;
	BME_Edge *ne, *e1, *e2;
	float maxfactor, scale, len, dis, vec1[3], vec2[3], t_up_vec[3];
	int is_edge, forward, is_split_vert;

	if (l == NULL) {
		/* what you call operator overloading in C :)
		 * I wanted to use the same function for both wire edges and poly loops
		 * so... here we walk around edges to find the needed verts */
		forward = 1;
		is_split_vert = 0;
		if (v->edge == NULL) {
			//printf("We can't split a loose vert's edge!\n");
			return NULL;
		}
		e1 = v->edge; /* we just use the first two edges */
		e2 = BME_disk_nextedge(v->edge, v);
		if (e1 == e2) {
			//printf("You need at least two edges to use BME_bevel_split_edge()\n");
			return NULL;
		}
		v2 = BME_edge_getothervert(e1, v);
		v3 = BME_edge_getothervert(e2, v);
		if (v1 != v2 && v1 != v3) {
			//printf("Error: more than 2 edges in v's disk cycle, or v1 does not share an edge with v\n");
			return NULL;
		}
		if (v1 == v2) {
			v2 = v3;
		}
		else {
			e1 = e2;
		}
		ov = BME_edge_getothervert(e1,v);
		sv = BME_split_edge(bm,v,e1,&ne,0);
		//BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
		//BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
		//BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
		BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
		sv->tflag1 |= BME_BEVEL_BEVEL;
		ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
		BME_bevel_get_vec(vec1,v1,v,td);
		BME_bevel_get_vec(vec2,v2,v,td);
		cross_v3_v3v3(t_up_vec,vec1,vec2);
		normalize_v3(t_up_vec);
		up_vec = t_up_vec;
	}
	else {
		/* establish loop direction */
		if (l->v == v) {
			forward = 1;
			lv1 = l->next;
			lv2 = l->prev;
			v1 = l->next->v;
			v2 = l->prev->v;
		}
		else if (l->next->v == v) {
			forward = 0;
			lv1 = l;
			lv2 = l->next->next;
			v1 = l->v;
			v2 = l->next->next->v;
		}
		else {
			//printf("ERROR: BME_bevel_split_edge() - v must be adjacent to l\n");
			return NULL;
		}

		if (BME_bevel_is_split_vert(lv1)) {
			is_split_vert = 1;
			sv = v1;
			if (forward) v1 = l->next->next->v;
			else v1 = l->prev->v;
		}
		else {
			is_split_vert = 0;
			ov = BME_edge_getothervert(l->e,v);
			sv = BME_split_edge(bm,v,l->e,&ne,0);
			//BME_data_interp_from_verts(bm, v, ov, sv, 0.25); /*this is technically wrong...*/
			//BME_data_interp_from_faceverts(bm, v, ov, sv, 0.25);
			//BME_data_interp_from_faceverts(bm, ov, v, sv, 0.25);
			BME_assign_transdata(td, bm, sv, sv->co, sv->co, NULL, sv->co, 0, -1, -1, NULL); /* quick default */
			sv->tflag1 |= BME_BEVEL_BEVEL;
			ne->tflag1 = BME_BEVEL_ORIG; /* mark edge as original, even though it isn't */
		}

		if (BME_bevel_is_split_vert(lv2)) {
			if (forward) v2 = lv2->prev->v;
			else v2 = lv2->next->v;
		}
	}

	is_edge = BME_bevel_get_vec(vec1,v,v1,td); /* get the vector we will be projecting onto */
	BME_bevel_get_vec(vec2,v,v2,td); /* get the vector we will be projecting parallel to */
	len = len_v3(vec1);
	normalize_v3(vec1);

	vtd = BME_get_transdata(td, sv);
	vtd1 = BME_get_transdata(td, v);
	vtd2 = BME_get_transdata(td,v1);

	if (vtd1->loc == NULL) {
		/* this is a vert with data only for calculating initial weights */
		if (vtd1->weight < 0) {
			vtd1->weight = 0;
		}
		scale = vtd1->weight/vtd1->factor;
		if (!vtd1->max) {
			vtd1->max = BME_new_transdata_float(td);
			*vtd1->max = -1;
		}
	}
	else {
		scale = vtd1->weight;
	}
	vtd->max = vtd1->max;

	if (is_edge && vtd1->loc != NULL) {
		maxfactor = vtd1->maxfactor;
	}
	else {
		maxfactor = scale*BME_bevel_project_vec(vec1,vec2,up_vec,forward,td);
		if (vtd->maxfactor > 0 && vtd->maxfactor < maxfactor) {
			maxfactor = vtd->maxfactor;
		}
	}

	dis = (v1->tflag1 & BME_BEVEL_ORIG)? len/3 : len/2;
	if (is_edge || dis > maxfactor*value) {
		dis = maxfactor*value;
	}
	VECADDFAC(sv->co,v->co,vec1,dis);
	VECSUB(vec1,sv->co,vtd1->org);
	dis = len_v3(vec1);
	normalize_v3(vec1);
	BME_assign_transdata(td, bm, sv, vtd1->org, vtd1->org, vec1, sv->co, dis, scale, maxfactor, vtd->max);

	return sv;
}
Esempio n. 19
0
static int chunk_object(Mesh *ret, FPOS *pfo, Mesh::Coord scale, struct Bone ***bones, int num){
	char *s, *name = NULL;
	int n, i, j;
	Mesh::Attrib *patr;
	char line[512], *cur;
	Mesh::Index atr = (Mesh::Index)-1;
	int shading = 0;
	double facet = 0.;
	struct Bone *bone = NULL;
	int mirror = 0, mirror_axis = 0, mirrors = 0;
	int mirrornv[3];

	pfo->is->getline(line, sizeof line);
	s = line;
	if(!s) return NULL;
	cur = s;
	s = quotok(&cur);
	name = (char*)malloc(strlen(s) + 1);
	strcpy(name, s);

	if(bones && *bones){
//		(*bones)[num] = malloc(sizeof(struct Bone));
		bone = (*bones)[num];
//		VECNULL(bone->joint);
//		bone->depth = 0;
//		bone->parent = NULL;
	}

	/* forward until vertex chunk */
	while((pfo->is->getline(line, sizeof line), !pfo->is->eof()) && !(cur = line, (s = quotok(&cur)) && !stricmp(s, "vertex"))){
		if(!stricmp(s, "shading"))
			shading = atoi(quotok(&cur));
		else if(!stricmp(s, "facet"))
			facet = atof(quotok(&cur));
		else if(!stricmp(s, "depth")){
			if(bone){
				bone->depth = atoi(quotok(&cur));
				if(num){
					int j;
					for(j = num - 1; 0 <= j; j--){
						if((*bones)[j]->depth < bone->depth){
							bone->parent = (*bones)[j];
							bone->nextSibling = (*bones)[j]->children;
							(*bones)[j]->children = bone;
							break;
						}
					}
				}
				else
					bone->parent = NULL;
			}
		}
		else if(!stricmp(s, "mirror")){
			mirror = atoi(quotok(&cur));
		}
		else if(!stricmp(s, "mirror_axis")){
			mirror_axis = atoi(quotok(&cur));

			// There could be multiple mirrors for a object, so we count it for allocating space.
			mirrors = 0;
			for(int m = 0; m < 3; m++) if(mirror_axis & (1 << m))
				mirrors++;
		}
	}

	if(!s)
		return 0;

	/* multiple vertex chunks leads to an error. */
	if(ret->v)
		return 0;

	s = quotok(&cur);
	ret->nv = n = atoi(s);
	// Mirroring generates twice as many vertices for each mirror, i.e. 2 power count of mirrors.
	ret->v = (Mesh::Coord(*)[3])malloc(n * (mirror ? 1 << mirrors : 1) * sizeof *ret->v);

	i = 0;
	while(i < n && (pfo->is->getline(line, sizeof line), s = line, !pfo->is->eof())){
		if(!s)
			return NULL;
		if(*s == '{')
			break;
		cur = line;
		for(j = 0; j < 3 && (s = quotok(&cur)); j++)
			ret->v[i][j] = (Mesh::Coord)atof(s) * (scale);
		i++;
	}

	if(mirror){
		for(int m = 0; m < 3; m++){
			// Check for each axis if it's flagged for mirroring.
			if(mirror_axis & (1 << m)){
				// Mirrored vertices have simply negated coordinate along axis perpendicular to the mirror.
				for(i = 0; i < n; i++){
					VECCPY(ret->v[i+n], ret->v[i]);
					ret->v[i+n][m] *= -1;
				}
				mirrornv[m] = n;
				n = ret->nv *= 2;
			}
		}
	}

	/* forward until face chunk */
	while((pfo->is->getline(line, sizeof line), !pfo->is->eof()) && !(cur = line, (s = quotok(&cur)) && !stricmp(s, "face")));

	/* multiple face chunks leads to an error. */
	if(ret->p)
		return 0;

	s = quotok(&cur);
	ret->np = n = atoi(s);
	// Mirroring generates twice as many vertices for each mirror, i.e. 2 power count of mirrors.
	ret->p = (Mesh::Primitive**)malloc(n * (mirror ? 1 << mirrors : 1) * sizeof *ret->p);

	i = 0;
	while(i <= n && (pfo->is->getline(line, sizeof line), s = line, !pfo->is->eof())){
		int polys;
		Mesh::ElemType type = Mesh::ET_Polygon;
		Mesh::Index verts[4], norms[4], uvs[4]; /* vertex count is capped at 4 in Metasequoia */
		if(!s)
			return NULL;
		if(*s == '{')
			break;
		else if(strchr(s, '}'))
			break;
		cur = line;
		s = quotok(&cur);
		polys = atoi(s);

		// Polygons with two vertices (edges) are treated as bone segments.
		if(polys == 2){
			 while(s = quotok(&cur)) if(!strnicmp(s, "V(", sizeof"V("-1)){
				char *p = &s[sizeof"V("-1];

				if(bone){
					int vind[2];
					avec3_t org;
					double sd;
					vind[0] = atoi(p);
					quotok(&p);
					vind[1] = atoi(p);

					// Set to measure distance from parent bonee's joint position.
					if(bone->parent){
						VECCPY(org, bone->parent->joint);
					}
					else{
						VECNULL(org);
					}

					// Choose the farther vertex of the edge as the bone joint, since the user of Metasequoia has no
					// way to figure out which is earlier in the data structure.
					if(VECSDIST(org, ret->v[vind[0]]) < VECSDIST(org, ret->v[vind[1]])){
						VECCPY(bone->joint, ret->v[vind[1]]);
					}
					else{
						VECCPY(bone->joint, ret->v[vind[0]]);
					}
				}
			}

			// Exclude this polygon (line) from drawing
			n--;
			ret->np--;
			continue;
		}
		else while(s = quotok(&cur)){

			/* cache vertex indices temporarily until presence of UV map is determined. */
			if(!strnicmp(s, "V(", sizeof"V("-1)){
				char *p = &s[sizeof"V("-1];

				/* face direction conversion */
				for(j = 0; j < polys; j++)
					verts[polys - j - 1] = (Mesh::Coord)strtol(p, &p, 10);

				/* Metasequoia never writes normal vector directions as part of data file,
				so we always need to calculate them, regardless of whether smoothshading is
				enabled or not.
				For drawing performance, we choose to calculate normal vectors here, not
				rendering or loading time of actual use. Sure we could add another polygon
				type to inform renderer to calculate them on runtime, but I prefer leaving
				runtime routine simpler (thus hopefully faster).
				The following code fragment is just the same as standard suf.c.*/
				{
					unsigned short a, b, c, vvi;
					double vv[3];
					int i = polys;

					/* there's an occasion that three consequative vertices lie on a line,
						so we need to find the valid triplet from all possible cases.
						note that polygon normal is calculated the same direction,
						as long as the polygon is convex. */
					for(a = 0; a < i; a++) for(b = a+1; b < i; b++) for(c = b+1; c < i; c++){
						double *v0, *v1, *v2;
						double v01[3], v02[3];
						v0 = ret->v[verts[a]];
						v1 = ret->v[verts[b]];
						v2 = ret->v[verts[c]];
						VECSUB(v01, v0, v1);
						VECSUB(v02, v0, v2);
						VECVP(vv, v01, v02);
						if(vv[0] != 0. || vv[1] != 0. || vv[2] != 0.)
							goto abc_break;
					}
	abc_break:

					/* polygon on a line */
					if(a == i){
						Mesh::Coord nullvec[3];
						VECNULL(nullvec);
						vvi = ret->add_vertex(nullvec);
						for(j = 0; j < i; j++)
							norms[j] = vvi;
						break;
					}

					/* this normalization isn't necessary, but
						it would improve memory space efficiency, for
						normal vectors tend to point the same direction
						with different length. */
					VECNORMIN(vv);

					vvi = ret->add_vertex(vv);
					for(j = 0; j < i; j++)
						norms[j] = vvi;
				}
			}
			else if(!strnicmp(s, "M(", sizeof"M("-1)){
				atr = (Mesh::Index)atoi(&s[sizeof"M("-1]);
				assert(atr < 30000);
			}
			else if(!strnicmp(s, "UV(", sizeof"UV("-1)){
				char *q = &s[sizeof"UV("-1];
				Mesh::Coord uv[3];
				type = Mesh::ET_UVPolygon;
				for(j = 0; j < polys; j++){
					uv[0] = strtod(q, &q);
					uv[1] = strtod(q, &q);
					uv[2] = 0.;
					uvs[polys - j - 1] = ret->add_vertex(uv);
				}
			}
		}

		if(atr == (Mesh::Index)-1){
			fprintf(stderr, "Error: Material is not specified! poly %d\n", i);
			return 0;
		}

		if(type == Mesh::ET_UVPolygon){
			struct Mesh::UVPolygon *p;
			type = Mesh::ET_UVPolygon;
			ret->p[i] = (Mesh::Primitive*)malloc(offsetof(Mesh::UVPolygon, v) + polys * sizeof(struct Mesh::UVPolygon::Vertex));
			p = &ret->p[i]->uv;
			p->t = Mesh::ET_UVPolygon;
			p->n = polys;
			p->atr = atr;
			for(j = 0; j < polys; j++){
				p->v[j].pos = verts[j];
				p->v[j].nrm = norms[j];
				p->v[j].tex = uvs[j];
			}
		}
		else{
			Mesh::Polygon *p;
			ret->p[i] = (Mesh::Primitive*)malloc(offsetof(Mesh::UVPolygon, v) + polys * sizeof(Mesh::Index[2]));
			p = &ret->p[i]->p;
			p->t = Mesh::ET_Polygon;
			p->n = polys;
			p->atr = atr;
			assert(p->atr < 30000);
			for(j = 0; j < polys; j++){
				p->v[j].pos = verts[j];
				p->v[j].nrm = norms[j];
			}
		}

		i++;
	}

	for(int m = 0; m < 3; m++) if(mirror_axis & (1 << m)){
		n = ret->np;
		for(i = 0; i < n; i++){
			if(ret->p[i]->t == Mesh::ET_UVPolygon){
				Mesh::UVPolygon *p, *p0 = &ret->p[i]->uv;
				ret->p[i+n] = (Mesh::Primitive*)malloc(offsetof(Mesh::UVPolygon, v) + p0->n * sizeof(Mesh::UVPolygon::Vertex));
				p = &ret->p[i+n]->uv;
				p->t = Mesh::ET_UVPolygon;
				p->n = p0->n;
				p->atr = p0->atr;
				for(j = 0; j < p0->n; j++){
					avec3_t vecn;
					// Flip face direction because it's mirrored.
					p->v[j].pos = p0->v[p0->n-j-1].pos + mirrornv[m];
					VECCPY(vecn, ret->v[p0->v[p0->n-j-1].nrm]);
					// Normal vector's coordinate along mirror axis must be negated just like position vector.
					vecn[m] *= -1;
					p->v[j].nrm = ret->add_vertex(vecn);
					p->v[j].tex = p0->v[p0->n-j-1].tex; // Keep texture coord to the same.
				}
			}
			else{
				Mesh::Polygon *p, *p0 = &ret->p[i]->p;
				ret->p[i+n] = (Mesh::Primitive*)malloc(offsetof(Mesh::Polygon, v) + p0->n * sizeof(Mesh::Index[2]));
				p = &ret->p[i+n]->p;
				p->t = Mesh::ET_Polygon;
				p->n = p0->n;
				p->atr = p0->atr;
				for(j = 0; j < p0->n; j++){
					avec3_t vecn;
					// Flip face direction because it's mirrored.
					p->v[j].pos = p0->v[p0->n-j-1].pos + mirrornv[m];
					VECCPY(vecn, ret->v[p0->v[p0->n-j-1].nrm]);
					// Normal vector's coordinate along mirror axis must be negated just like position vector.
					vecn[m] *= -1;
					p->v[j].nrm = ret->add_vertex(vecn);
				}
			}
		}
		ret->np *= 2;
	}

	if(shading){
		double cf;
		cf = cos(facet / deg_per_rad);
		for(i = 0; i < ret->np; i++) for(j = 0; j < ret->p[i]->uv.n; j++){
			int k, l, is = 0;
			Mesh::Polygon::Vertex *shares[32];
			Mesh::Polygon::Vertex &vertex = ret->p[i]->t == Mesh::ET_Polygon ? ret->p[i]->p.v[j] : ret->p[i]->uv.v[j];
			avec3_t norm;
			for(k = 0; k < ret->np; k++) for(l = 0; l < ret->p[k]->uv.n; l++){
				Mesh::Polygon::Vertex &vertex2 = ret->p[k]->t == Mesh::ET_Polygon ? ret->p[k]->p.v[l] : ret->p[k]->uv.v[l];
				if(vertex.pos == vertex2.pos && cf < VECSP(ret->v[vertex2.nrm], ret->v[vertex.nrm])){
					if(is == numof(shares))
						break;
					shares[is++] = &vertex2;
				}
			}
			for(k = 0; k < is; k++) if(shares[k]->nrm != vertex.nrm)
				break;
			if(k == is)
				continue;
			VECNULL(norm);
			for(k = 0; k < is; k++)
				VECADDIN(norm, ret->v[shares[k]->nrm]);
			VECNORMIN(norm);
			l = ret->add_vertex(norm);
			for(k = 0; k < is; k++)
				shares[k]->nrm = l;
		}
	}

	if(!(s = ftok(pfo)) || s[0] != '}')
		return 0;

	return 1;
}
Esempio n. 20
0
/*
 * Function adapted from David Eberly's distance tools (LGPL)
 * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
 */
static float nearest_point_in_tri_surface(const float *v0,const float *v1,const float *v2,const float *p, int *v, int *e, float *nearest )
{
	float diff[3];
	float e0[3];
	float e1[3];
	float A00;
	float A01;
	float A11;
	float B0;
	float B1;
	float C;
	float Det;
	float S;
	float T;
	float sqrDist;
	int lv = -1, le = -1;
	
	VECSUB(diff, v0, p);
	VECSUB(e0, v1, v0);
	VECSUB(e1, v2, v0);
	
	A00 = INPR ( e0, e0 );
	A01 = INPR( e0, e1 );
	A11 = INPR ( e1, e1 );
	B0 = INPR( diff, e0 );
	B1 = INPR( diff, e1 );
	C = INPR( diff, diff );
	Det = fabs( A00 * A11 - A01 * A01 );
	S = A01 * B1 - A11 * B0;
	T = A01 * B0 - A00 * B1;

	if ( S + T <= Det )
	{
		if ( S < 0.0f )
		{
			if ( T < 0.0f )  // Region 4
			{
				if ( B0 < 0.0f )
				{
					T = 0.0f;
					if ( -B0 >= A00 )
					{
						S = (float)1.0;
						sqrDist = A00 + 2.0f * B0 + C;
						lv = 1;
					}
					else
					{
						if(fabsf(A00) > FLT_EPSILON)
							S = -B0/A00;
						else
							S = 0.0f;
						sqrDist = B0 * S + C;
						le = 0;
					}
				}
				else
				{
					S = 0.0f;
					if ( B1 >= 0.0f )
					{
						T = 0.0f;
						sqrDist = C;
						lv = 0;
					}
					else if ( -B1 >= A11 )
					{
						T = 1.0f;
						sqrDist = A11 + 2.0f * B1 + C;
						lv = 2;
					}
					else
					{
						if(fabsf(A11) > FLT_EPSILON)
							T = -B1 / A11;
						else
							T = 0.0f;
						sqrDist = B1 * T + C;
						le = 1;
					}
				}
			}
			else  // Region 3
			{
				S = 0.0f;
				if ( B1 >= 0.0f )
				{
					T = 0.0f;
					sqrDist = C;
					lv = 0;
				}
				else if ( -B1 >= A11 )
				{
					T = 1.0f;
					sqrDist = A11 + 2.0f * B1 + C;
					lv = 2;
				}
				else
				{
					if(fabsf(A11) > FLT_EPSILON)
						T = -B1 / A11;
					else
						T = 0.0;
					sqrDist = B1 * T + C;
					le = 1;
				}
			}
		}
		else if ( T < 0.0f )  // Region 5
		{
			T = 0.0f;
			if ( B0 >= 0.0f )
			{
				S = 0.0f;
				sqrDist = C;
				lv = 0;
			}
			else if ( -B0 >= A00 )
			{
				S = 1.0f;
				sqrDist = A00 + 2.0f * B0 + C;
				lv = 1;
			}
			else
			{
				if(fabsf(A00) > FLT_EPSILON)
					S = -B0 / A00;
				else
					S = 0.0f;
				sqrDist = B0 * S + C;
				le = 0;
			}
		}
		else  // Region 0
		{
			// Minimum at interior lv
			float invDet;
			if(fabsf(Det) > FLT_EPSILON)
				invDet = 1.0f / Det;
			else
				invDet = 0.0f;
			S *= invDet;
			T *= invDet;
			sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0) +
					T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
		}
	}
	else
	{
		float tmp0, tmp1, numer, denom;

		if ( S < 0.0f )  // Region 2
		{
			tmp0 = A01 + B0;
			tmp1 = A11 + B1;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = A00 - 2.0f * A01 + A11;
				if ( numer >= denom )
				{
					S = 1.0f;
					T = 0.0f;
					sqrDist = A00 + 2.0f * B0 + C;
					lv = 1;
				}
				else
				{
					if(fabsf(denom) > FLT_EPSILON)
						S = numer / denom;
					else
						S = 0.0f;
					T = 1.0f - S;
					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
					le = 2;
				}
			}
			else
			{
				S = 0.0f;
				if ( tmp1 <= 0.0f )
				{
					T = 1.0f;
					sqrDist = A11 + 2.0f * B1 + C;
					lv = 2;
				}
				else if ( B1 >= 0.0f )
				{
					T = 0.0f;
					sqrDist = C;
					lv = 0;
				}
				else
				{
					if(fabsf(A11) > FLT_EPSILON)
						T = -B1 / A11;
					else
						T = 0.0f;
					sqrDist = B1 * T + C;
					le = 1;
				}
			}
		}
		else if ( T < 0.0f )  // Region 6
		{
			tmp0 = A01 + B1;
			tmp1 = A00 + B0;
			if ( tmp1 > tmp0 )
			{
				numer = tmp1 - tmp0;
				denom = A00 - 2.0f * A01 + A11;
				if ( numer >= denom )
				{
					T = 1.0f;
					S = 0.0f;
					sqrDist = A11 + 2.0f * B1 + C;
					lv = 2;
				}
				else
				{
					if(fabsf(denom) > FLT_EPSILON)
						T = numer / denom;
					else
						T = 0.0f;
					S = 1.0f - T;
					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
					le = 2;
				}
			}
			else
			{
				T = 0.0f;
				if ( tmp1 <= 0.0f )
				{
					S = 1.0f;
					sqrDist = A00 + 2.0f * B0 + C;
					lv = 1;
				}
				else if ( B0 >= 0.0f )
				{
					S = 0.0f;
					sqrDist = C;
					lv = 0;
				}
				else
				{
					if(fabsf(A00) > FLT_EPSILON)
						S = -B0 / A00;
					else
						S = 0.0f;
					sqrDist = B0 * S + C;
					le = 0;
				}
			}
		}
		else  // Region 1
		{
			numer = A11 + B1 - A01 - B0;
			if ( numer <= 0.0f )
			{
				S = 0.0f;
				T = 1.0f;
				sqrDist = A11 + 2.0f * B1 + C;
				lv = 2;
			}
			else
			{
				denom = A00 - 2.0f * A01 + A11;
				if ( numer >= denom )
				{
					S = 1.0f;
					T = 0.0f;
					sqrDist = A00 + 2.0f * B0 + C;
					lv = 1;
				}
				else
				{
					if(fabsf(denom) > FLT_EPSILON)
						S = numer / denom;
					else
						S = 0.0f;
					T = 1.0f - S;
					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
					le = 2;
				}
			}
		}
	}

	// Account for numerical round-off error
	if ( sqrDist < FLT_EPSILON )
		sqrDist = 0.0f;
	
	{
		float w[3], x[3], y[3], z[3];
		VECCOPY(w, v0);
		VECCOPY(x, e0);
		mul_v3_fl(x, S);
		VECCOPY(y, e1);
		mul_v3_fl(y, T);
		VECADD(z, w, x);
		VECADD(z, z, y);
		//VECSUB(d, p, z);
		VECCOPY(nearest, z);
		// d = p - ( v0 + S * e0 + T * e1 );
	}
	*v = lv;
	*e = le;

	return sqrDist;
}
Esempio n. 21
0
void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow)
{
	RegionView3D *rv3d= ar->regiondata;

	float viewnormal[3];
	int i, j, n, good_index;
	float d, d0, dd, ds;
	float *points = NULL;
	int numpoints = 0;
	float cor[3] = {1.,1.,1.};
	int gl_depth = 0, gl_blend = 0;

	/* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */
	float cv[][3] = {
		{1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f},
		{1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f}
	};

	// edges have the form edges[n][0][xyz] + t*edges[n][1][xyz]
	float edges[12][2][3] = {
		{{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}},

		{{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},
		{{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}},

		{{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}},
		{{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}
	};

	/* Fragment program to calculate the view3d of smoke */
	/* using 2 textures, density and shadow */
	const char *text = "!!ARBfp1.0\n"
					"PARAM dx = program.local[0];\n"
					"PARAM darkness = program.local[1];\n"
					"PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n"
					"TEMP temp, shadow, value;\n"
					"TEX temp, fragment.texcoord[0], texture[0], 3D;\n"
					"TEX shadow, fragment.texcoord[0], texture[1], 3D;\n"
					"MUL value, temp, darkness;\n"
					"MUL value, value, dx;\n"
					"MUL value, value, f;\n"
					"EX2 temp, -value.r;\n"
					"SUB temp.a, 1.0, temp.r;\n"
					"MUL temp.r, temp.r, shadow.r;\n"
					"MUL temp.g, temp.g, shadow.r;\n"
					"MUL temp.b, temp.b, shadow.r;\n"
					"MOV result.color, temp;\n"
					"END\n";
	GLuint prog;

	
	float size[3];

	if(!tex) {
		printf("Could not allocate 3D texture for 3D View smoke drawing.\n");
		return;
	}

	tstart();

	VECSUB(size, max, min);

	// maxx, maxy, maxz
	cv[0][0] = max[0];
	cv[0][1] = max[1];
	cv[0][2] = max[2];
	// minx, maxy, maxz
	cv[1][0] = min[0];
	cv[1][1] = max[1];
	cv[1][2] = max[2];
	// minx, miny, maxz
	cv[2][0] = min[0];
	cv[2][1] = min[1];
	cv[2][2] = max[2];
	// maxx, miny, maxz
	cv[3][0] = max[0];
	cv[3][1] = min[1];
	cv[3][2] = max[2];

	// maxx, maxy, minz
	cv[4][0] = max[0];
	cv[4][1] = max[1];
	cv[4][2] = min[2];
	// minx, maxy, minz
	cv[5][0] = min[0];
	cv[5][1] = max[1];
	cv[5][2] = min[2];
	// minx, miny, minz
	cv[6][0] = min[0];
	cv[6][1] = min[1];
	cv[6][2] = min[2];
	// maxx, miny, minz
	cv[7][0] = max[0];
	cv[7][1] = min[1];
	cv[7][2] = min[2];

	VECCOPY(edges[0][0], cv[4]); // maxx, maxy, minz
	VECCOPY(edges[1][0], cv[5]); // minx, maxy, minz
	VECCOPY(edges[2][0], cv[6]); // minx, miny, minz
	VECCOPY(edges[3][0], cv[7]); // maxx, miny, minz

	VECCOPY(edges[4][0], cv[3]); // maxx, miny, maxz
	VECCOPY(edges[5][0], cv[2]); // minx, miny, maxz
	VECCOPY(edges[6][0], cv[6]); // minx, miny, minz
	VECCOPY(edges[7][0], cv[7]); // maxx, miny, minz

	VECCOPY(edges[8][0], cv[1]); // minx, maxy, maxz
	VECCOPY(edges[9][0], cv[2]); // minx, miny, maxz
	VECCOPY(edges[10][0], cv[6]); // minx, miny, minz
	VECCOPY(edges[11][0], cv[5]); // minx, maxy, minz

	// printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]);
	// printf("min[2]: %f, max[2]: %f\n", min[2], max[2]);

	edges[0][1][2] = size[2];
	edges[1][1][2] = size[2];
	edges[2][1][2] = size[2];
	edges[3][1][2] = size[2];

	edges[4][1][1] = size[1];
	edges[5][1][1] = size[1];
	edges[6][1][1] = size[1];
	edges[7][1][1] = size[1];

	edges[8][1][0] = size[0];
	edges[9][1][0] = size[0];
	edges[10][1][0] = size[0];
	edges[11][1][0] = size[0];

	glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend);
	glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth);

	glLoadMatrixf(rv3d->viewmat);
	// glMultMatrixf(ob->obmat);	

	glDepthMask(GL_FALSE);
	glDisable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	/*
	printf("Viewinv:\n");
	printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]);
	printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]);
	printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]);
	*/

	// get view vector
	VECCOPY(viewnormal, rv3d->viewinv[2]);
	normalize_v3(viewnormal);

	// find cube vertex that is closest to the viewer
	for (i=0; i<8; i++) {
		float x,y,z;

		x = cv[i][0] - viewnormal[0];
		y = cv[i][1] - viewnormal[1];
		z = cv[i][2] - viewnormal[2];

		if ((x>=min[0])&&(x<=max[0])
			&&(y>=min[1])&&(y<=max[1])
			&&(z>=min[2])&&(z<=max[2])) {
			break;
		}
	}

	if(i >= 8) {
		/* fallback, avoid using buffer over-run */
		i= 0;
	}

	// printf("i: %d\n", i);
	// printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]);

	if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program"))
	{
		glEnable(GL_FRAGMENT_PROGRAM_ARB);
		glGenProgramsARB(1, &prog);

		glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog);
		glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text);

		// cell spacing
		glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0);
		// custom parameter for smoke style (higher = thicker)
		glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0);
	}
	else
		printf("Your gfx card does not support 3D View smoke drawing.\n");

	GPU_texture_bind(tex, 0);
	if(tex_shadow)
		GPU_texture_bind(tex_shadow, 1);
	else
		printf("No volume shadow\n");

	if (!GPU_non_power_of_two_support()) {
		cor[0] = (float)res[0]/(float)larger_pow2(res[0]);
		cor[1] = (float)res[1]/(float)larger_pow2(res[1]);
		cor[2] = (float)res[2]/(float)larger_pow2(res[2]);
	}

	// our slices are defined by the plane equation a*x + b*y +c*z + d = 0
	// (a,b,c), the plane normal, are given by viewdir
	// d is the parameter along the view direction. the first d is given by
	// inserting previously found vertex into the plane equation
	d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]);
	ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]);
	dd = 0.05; // ds/512.0f;
	n = 0;
	good_index = i;

	// printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds);

	points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview");

	while(1) {
		float p0[3];
		float tmp_point[3], tmp_point2[3];

		if(dd*(float)n > ds)
			break;

		VECCOPY(tmp_point, viewnormal);
		mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n));
		VECADD(tmp_point2, cv[good_index], tmp_point);
		d = INPR(tmp_point2, viewnormal);

		// printf("my d: %f\n", d);

		// intersect_edges returns the intersection points of all cube edges with
		// the given plane that lie within the cube
		numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges);

		// printf("points: %d\n", numpoints);

		if (numpoints > 2) {
			VECCOPY(p0, points);

			// sort points to get a convex polygon
			for(i = 1; i < numpoints - 1; i++)
			{
				for(j = i + 1; j < numpoints; j++)
				{
					if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3]))
					{
						float tmp2[3];
						VECCOPY(tmp2, &points[j * 3]);
						VECCOPY(&points[j * 3], &points[i * 3]);
						VECCOPY(&points[i * 3], tmp2);
					}
				}
			}

			// printf("numpoints: %d\n", numpoints);
			glBegin(GL_POLYGON);
			glColor3f(1.0, 1.0, 1.0);
			for (i = 0; i < numpoints; i++) {
				glTexCoord3d((points[i * 3 + 0] - min[0] )*cor[0]/size[0], (points[i * 3 + 1] - min[1])*cor[1]/size[1], (points[i * 3 + 2] - min[2])*cor[2]/size[2]);
				glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]);
			}
			glEnd();
		}
		n++;
	}

	tend();
	// printf ( "Draw Time: %f\n",( float ) tval() );

	if(tex_shadow)
		GPU_texture_unbind(tex_shadow);
	GPU_texture_unbind(tex);

	if(GLEW_ARB_fragment_program)
	{
		glDisable(GL_FRAGMENT_PROGRAM_ARB);
		glDeleteProgramsARB(1, &prog);
	}


	MEM_freeN(points);

	if(!gl_blend)
		glDisable(GL_BLEND);
	if(gl_depth)
	{
		glEnable(GL_DEPTH_TEST);
		glDepthMask(GL_TRUE);	
	}
}
Esempio n. 22
0
int Fbonded_eval_impr_term(Fbonded *p,
    const ImprPrm *prm,
    const dvec *pos_i,
    const dvec *pos_j,
    const dvec *pos_k,
    const dvec *pos_l,
    dvec *f_i,
    dvec *f_j,
    dvec *f_k,
    dvec *f_l,
    dreal *u,
    dreal virial[NELEMS_VIRIAL]) {
  dvec r12, r23, r34;
  dvec A, B, C;
  dreal rA, rB, rC;
  dreal cos_phi, sin_phi, phi;
  dreal K, K1;
  dvec f1, f2, f3;

  dreal k = prm->k_impr;
  dreal delta = prm->psi0;
  dreal diff;

  Domain_shortest_vec(p->domain, &r12, pos_i, pos_j);
  Domain_shortest_vec(p->domain, &r23, pos_j, pos_k);
  Domain_shortest_vec(p->domain, &r34, pos_k, pos_l);

  VECCROSS(A, r12, r23);
  VECCROSS(B, r23, r34);
  VECCROSS(C, r23, A);

  rA = 1 / sqrt(VECLEN2(A));
  rB = 1 / sqrt(VECLEN2(B));
  rC = 1 / sqrt(VECLEN2(C));

  VECMUL(B, rB, B);  /* normalize B */
  cos_phi = VECDOT(A, B) * rA;
  sin_phi = VECDOT(C, B) * rC;

  phi = -atan2(sin_phi, cos_phi);

  diff = phi - delta;
  if      (diff < -M_PI)  diff += 2.0 * M_PI;
  else if (diff >  M_PI)  diff -= 2.0 * M_PI;
  K = k * diff * diff;
  K1 = 2.0 * k * diff;

  if (fabs(sin_phi) > 0.1) {
    dvec dcosdA, dcosdB;
    dvec tv1, tv2;

    /* use sine version to avoid 1/cos terms */

    VECMUL(A, rA, A);  /* normalize A */
    VECMSUB(dcosdA, cos_phi, A, B);
    VECMUL(dcosdA, rA, dcosdA);
    VECMSUB(dcosdB, cos_phi, B, A);
    VECMUL(dcosdB, rB, dcosdB);

    K1 /= sin_phi;
    VECCROSS(f1, r23, dcosdA);
    VECMUL(f1, K1, f1);
    VECCROSS(f3, dcosdB, r23);
    VECMUL(f3, K1, f3);

    VECCROSS(tv1, dcosdA, r12);
    VECCROSS(tv2, r34, dcosdB);
    VECADD(f2, tv1, tv2);
    VECMUL(f2, K1, f2);
  }
  else {
    dvec dsindB, dsindC;

    /* phi is too close to 0 or pi, use cos version to avoid 1/sin */

    VECMUL(C, rC, C);  /* normalize C */
    VECMSUB(dsindC, sin_phi, C, B);
    VECMUL(dsindC, rC, dsindC);
    VECMSUB(dsindB, sin_phi, B, C);
    VECMUL(dsindB, rB, dsindB);

    K1 /= -cos_phi;
    f1.x = K1 * ((r23.y * r23.y + r23.z * r23.z) * dsindC.x
                 - r23.x * r23.y * dsindC.y
                 - r23.x * r23.z * dsindC.z);
    f1.y = K1 * ((r23.z * r23.z + r23.x * r23.x) * dsindC.y
                 - r23.y * r23.z * dsindC.z
                 - r23.y * r23.x * dsindC.x);
    f1.z = K1 * ((r23.x * r23.x + r23.y * r23.y) * dsindC.z
                 - r23.z * r23.x * dsindC.x
                 - r23.z * r23.y * dsindC.y);

    VECCROSS(f3, dsindB, r23);
    VECMUL(f3, K1, f3);

    f2.x = K1 * (-(r23.y * r12.y + r23.z * r12.z) * dsindC.x
                 + (2.0 * r23.x * r12.y - r12.x * r23.y) * dsindC.y
                 + (2.0 * r23.x * r12.z - r12.x * r23.z) * dsindC.z
                 + dsindB.z * r34.y - dsindB.y * r34.z);
    f2.y = K1 * (-(r23.z * r12.z + r23.x * r12.x) * dsindC.y
                 + (2.0 * r23.y * r12.z - r12.y * r23.z) * dsindC.z
                 + (2.0 * r23.y * r12.x - r12.y * r23.x) * dsindC.x
                 + dsindB.x * r34.z - dsindB.z * r34.x);
    f2.z = K1 * (-(r23.x * r12.x + r23.y * r12.y) * dsindC.z
                 + (2.0 * r23.z * r12.x - r12.z * r23.x) * dsindC.x
                 + (2.0 * r23.z * r12.y - r12.z * r23.y) * dsindC.y
                 + dsindB.y * r34.x - dsindB.x * r34.y);
  }
  *u += K;
  VECADD(*f_i, *f_i, f1);
  f_j->x += f2.x - f1.x;
  f_j->y += f2.y - f1.y;
  f_j->z += f2.z - f1.z;
  f_k->x += f3.x - f2.x;
  f_k->y += f3.y - f2.y;
  f_k->z += f3.z - f2.z;
  VECSUB(*f_l, *f_l, f3);
  virial[VIRIAL_XX] += (f1.x * r12.x + f2.x * r23.x + f3.x * r34.x);
  virial[VIRIAL_XY] += (f1.x * r12.y + f2.x * r23.y + f3.x * r34.y);
  virial[VIRIAL_XZ] += (f1.x * r12.z + f2.x * r23.z + f3.x * r34.z);
  virial[VIRIAL_YY] += (f1.y * r12.y + f2.y * r23.y + f3.y * r34.y);
  virial[VIRIAL_YZ] += (f1.y * r12.z + f2.y * r23.z + f3.y * r34.z);
  virial[VIRIAL_ZZ] += (f1.z * r12.z + f2.z * r23.z + f3.z * r34.z);
  return OK;
}
Esempio n. 23
0
static void connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
{
	ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys);
	ParticleData *pa;
	PTCacheEdit *edit;
	PTCacheEditPoint *point;
	PTCacheEditKey *ekey = NULL;
	HairKey *key;
	BVHTreeFromMesh bvhtree= {NULL};
	BVHTreeNearest nearest;
	MFace *mface;
	DerivedMesh *dm = NULL;
	int numverts;
	int i, k;
	float hairmat[4][4], imat[4][4];
	float v[4][3], vec[3];

	if(!psys || !psys->part || psys->part->type != PART_HAIR)
		return;
	
	edit= psys->edit;
	point=  edit ? edit->points : NULL;
	
	if(psmd->dm->deformedOnly)
		/* we don't want to mess up psmd->dm when converting to global coordinates below */
		dm= CDDM_copy(psmd->dm);
	else
		dm= mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);

	numverts = dm->getNumVerts (dm);

	/* convert to global coordinates */
	for (i=0; i<numverts; i++)
		mul_m4_v3(ob->obmat, CDDM_get_vert(dm, i)->co);

	bvhtree_from_mesh_faces(&bvhtree, dm, 0.0, 2, 6);

	for(i=0, pa= psys->particles; i<psys->totpart; i++,pa++) {
		key = pa->hair;

		nearest.index = -1;
		nearest.dist = FLT_MAX;

		BLI_bvhtree_find_nearest(bvhtree.tree, key->co, &nearest, bvhtree.nearest_callback, &bvhtree);

		if(nearest.index == -1) {
			if (G.f & G_DEBUG)
				printf("No nearest point found for hair root!");
			continue;
		}

		mface = CDDM_get_face(dm,nearest.index);

		copy_v3_v3(v[0], CDDM_get_vert(dm,mface->v1)->co);
		copy_v3_v3(v[1], CDDM_get_vert(dm,mface->v2)->co);
		copy_v3_v3(v[2], CDDM_get_vert(dm,mface->v3)->co);
		if(mface->v4) {
			copy_v3_v3(v[3], CDDM_get_vert(dm,mface->v4)->co);
			interp_weights_poly_v3( pa->fuv,v, 4, nearest.co);
		}
		else
			interp_weights_poly_v3( pa->fuv,v, 3, nearest.co);

		pa->num = nearest.index;
		pa->num_dmcache = psys_particle_dm_face_lookup(ob,psmd->dm,pa->num,pa->fuv,NULL);
		
		psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
		invert_m4_m4(imat,hairmat);

		VECSUB(vec, nearest.co, key->co);

		if(point) {
			ekey = point->keys;
			point++;
		}

		for(k=0,key=pa->hair; k<pa->totkey; k++,key++) {
			VECADD(key->co, key->co, vec);
			mul_m4_v3(imat,key->co);

			if(ekey) {
				ekey->flag |= PEK_USE_WCO;
				ekey++;
			}
		}
	}

	free_bvhtree_from_mesh(&bvhtree);
	dm->release(dm);

	psys_free_path_cache(psys, psys->edit);

	psys->flag &= ~PSYS_GLOBAL_HAIR;

	PE_update_object(scene, ob, 0);
}
Esempio n. 24
0
// set the currently used goal position ---------------------------------------
//
void BOT_AI::_GoalCheck_AgentMode_Attack()
{
	//FIXME: push current goal onto goal stack
	BOT_Goal* pGoal	= m_State.GetCurGoal();
	ASSERT( pGoal != NULL );

	//FIXME: here we should also evaluate whether we pick another target

	// select a target, if none, or no ship selected as target 
	GenObject*	pTargetObject = pGoal->GetTargetObject();
	Vector3*	pGoalPos		 = pGoal->GetGoalPosition();
	if( ( pTargetObject == NULL ) || ( OBJECT_TYPE_SHIP( pTargetObject) == FALSE ) ){

		// let the character select a target
		pTargetObject = m_Character.SelectAttackTarget( m_pShip );

		// no target
		if ( pTargetObject == NULL ) {
			//FIXME: transition function
			m_nAgentMode = AGENTMODE_IDLE;
			pGoal->SetTargetObject(NULL);

#ifdef BOT_LOGFILES
			BOT_MsgOut( "switching from ATTACK to IDLE" );
#endif // BOT_LOGFILES

			return;
		}

		// set the target object
		pGoal->SetTargetObject( pTargetObject );

		// set the goal position to where the target is
		FetchTVector( pTargetObject->ObjPosition, pGoalPos );

#ifdef BOT_LOGFILES
		BOT_MsgOut( "found new ATTACK target %d", pTargetObject->HostObjNumber );
#endif // BOT_LOGFILES

	}

	Vector3	TargetPos;
	FetchTVector( pTargetObject->ObjPosition, &TargetPos );

	// get vector to target
	Vector3 vec2Target;	
	VECSUB( &vec2Target, &TargetPos, &m_AgentPos );

	float len = VctLenX( &vec2Target );
#ifdef BOT_LOGFILES
	BOT_MsgOut( "BOT: distance to target: %f", len );
#endif
#define MIN_DISTANCE_TO_TARGET 100.0f
        if ( len < 500.0F) {
			    if ( FireRepeat > 0 ) {
			       FireRepeat -= CurScreenRefFrames;
        		}
                if ( ( FireRepeat > 0 ) || ( FireDisable > 0 ) ) {
		    //do nothing!
                } else {
      
                // create laser
                   OBJ_ShootLaser( m_pShip );

                   if ( ( FireRepeat  += MyShip->FireRepeatDelay  ) <= 0 ) {
                      FireRepeat = 1;
                   }
                   if ( ( FireDisable += MyShip->FireDisableDelay ) <= 0 ) {
                      FireDisable = 1;
                   }
		}
	}
	if ( len < MIN_DISTANCE_TO_TARGET )  {
                		
		// if nearby goal, we stay where we are
		memcpy( pGoalPos, &m_AgentPos, sizeof( Vector3 ) );
               
        } else {

		// set the goal position to the position of the target
		ASSERT( pTargetObject != NULL );
		FetchTVector( pTargetObject->ObjPosition, pGoalPos );
	}

#ifdef BOT_LOGFILES
	BOT_MsgOut( "ATTACK goal is at %f %f %f", pGoalPos->X, pGoalPos->Y, pGoalPos->Z );
#endif // BOT_LOGFILES
}
Esempio n. 25
0
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm )
{
	Cloth *cloth = clmd->clothObject;
	ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL;
	unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0;
	unsigned int i = 0;
	unsigned int numverts = (unsigned int)dm->getNumVerts ( dm );
	unsigned int numedges = (unsigned int)dm->getNumEdges ( dm );
	unsigned int numfaces = (unsigned int)dm->getNumFaces ( dm );
	MEdge *medge = dm->getEdgeArray ( dm );
	MFace *mface = dm->getFaceArray ( dm );
	int index2 = 0; // our second vertex index
	LinkNode **edgelist = NULL;
	EdgeHash *edgehash = NULL;
	LinkNode *search = NULL, *search2 = NULL;
	float temp[3];
	
	// error handling
	if ( numedges==0 )
		return 0;

	cloth->springs = NULL;

	edgelist = MEM_callocN ( sizeof ( LinkNode * ) * numverts, "cloth_edgelist_alloc" );
	
	if(!edgelist)
		return 0;
	
	for ( i = 0; i < numverts; i++ )
	{
		edgelist[i] = NULL;
	}

	if ( cloth->springs )
		MEM_freeN ( cloth->springs );

	// create spring network hash
	edgehash = BLI_edgehash_new();

	// structural springs
	for ( i = 0; i < numedges; i++ )
	{
		spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );

		if ( spring )
		{
			spring->ij = MIN2(medge[i].v1, medge[i].v2);
			spring->kl = MAX2(medge[i].v2, medge[i].v1);
			VECSUB ( temp, cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest );
			spring->restlen =  sqrt ( INPR ( temp, temp ) );
			clmd->sim_parms->avg_spring_len += spring->restlen;
			cloth->verts[spring->ij].avg_spring_len += spring->restlen;
			cloth->verts[spring->kl].avg_spring_len += spring->restlen;
			cloth->verts[spring->ij].spring_count++;
			cloth->verts[spring->kl].spring_count++;
			spring->type = CLOTH_SPRING_TYPE_STRUCTURAL;
			spring->flags = 0;
			spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0;
			struct_springs++;
			
			BLI_linklist_prepend ( &cloth->springs, spring );
		}
		else
		{
			cloth_free_errorsprings(cloth, edgehash, edgelist);
			return 0;
		}
	}
	
	if(struct_springs > 0)
		clmd->sim_parms->avg_spring_len /= struct_springs;
	
	for(i = 0; i < numverts; i++)
	{
		cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49 / ((float)cloth->verts[i].spring_count);
	}
	
	// shear springs
	for ( i = 0; i < numfaces; i++ )
	{
		// triangle faces already have shear springs due to structural geometry
		if ( !mface[i].v4 )
			continue; 
		
		spring = ( ClothSpring *) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
		
		if(!spring)
		{
			cloth_free_errorsprings(cloth, edgehash, edgelist);
			return 0;
		}

		spring->ij = MIN2(mface[i].v1, mface[i].v3);
		spring->kl = MAX2(mface[i].v3, mface[i].v1);
		VECSUB ( temp, cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest );
		spring->restlen =  sqrt ( INPR ( temp, temp ) );
		spring->type = CLOTH_SPRING_TYPE_SHEAR;
		spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0;

		BLI_linklist_append ( &edgelist[spring->ij], spring );
		BLI_linklist_append ( &edgelist[spring->kl], spring );
		shear_springs++;

		BLI_linklist_prepend ( &cloth->springs, spring );

		
		// if ( mface[i].v4 ) --> Quad face
		spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
		
		if(!spring)
		{
			cloth_free_errorsprings(cloth, edgehash, edgelist);
			return 0;
		}

		spring->ij = MIN2(mface[i].v2, mface[i].v4);
		spring->kl = MAX2(mface[i].v4, mface[i].v2);
		VECSUB ( temp, cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest );
		spring->restlen =  sqrt ( INPR ( temp, temp ) );
		spring->type = CLOTH_SPRING_TYPE_SHEAR;
		spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0;

		BLI_linklist_append ( &edgelist[spring->ij], spring );
		BLI_linklist_append ( &edgelist[spring->kl], spring );
		shear_springs++;

		BLI_linklist_prepend ( &cloth->springs, spring );
	}
	
	if(numfaces) {
		// bending springs
		search2 = cloth->springs;
		for ( i = struct_springs; i < struct_springs+shear_springs; i++ )
		{
			if ( !search2 )
				break;

			tspring2 = search2->link;
			search = edgelist[tspring2->kl];
			while ( search )
			{
				tspring = search->link;
				index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) );
				
				// check for existing spring
				// check also if startpoint is equal to endpoint
				if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) )
				&& ( index2!=tspring2->ij ) )
				{
					spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
					
					if(!spring)
					{
						cloth_free_errorsprings(cloth, edgehash, edgelist);
						return 0;
					}

					spring->ij = MIN2(tspring2->ij, index2);
					spring->kl = MAX2(tspring2->ij, index2);
					VECSUB ( temp, cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest );
					spring->restlen =  sqrt ( INPR ( temp, temp ) );
					spring->type = CLOTH_SPRING_TYPE_BENDING;
					spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0;
					BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL );
					bend_springs++;

					BLI_linklist_prepend ( &cloth->springs, spring );
				}
				search = search->next;
			}
			search2 = search2->next;
		}
	}
	else if(struct_springs > 2) {
		/* bending springs for hair strands */
		/* The current algorightm only goes through the edges in order of the mesh edges list	*/
		/* and makes springs between the outer vert of edges sharing a vertice. This works just */
		/* fine for hair, but not for user generated string meshes. This could/should be later	*/
		/* extended to work with non-ordered edges so that it can be used for general "rope		*/
		/* dynamics" without the need for the vertices or edges to be ordered through the length*/
		/* of the strands. -jahka */
		search = cloth->springs;
		search2 = search->next;
		while(search && search2)
		{
			tspring = search->link;
			tspring2 = search2->link;

			if(tspring->ij == tspring2->kl) {
				spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
				
				if(!spring)
				{
					cloth_free_errorsprings(cloth, edgehash, edgelist);
					return 0;
				}

				spring->ij = tspring2->ij;
				spring->kl = tspring->kl;
				VECSUB ( temp, cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest );
				spring->restlen =  sqrt ( INPR ( temp, temp ) );
				spring->type = CLOTH_SPRING_TYPE_BENDING;
				spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0;
				bend_springs++;

				BLI_linklist_prepend ( &cloth->springs, spring );
			}
			
			search = search->next;
			search2 = search2->next;
		}
	}
	
	/* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */
	for ( i = 0; i < numedges; i++ ) // struct springs
		BLI_edgehash_insert ( edgehash, MIN2(medge[i].v1, medge[i].v2), MAX2(medge[i].v2, medge[i].v1), NULL );
	
	for ( i = 0; i < numfaces; i++ ) // edge springs
	{
		if(mface[i].v4)
		{
			BLI_edgehash_insert ( edgehash, MIN2(mface[i].v1, mface[i].v3), MAX2(mface[i].v3, mface[i].v1), NULL );
			
			BLI_edgehash_insert ( edgehash, MIN2(mface[i].v2, mface[i].v4), MAX2(mface[i].v2, mface[i].v4), NULL );
		}
	}
	
	
	cloth->numsprings = struct_springs + shear_springs + bend_springs;
	
	if ( edgelist )
	{
		for ( i = 0; i < numverts; i++ )
		{
			BLI_linklist_free ( edgelist[i],NULL );
		}
	
		MEM_freeN ( edgelist );
	}
	
	cloth->edgehash = edgehash;
	
	if(G.rt>0)
		printf("avg_len: %f\n",clmd->sim_parms->avg_spring_len);

	return 1;

} /* cloth_build_springs */
Esempio n. 26
0
File: smoke.c Progetto: jinjoh/NOOR
int smokeModifier_init (SmokeModifierData *smd, Object *ob, Scene *scene, DerivedMesh *dm)
{
	if((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain && !smd->domain->fluid)
	{
		size_t i;
		float min[3] = {FLT_MAX, FLT_MAX, FLT_MAX}, max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
		float size[3];
		MVert *verts = dm->getVertArray(dm);
		float scale = 0.0;
		int res;		

		res = smd->domain->maxres;

		// get BB of domain
		for(i = 0; i < dm->getNumVerts(dm); i++)
		{
			float tmp[3];

			VECCOPY(tmp, verts[i].co);
			Mat4MulVecfl(ob->obmat, tmp);

			// min BB
			min[0] = MIN2(min[0], tmp[0]);
			min[1] = MIN2(min[1], tmp[1]);
			min[2] = MIN2(min[2], tmp[2]);

			// max BB
			max[0] = MAX2(max[0], tmp[0]);
			max[1] = MAX2(max[1], tmp[1]);
			max[2] = MAX2(max[2], tmp[2]);
		}

		VECCOPY(smd->domain->p0, min);
		VECCOPY(smd->domain->p1, max);

		// calc other res with max_res provided
		VECSUB(size, max, min);

		// printf("size: %f, %f, %f\n", size[0], size[1], size[2]);

		// prevent crash when initializing a plane as domain
		if((size[0] < FLT_EPSILON) || (size[1] < FLT_EPSILON) || (size[2] < FLT_EPSILON))
			return 0;

		if(size[0] > size[1])
		{
			if(size[0] > size[1])
			{
				scale = res / size[0];
				smd->domain->dx = size[0] / res;
				smd->domain->res[0] = res;
				smd->domain->res[1] = (int)(size[1] * scale + 0.5);
				smd->domain->res[2] = (int)(size[2] * scale + 0.5);
			}
			else
			{
				scale = res / size[1];
				smd->domain->dx = size[1] / res;
				smd->domain->res[1] = res;
				smd->domain->res[0] = (int)(size[0] * scale + 0.5);
				smd->domain->res[2] = (int)(size[2] * scale + 0.5);
			}
		}
		else
		{
			if(size[1] > size[2])
			{
				scale = res / size[1];
				smd->domain->dx = size[1] / res;
				smd->domain->res[1] = res;
				smd->domain->res[0] = (int)(size[0] * scale + 0.5);
				smd->domain->res[2] = (int)(size[2] * scale + 0.5);
			}
			else
			{
				scale = res / size[2];
				smd->domain->dx = size[2] / res;
				smd->domain->res[2] = res;
				smd->domain->res[0] = (int)(size[0] * scale + 0.5);
				smd->domain->res[1] = (int)(size[1] * scale + 0.5);
			}
		}

		// printf("smd->domain->dx: %f\n", smd->domain->dx);

		// TODO: put in failsafe if res<=0 - dg

		// printf("res[0]: %d, res[1]: %d, res[2]: %d\n", smd->domain->res[0], smd->domain->res[1], smd->domain->res[2]);
		// dt max is 0.1
		smd->domain->fluid = smoke_init(smd->domain->res, smd->domain->p0, 0.1);
		smd->time = scene->r.cfra;

		if(smd->domain->flags & MOD_SMOKE_HIGHRES)
		{
			smd->domain->wt = smoke_turbulence_init(smd->domain->res, smd->domain->amplify + 1, smd->domain->noise);
			smd->domain->res_wt[0] = smd->domain->res[0] * (smd->domain->amplify + 1);
			smd->domain->res_wt[1] = smd->domain->res[1] * (smd->domain->amplify + 1);			
			smd->domain->res_wt[2] = smd->domain->res[2] * (smd->domain->amplify + 1);			
			smd->domain->dx_wt = smd->domain->dx / (smd->domain->amplify + 1);		
			// printf("smd->domain->amplify: %d\n",  smd->domain->amplify);
			// printf("(smd->domain->flags & MOD_SMOKE_HIGHRES)\n");
		}

		if(!smd->domain->shadow)
			smd->domain->shadow = MEM_callocN(sizeof(float) * smd->domain->res[0] * smd->domain->res[1] * smd->domain->res[2], "SmokeDomainShadow");

		smoke_initBlenderRNA(smd->domain->fluid, &(smd->domain->alpha), &(smd->domain->beta));

		if(smd->domain->wt)	
		{
			smoke_initWaveletBlenderRNA(smd->domain->wt, &(smd->domain->strength));
			// printf("smoke_initWaveletBlenderRNA\n");
		}
		return 1;
	}
	else if((smd->type & MOD_SMOKE_TYPE_FLOW) && smd->flow)
	{
		// handle flow object here
		// XXX TODO

		smd->time = scene->r.cfra;

		// update particle lifetime to be one frame
		// smd->flow->psys->part->lifetime = scene->r.efra + 1;
/*
		if(!smd->flow->bvh)
		{
			// smd->flow->bvh = MEM_callocN(sizeof(BVHTreeFromMesh), "smoke_bvhfromfaces");
			// bvhtree_from_mesh_faces(smd->flow->bvh, dm, 0.0, 2, 6);

			// copy obmat
			// Mat4CpyMat4(smd->flow->mat, ob->obmat);
			// Mat4CpyMat4(smd->flow->mat_old, ob->obmat);
		}
*/

		return 1;
	}
	else if((smd->type & MOD_SMOKE_TYPE_COLL))
	{
		smd->time = scene->r.cfra;

		// todo: delete this when loading colls work -dg
		if(!smd->coll)
			smokeModifier_createType(smd);

		if(!smd->coll->points)
		{
			// init collision points
			SmokeCollSettings *scs = smd->coll;

			// copy obmat
			Mat4CpyMat4(scs->mat, ob->obmat);
			Mat4CpyMat4(scs->mat_old, ob->obmat);

			fill_scs_points(ob, dm, scs);
		}

		if(!smd->coll->bvhtree)
		{
			smd->coll->bvhtree = NULL; // bvhtree_build_from_smoke ( ob->obmat, dm->getFaceArray(dm), dm->getNumFaces(dm), dm->getVertArray(dm), dm->getNumVerts(dm), 0.0 );
		}
		return 1;
	}

	return 1;
}
Esempio n. 27
0
File: smoke.c Progetto: jinjoh/NOOR
static void fill_scs_points(Object *ob, DerivedMesh *dm, SmokeCollSettings *scs)
{
	MVert *mvert = dm->getVertArray(dm);
	MFace *mface = dm->getFaceArray(dm);
	int i = 0, divs = 0;
	int *tridivs = NULL;
	float cell_len = 1.0 / 50.0; // for res = 50
	int newdivs = 0;
	int quads = 0, facecounter = 0;

	// count quads
	for(i = 0; i < dm->getNumFaces(dm); i++)
	{
		if(mface[i].v4)
			quads++;
	}

	calcTriangleDivs(ob, mvert, dm->getNumVerts(dm), mface,  dm->getNumFaces(dm), dm->getNumFaces(dm) + quads, &tridivs, cell_len);

	// count triangle divisions
	for(i = 0; i < dm->getNumFaces(dm) + quads; i++)
	{
		divs += (tridivs[3 * i] + 1) * (tridivs[3 * i + 1] + 1) * (tridivs[3 * i + 2] + 1);
	}

	// printf("divs: %d\n", divs);

	scs->points = MEM_callocN(sizeof(float) * (dm->getNumVerts(dm) + divs) * 3, "SmokeCollPoints");

	for(i = 0; i < dm->getNumVerts(dm); i++)
	{
		float tmpvec[3];
		VECCOPY(tmpvec, mvert[i].co);
		Mat4MulVecfl (ob->obmat, tmpvec);
		VECCOPY(&scs->points[i * 3], tmpvec);
	}
	
	for(i = 0, facecounter = 0; i < dm->getNumFaces(dm); i++)
	{
		int again = 0;
		do
		{
			int j, k;
			int divs1 = tridivs[3 * facecounter + 0];
			int divs2 = tridivs[3 * facecounter + 1];
			//int divs3 = tridivs[3 * facecounter + 2];
			float side1[3], side2[3], trinormorg[3], trinorm[3];
			
			if(again == 1 && mface[i].v4)
			{
				VECSUB(side1,  mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
				VECSUB(side2,  mvert[ mface[i].v4 ].co, mvert[ mface[i].v1 ].co);
			}
			else
			{
				VECSUB(side1,  mvert[ mface[i].v2 ].co, mvert[ mface[i].v1 ].co);
				VECSUB(side2,  mvert[ mface[i].v3 ].co, mvert[ mface[i].v1 ].co);
			}

			Crossf(trinormorg, side1, side2);
			Normalize(trinormorg);
			VECCOPY(trinorm, trinormorg);
			VecMulf(trinorm, 0.25 * cell_len);

			for(j = 0; j <= divs1; j++)
			{
				for(k = 0; k <= divs2; k++)
				{
					float p1[3], p2[3], p3[3], p[3]={0,0,0}; 
					const float uf = (float)(j + TRI_UVOFFSET) / (float)(divs1 + 0.0);
					const float vf = (float)(k + TRI_UVOFFSET) / (float)(divs2 + 0.0);
					float tmpvec[3];
					
					if(uf+vf > 1.0) 
					{
						// printf("bigger - divs1: %d, divs2: %d\n", divs1, divs2);
						continue;
					}

					VECCOPY(p1, mvert[ mface[i].v1 ].co);
					if(again == 1 && mface[i].v4)
					{
						VECCOPY(p2, mvert[ mface[i].v3 ].co);
						VECCOPY(p3, mvert[ mface[i].v4 ].co);
					}
					else
					{
						VECCOPY(p2, mvert[ mface[i].v2 ].co);
						VECCOPY(p3, mvert[ mface[i].v3 ].co);
					}

					VecMulf(p1, (1.0-uf-vf));
					VecMulf(p2, uf);
					VecMulf(p3, vf);
					
					VECADD(p, p1, p2);
					VECADD(p, p, p3);

					if(newdivs > divs)
						printf("mem problem\n");

					// mMovPoints.push_back(p + trinorm);
					VECCOPY(tmpvec, p);
					VECADD(tmpvec, tmpvec, trinorm);
					Mat4MulVecfl (ob->obmat, tmpvec);
					VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
					newdivs++;

					if(newdivs > divs)
						printf("mem problem\n");

					// mMovPoints.push_back(p - trinorm);
					VECCOPY(tmpvec, p);
					VECSUB(tmpvec, tmpvec, trinorm);
					Mat4MulVecfl (ob->obmat, tmpvec);
					VECCOPY(&scs->points[3 * (dm->getNumVerts(dm) + newdivs)], tmpvec);
					newdivs++;
				}
			}

			if(again == 0 && mface[i].v4)
				again++;
			else
				again = 0;

			facecounter++;

		} while(again!=0);
	}

	scs->numpoints = dm->getNumVerts(dm) + newdivs;

	MEM_freeN(tridivs);
}