Beispiel #1
0
/* draw a given stroke in 2d */
static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag, 
							short debug, int offsx, int offsy, int winx, int winy)
{
	/* otherwise thickness is twice that of the 3D view */
	float thickness= (float)thickness_s * 0.5f;

	/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
	 * 	- 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
	 */
	if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || 
		 ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) ) 
	{
		bGPDspoint *pt;
		int i;
		
		glBegin(GL_LINE_STRIP);
		for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
			if (sflag & GP_STROKE_2DSPACE) {
				glVertex2f(pt->x, pt->y);
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				const float x= (pt->x * winx) + offsx;
				const float y= (pt->y * winy) + offsy;
				
				glVertex2f(x, y);
			}
			else {
				const float x= (pt->x / 100 * winx) + offsx;
				const float y= (pt->y / 100 * winy) + offsy;
				
				glVertex2f(x, y);
			}
		}
		glEnd();
	}
	
	/* tesselation code - draw stroke as series of connected quads with connection
	 * edges rotated to minimise shrinking artifacts, and rounded endcaps
	 */
	else 
	{ 
		bGPDspoint *pt1, *pt2;
		float pm[2];
		int i;
		
		glShadeModel(GL_FLAT);
		glBegin(GL_QUADS);
		
		for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) {
			float s0[2], s1[2];		/* segment 'center' points */
			float t0[2], t1[2];		/* tesselated coordinates */
			float m1[2], m2[2];		/* gradient and normal */
			float mt[2], sc[2];		/* gradient for thickness, point for end-cap */
			float pthick;			/* thickness at segment point */
			
			/* get x and y coordinates from points */
			if (sflag & GP_STROKE_2DSPACE) {
				s0[0]= pt1->x; 		s0[1]= pt1->y;
				s1[0]= pt2->x;		s1[1]= pt2->y;
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				s0[0]= (pt1->x * winx) + offsx; 		
				s0[1]= (pt1->y * winy) + offsy;
				s1[0]= (pt2->x * winx) + offsx;		
				s1[1]= (pt2->y * winy) + offsy;
			}
			else {
				s0[0]= (pt1->x / 100 * winx) + offsx;
				s0[1]= (pt1->y / 100 * winy) + offsy;
				s1[0]= (pt2->x / 100 * winx) + offsx;
				s1[1]= (pt2->y / 100 * winy) + offsy;
			}		
			
			/* calculate gradient and normal - 'angle'=(ny/nx) */
			m1[1]= s1[1] - s0[1];		
			m1[0]= s1[0] - s0[0];
			normalize_v2(m1);
			m2[1]= -m1[0];
			m2[0]= m1[1];
			
			/* always use pressure from first point here */
			pthick= (pt1->pressure * thickness);
			
			/* if the first segment, start of segment is segment's normal */
			if (i == 0) {
				/* draw start cap first 
				 *	- make points slightly closer to center (about halfway across) 
				 */				
				mt[0]= m2[0] * pthick * 0.5f;
				mt[1]= m2[1] * pthick * 0.5f;
				sc[0]= s0[0] - (m1[0] * pthick * 0.75f);
				sc[1]= s0[1] - (m1[1] * pthick * 0.75f);
				
				t0[0]= sc[0] - mt[0];
				t0[1]= sc[1] - mt[1];
				t1[0]= sc[0] + mt[0];
				t1[1]= sc[1] + mt[1];
				
				glVertex2fv(t0);
				glVertex2fv(t1);
				
				/* calculate points for start of segment */
				mt[0]= m2[0] * pthick;
				mt[1]= m2[1] * pthick;
				
				t0[0]= s0[0] - mt[0];
				t0[1]= s0[1] - mt[1];
				t1[0]= s0[0] + mt[0];
				t1[1]= s0[1] + mt[1];
				
				/* draw this line twice (first to finish off start cap, then for stroke) */
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
			}
			/* if not the first segment, use bisector of angle between segments */
			else {
				float mb[2]; 		/* bisector normal */
				float athick, dfac;		/* actual thickness, difference between thicknesses */
				
				/* calculate gradient of bisector (as average of normals) */
				mb[0]= (pm[0] + m2[0]) / 2;
				mb[1]= (pm[1] + m2[1]) / 2;
				normalize_v2(mb);
				
				/* calculate gradient to apply 
				 * 	- as basis, use just pthick * bisector gradient
				 *	- if cross-section not as thick as it should be, add extra padding to fix it
				 */
				mt[0]= mb[0] * pthick;
				mt[1]= mb[1] * pthick;
				athick= len_v2(mt);
				dfac= pthick - (athick * 2);
				if ( ((athick * 2.0f) < pthick) && (IS_EQF(athick, pthick)==0) )
				{
					mt[0] += (mb[0] * dfac);
					mt[1] += (mb[1] * dfac);
				}	
				
				/* calculate points for start of segment */
				t0[0]= s0[0] - mt[0];
				t0[1]= s0[1] - mt[1];
				t1[0]= s0[0] + mt[0];
				t1[1]= s0[1] + mt[1];
				
				/* draw this line twice (once for end of current segment, and once for start of next) */
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
			}
			
			/* if last segment, also draw end of segment (defined as segment's normal) */
			if (i == totpoints-2) {
				/* for once, we use second point's pressure (otherwise it won't be drawn) */
				pthick= (pt2->pressure * thickness);
				
				/* calculate points for end of segment */
				mt[0]= m2[0] * pthick;
				mt[1]= m2[1] * pthick;
				
				t0[0]= s1[0] - mt[0];
				t0[1]= s1[1] - mt[1];
				t1[0]= s1[0] + mt[0];
				t1[1]= s1[1] + mt[1];
				
				/* draw this line twice (once for end of stroke, and once for endcap)*/
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
				
				
				/* draw end cap as last step 
				 *	- make points slightly closer to center (about halfway across) 
				 */				
				mt[0]= m2[0] * pthick * 0.5f;
				mt[1]= m2[1] * pthick * 0.5f;
				sc[0]= s1[0] + (m1[0] * pthick * 0.75f);
				sc[1]= s1[1] + (m1[1] * pthick * 0.75f);
				
				t0[0]= sc[0] - mt[0];
				t0[1]= sc[1] - mt[1];
				t1[0]= sc[0] + mt[0];
				t1[1]= sc[1] + mt[1];
				
				glVertex2fv(t1);
				glVertex2fv(t0);
			}
			
			/* store stroke's 'natural' normal for next stroke to use */
			copy_v2_v2(pm, m2);
		}
		
		glEnd();
	}
	
	/* draw debug points of curve on top? (original stroke points) */
	if (debug) {
		bGPDspoint *pt;
		int i;
		
		glBegin(GL_POINTS);
		for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
			if (sflag & GP_STROKE_2DSPACE) {
				glVertex2fv(&pt->x);
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				const float x= (float)((pt->x * winx) + offsx);
				const float y= (float)((pt->y * winy) + offsy);
				
				glVertex2f(x, y);
			}
			else {
				const float x= (float)(pt->x / 100 * winx) + offsx;
				const float y= (float)(pt->y / 100 * winy) + offsy;
				
				glVertex2f(x, y);
			}
		}
		glEnd();
	}
}
Beispiel #2
0
static void setup_vertex_point(Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
                               const float point_co[2], const float tangent[2], const float u,
                               MaskSplinePoint *reference_point, const short reference_adjacent,
                               const float view_zoom)
{
	MaskSplinePoint *prev_point = NULL;
	MaskSplinePoint *next_point = NULL;
	BezTriple *bezt;
	float co[3];
	const float len = 10.0; /* default length of handle in pixel space */

	copy_v2_v2(co, point_co);
	co[2] = 0.0f;

	/* point coordinate */
	bezt = &new_point->bezt;

	bezt->h1 = bezt->h2 = HD_ALIGN;

	if (reference_point) {
		bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
	}
	else if (reference_adjacent) {
		if (spline->tot_point != 1) {
			int index = (int)(new_point - spline->points);
			prev_point = &spline->points[(index - 1) % spline->tot_point];
			next_point = &spline->points[(index + 1) % spline->tot_point];

			bezt->h1 = bezt->h2 = MAX2(prev_point->bezt.h2, next_point->bezt.h1);

			/* note, we may want to copy other attributes later, radius? pressure? color? */
		}
	}

	copy_v3_v3(bezt->vec[0], co);
	copy_v3_v3(bezt->vec[1], co);
	copy_v3_v3(bezt->vec[2], co);

	/* initial offset for handles */
	if (spline->tot_point == 1) {
		/* first point of splien is aligned horizontally */
		bezt->vec[0][0] -= len * view_zoom;
		bezt->vec[2][0] += len * view_zoom;
	}
	else if (tangent) {
		float vec[2];

		copy_v2_v2(vec, tangent);

		mul_v2_fl(vec, len);

		sub_v2_v2(bezt->vec[0], vec);
		add_v2_v2(bezt->vec[2], vec);

		if (reference_adjacent) {
			BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
		}
	}
	else {

		/* calculating auto handles works much nicer */
#if 0
		/* next points are aligning in the direction of previous/next point */
		MaskSplinePoint *point;
		float v1[2], v2[2], vec[2];
		float dir = 1.0f;

		if (new_point == spline->points) {
			point = new_point + 1;
			dir = -1.0f;
		}
		else
			point = new_point - 1;

		if (spline->tot_point < 3) {
			v1[0] = point->bezt.vec[1][0] * width;
			v1[1] = point->bezt.vec[1][1] * height;

			v2[0] = new_point->bezt.vec[1][0] * width;
			v2[1] = new_point->bezt.vec[1][1] * height;
		}
		else {
			if (new_point == spline->points) {
				v1[0] = spline->points[1].bezt.vec[1][0] * width;
				v1[1] = spline->points[1].bezt.vec[1][1] * height;

				v2[0] = spline->points[spline->tot_point - 1].bezt.vec[1][0] * width;
				v2[1] = spline->points[spline->tot_point - 1].bezt.vec[1][1] * height;
			}
			else {
				v1[0] = spline->points[0].bezt.vec[1][0] * width;
				v1[1] = spline->points[0].bezt.vec[1][1] * height;

				v2[0] = spline->points[spline->tot_point - 2].bezt.vec[1][0] * width;
				v2[1] = spline->points[spline->tot_point - 2].bezt.vec[1][1] * height;
			}
		}

		sub_v2_v2v2(vec, v1, v2);
		mul_v2_fl(vec, len * dir / len_v2(vec));

		vec[0] /= width;
		vec[1] /= height;

		add_v2_v2(bezt->vec[0], vec);
		sub_v2_v2(bezt->vec[2], vec);
#else
		BKE_mask_calc_handle_point_auto(spline, new_point, TRUE);
		BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);

#endif
	}

	BKE_mask_parent_init(&new_point->parent);

	/* select new point */
	MASKPOINT_SEL_ALL(new_point);
	ED_mask_select_flush_all(mask);
}
Beispiel #3
0
/* tries to realize the wanted velocity taking all constraints into account */
void boid_body(BoidBrainData *bbd, ParticleData *pa)
{
	BoidSettings *boids = bbd->part->boids;
	BoidParticle *bpa = pa->boid;
	BoidValues val;
	EffectedPoint epoint;
	float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
	float dvec[3], bvec[3];
	float new_dir[3], new_speed;
	float old_dir[3], old_speed;
	float wanted_dir[3];
	float q[4], mat[3][3]; /* rotation */
	float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f};
	float force[3] = {0.0f, 0.0f, 0.0f};
	float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep;

	set_boid_values(&val, boids, pa);

	/* make sure there's something in new velocity, location & rotation */
	copy_particle_key(&pa->state,&pa->prev_state,0);

	if(bbd->part->flag & PART_SIZEMASS)
		pa_mass*=pa->size;

	/* if boids can't fly they fall to the ground */
	if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && psys_uses_gravity(bbd->sim))
		bpa->data.mode = eBoidMode_Falling;

	if(bpa->data.mode == eBoidMode_Falling) {
		/* Falling boids are only effected by gravity. */
		acc[2] = bbd->sim->scene->physics_settings.gravity[2];
	}
	else {
		/* figure out acceleration */
		float landing_level = 2.0f;
		float level = landing_level + 1.0f;
		float new_vel[3];

		if(bpa->data.mode == eBoidMode_Liftoff) {
			bpa->data.mode = eBoidMode_InAir;
			bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
		}
		else if(bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
			/* auto-leveling & landing if close to ground */

			bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
			
			/* level = how many particle sizes above ground */
			level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5f;

			landing_level = - boids->landing_smoothness * pa->prev_state.vel[2] * pa_mass;

			if(pa->prev_state.vel[2] < 0.0f) {
				if(level < 1.0f) {
					bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
					bbd->wanted_speed = 0.0f;
					bpa->data.mode = eBoidMode_Falling;
				}
				else if(level < landing_level) {
					bbd->wanted_speed *= (level - 1.0f)/landing_level;
					bbd->wanted_co[2] *= (level - 1.0f)/landing_level;
				}
			}
		}

		copy_v3_v3(old_dir, pa->prev_state.ave);
		new_speed = normalize_v3_v3(wanted_dir, bbd->wanted_co);

		/* first check if we have valid direction we want to go towards */
		if(new_speed == 0.0f) {
			copy_v3_v3(new_dir, old_dir);
		}
		else {
			float old_dir2[2], wanted_dir2[2], nor[3], angle;
			copy_v2_v2(old_dir2, old_dir);
			normalize_v2(old_dir2);
			copy_v2_v2(wanted_dir2, wanted_dir);
			normalize_v2(wanted_dir2);

			/* choose random direction to turn if wanted velocity */
			/* is directly behind regardless of z-coordinate */
			if(dot_v2v2(old_dir2, wanted_dir2) < -0.99f) {
				wanted_dir[0] = 2.0f*(0.5f - BLI_frand());
				wanted_dir[1] = 2.0f*(0.5f - BLI_frand());
				wanted_dir[2] = 2.0f*(0.5f - BLI_frand());
				normalize_v3(wanted_dir);
			}

			/* constrain direction with maximum angular velocity */
			angle = saacos(dot_v3v3(old_dir, wanted_dir));
			angle = MIN2(angle, val.max_ave);

			cross_v3_v3v3(nor, old_dir, wanted_dir);
			axis_angle_to_quat( q,nor, angle);
			copy_v3_v3(new_dir, old_dir);
			mul_qt_v3(q, new_dir);
			normalize_v3(new_dir);

			/* save direction in case resulting velocity too small */
			axis_angle_to_quat( q,nor, angle*dtime);
			copy_v3_v3(pa->state.ave, old_dir);
			mul_qt_v3(q, pa->state.ave);
			normalize_v3(pa->state.ave);
		}

		/* constrain speed with maximum acceleration */
		old_speed = len_v3(pa->prev_state.vel);
		
		if(bbd->wanted_speed < old_speed)
			new_speed = MAX2(bbd->wanted_speed, old_speed - val.max_acc);
		else
			new_speed = MIN2(bbd->wanted_speed, old_speed + val.max_acc);

		/* combine direction and speed */
		copy_v3_v3(new_vel, new_dir);
		mul_v3_fl(new_vel, new_speed);

		/* maintain minimum flying velocity if not landing */
		if(level >= landing_level) {
			float len2 = dot_v2v2(new_vel,new_vel);
			float root;

			len2 = MAX2(len2, val.min_speed*val.min_speed);
			root = sasqrt(new_speed*new_speed - len2);

			new_vel[2] = new_vel[2] < 0.0f ? -root : root;

			normalize_v2(new_vel);
			mul_v2_fl(new_vel, sasqrt(len2));
		}

		/* finally constrain speed to max speed */
		new_speed = normalize_v3(new_vel);
		mul_v3_fl(new_vel, MIN2(new_speed, val.max_speed));

		/* get acceleration from difference of velocities */
		sub_v3_v3v3(acc, new_vel, pa->prev_state.vel);

		/* break acceleration to components */
		project_v3_v3v3(tan_acc, acc, pa->prev_state.ave);
		sub_v3_v3v3(nor_acc, acc, tan_acc);
	}

	/* account for effectors */
	pd_point_from_particle(bbd->sim, pa, &pa->state, &epoint);
	pdDoEffectors(bbd->sim->psys->effectors, bbd->sim->colliders, bbd->part->effector_weights, &epoint, force, NULL);

	if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
		float length = normalize_v3(force);

		length = MAX2(0.0f, length - boids->land_stick_force);

		mul_v3_fl(force, length);
	}
	
	add_v3_v3(acc, force);

	/* store smoothed acceleration for nice banking etc. */
	madd_v3_v3fl(bpa->data.acc, acc, dtime);
	mul_v3_fl(bpa->data.acc, 1.0f / (1.0f + dtime));

	/* integrate new location & velocity */

	/* by regarding the acceleration as a force at this stage we*/
	/* can get better control allthough it's a bit unphysical	*/
	mul_v3_fl(acc, 1.0f/pa_mass);

	copy_v3_v3(dvec, acc);
	mul_v3_fl(dvec, dtime*dtime*0.5f);
	
	copy_v3_v3(bvec, pa->prev_state.vel);
	mul_v3_fl(bvec, dtime);
	add_v3_v3(dvec, bvec);
	add_v3_v3(pa->state.co, dvec);

	madd_v3_v3fl(pa->state.vel, acc, dtime);

	//if(bpa->data.mode != eBoidMode_InAir)
	bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);

	/* change modes, constrain movement & keep track of down vector */
	switch(bpa->data.mode) {
		case eBoidMode_InAir:
		{
			float grav[3];

			grav[0]= 0.0f;
			grav[1]= 0.0f;
			grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;

			/* don't take forward acceleration into account (better banking) */
			if(dot_v3v3(bpa->data.acc, pa->state.vel) > 0.0f) {
				project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
				sub_v3_v3v3(dvec, bpa->data.acc, dvec);
			}
			else {
				copy_v3_v3(dvec, bpa->data.acc);
			}

			/* gather apparent gravity */
			madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
			normalize_v3(bpa->gravity);

			/* stick boid on goal when close enough */
			if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
				bpa->data.mode = eBoidMode_Climbing;
				bpa->ground = bbd->goal_ob;
				boid_find_ground(bbd, pa, ground_co, ground_nor);
				boid_climb(boids, pa, ground_co, ground_nor);
			}
			else if(pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
				/* land boid when below ground */
				if(boids->options & BOID_ALLOW_LAND) {
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
					bpa->data.mode = eBoidMode_OnLand;
				}
				/* fly above ground */
				else if(bpa->ground) {
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
				}
			}
			break;
		}
		case eBoidMode_Falling:
		{
			float grav[3];

			grav[0]= 0.0f;
			grav[1]= 0.0f;
			grav[2]= bbd->sim->scene->physics_settings.gravity[2] < 0.0f ? -1.0f : 0.0f;


			/* gather apparent gravity */
			madd_v3_v3fl(bpa->gravity, grav, dtime);
			normalize_v3(bpa->gravity);

			if(boids->options & BOID_ALLOW_LAND) {
				/* stick boid on goal when close enough */
				if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
					bpa->data.mode = eBoidMode_Climbing;
					bpa->ground = bbd->goal_ob;
					boid_find_ground(bbd, pa, ground_co, ground_nor);
					boid_climb(boids, pa, ground_co, ground_nor);
				}
				/* land boid when really near ground */
				else if(pa->state.co[2] <= ground_co[2] + 1.01f * pa->size * boids->height){
					pa->state.co[2] = ground_co[2] + pa->size * boids->height;
					pa->state.vel[2] = 0.0f;
					bpa->data.mode = eBoidMode_OnLand;
				}
				/* if we're falling, can fly and want to go upwards lets fly */
				else if(boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
					bpa->data.mode = eBoidMode_InAir;
			}
			else
				bpa->data.mode = eBoidMode_InAir;
			break;
		}
		case eBoidMode_Climbing:
		{
			boid_climb(boids, pa, ground_co, ground_nor);
			//float nor[3];
			//copy_v3_v3(nor, ground_nor);

			///* gather apparent gravity to r_ve */
			//madd_v3_v3fl(pa->r_ve, ground_nor, -1.0);
			//normalize_v3(pa->r_ve);

			///* raise boid it's size from surface */
			//mul_v3_fl(nor, pa->size * boids->height);
			//add_v3_v3v3(pa->state.co, ground_co, nor);

			///* remove normal component from velocity */
			//project_v3_v3v3(v, pa->state.vel, ground_nor);
			//sub_v3_v3v3(pa->state.vel, pa->state.vel, v);
			break;
		}
		case eBoidMode_OnLand:
		{
			/* stick boid on goal when close enough */
			if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
				bpa->data.mode = eBoidMode_Climbing;
				bpa->ground = bbd->goal_ob;
				boid_find_ground(bbd, pa, ground_co, ground_nor);
				boid_climb(boids, pa, ground_co, ground_nor);
			}
			/* ground is too far away so boid falls */
			else if(pa->state.co[2]-ground_co[2] > 1.1f * pa->size * boids->height)
				bpa->data.mode = eBoidMode_Falling;
			else {
				/* constrain to surface */
				pa->state.co[2] = ground_co[2] + pa->size * boids->height;
				pa->state.vel[2] = 0.0f;
			}

			if(boids->banking > 0.0f) {
				float grav[3];
				/* Don't take gravity's strength in to account, */
				/* otherwise amount of banking is hard to control. */
				negate_v3_v3(grav, ground_nor);

				project_v3_v3v3(dvec, bpa->data.acc, pa->state.vel);
				sub_v3_v3v3(dvec, bpa->data.acc, dvec);

				/* gather apparent gravity */
				madd_v3_v3v3fl(bpa->gravity, grav, dvec, -boids->banking);
				normalize_v3(bpa->gravity);
			}
			else {
				/* gather negative surface normal */
				madd_v3_v3fl(bpa->gravity, ground_nor, -1.0f);
				normalize_v3(bpa->gravity);
			}
			break;
		}
	}

	/* save direction to state.ave unless the boid is falling */
	/* (boids can't effect their direction when falling) */
	if(bpa->data.mode!=eBoidMode_Falling && len_v3(pa->state.vel) > 0.1f*pa->size) {
		copy_v3_v3(pa->state.ave, pa->state.vel);
		pa->state.ave[2] *= bbd->part->boids->pitch;
		normalize_v3(pa->state.ave);
	}

	/* apply damping */
	if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
		mul_v3_fl(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);

	/* calculate rotation matrix based on forward & down vectors */
	if(bpa->data.mode == eBoidMode_InAir) {
		copy_v3_v3(mat[0], pa->state.ave);

		project_v3_v3v3(dvec, bpa->gravity, pa->state.ave);
		sub_v3_v3v3(mat[2], bpa->gravity, dvec);
		normalize_v3(mat[2]);
	}
	else {
		project_v3_v3v3(dvec, pa->state.ave, bpa->gravity);
		sub_v3_v3v3(mat[0], pa->state.ave, dvec);
		normalize_v3(mat[0]);

		copy_v3_v3(mat[2], bpa->gravity);
	}
	negate_v3(mat[2]);
	cross_v3_v3v3(mat[1], mat[2], mat[0]);
	
	/* apply rotation */
	mat3_to_quat_is_ok( q,mat);
	copy_qt_qt(pa->state.rot, q);
}
UvVertMap *BKE_mesh_uv_vert_map_create(
        struct MPoly *mpoly, struct MLoop *mloop, struct MLoopUV *mloopuv,
        unsigned int totpoly, unsigned int totvert,
        const float limit[2], const bool selected, const bool use_winding)
{
	UvVertMap *vmap;
	UvMapVert *buf;
	MPoly *mp;
	unsigned int a;
	int i, totuv, nverts;

	bool *winding;
	BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, 32);

	totuv = 0;

	/* generate UvMapVert array */
	mp = mpoly;
	for (a = 0; a < totpoly; a++, mp++)
		if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL)))
			totuv += mp->totloop;

	if (totuv == 0)
		return NULL;

	vmap = (UvVertMap *)MEM_callocN(sizeof(*vmap), "UvVertMap");
	buf = vmap->buf = (UvMapVert *)MEM_callocN(sizeof(*vmap->buf) * (size_t)totuv, "UvMapVert");
	vmap->vert = (UvMapVert **)MEM_callocN(sizeof(*vmap->vert) * totvert, "UvMapVert*");
	if (use_winding) {
		winding = MEM_callocN(sizeof(*winding) * totpoly, "winding");
	}

	if (!vmap->vert || !vmap->buf) {
		BKE_mesh_uv_vert_map_free(vmap);
		return NULL;
	}

	mp = mpoly;
	for (a = 0; a < totpoly; a++, mp++) {
		if (!selected || (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))) {
			float (*tf_uv)[2];

			if (use_winding) {
				tf_uv = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, mp->totloop);
			}

			nverts = mp->totloop;

			for (i = 0; i < nverts; i++) {
				buf->tfindex = (unsigned char)i;
				buf->f = a;
				buf->separate = 0;
				buf->next = vmap->vert[mloop[mp->loopstart + i].v];
				vmap->vert[mloop[mp->loopstart + i].v] = buf;

				if (use_winding) {
					copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv);
				}

				buf++;
			}

			if (use_winding) {
				winding[a] = cross_poly_v2((const float (*)[2])tf_uv, (unsigned int)nverts) > 0;
			}
		}
	}

	/* sort individual uvs for each vert */
	for (a = 0; a < totvert; a++) {
		UvMapVert *newvlist = NULL, *vlist = vmap->vert[a];
		UvMapVert *iterv, *v, *lastv, *next;
		float *uv, *uv2, uvdiff[2];

		while (vlist) {
			v = vlist;
			vlist = vlist->next;
			v->next = newvlist;
			newvlist = v;

			uv = mloopuv[mpoly[v->f].loopstart + v->tfindex].uv;
			lastv = NULL;
			iterv = vlist;

			while (iterv) {
				next = iterv->next;

				uv2 = mloopuv[mpoly[iterv->f].loopstart + iterv->tfindex].uv;
				sub_v2_v2v2(uvdiff, uv2, uv);


				if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
				    (!use_winding || winding[iterv->f] == winding[v->f]))
				{
					if (lastv) lastv->next = next;
					else vlist = next;
					iterv->next = newvlist;
					newvlist = iterv;
				}
				else
					lastv = iterv;

				iterv = next;
			}

			newvlist->separate = 1;
		}

		vmap->vert[a] = newvlist;
	}

	if (use_winding)  {
		MEM_freeN(winding);
	}

	BLI_buffer_free(&tf_uv_buf);

	return vmap;
}
static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
{
	Mesh *me = ob->data;
	DerivedMesh *ddm;
	MPoly *mp, *mface  = me->mpoly;
	MTexPoly *mtpoly   = me->mtpoly;
	MLoopUV *mloopuv   = me->mloopuv;
	MLoopUV *luv;
	MLoopCol *mloopcol = me->mloopcol;  /* why does mcol exist? */
	MLoopCol *lcol;

	bProperty *prop = BKE_bproperty_object_get(ob, "Text");
	GPUVertexAttribs gattribs;
	int a, totpoly = me->totpoly;

	/* fake values to pass to GPU_render_text() */
	MCol  tmp_mcol[4]  = {{0}};
	MCol *tmp_mcol_pt  = mloopcol ? tmp_mcol : NULL;
	MTFace tmp_tf      = {{{0}}};

	/* don't draw without tfaces */
	if (!mtpoly || !mloopuv)
		return;

	/* don't draw when editing */
	if (ob->mode & OB_MODE_EDIT)
		return;
	else if (ob == OBACT)
		if (paint_facesel_test(ob) || paint_vertsel_test(ob))
			return;

	ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);

	for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
		short matnr = mp->mat_nr;
		int mf_smooth = mp->flag & ME_SMOOTH;
		Material *mat = (me->mat) ? me->mat[matnr] : NULL;
		int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;


		if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) {
			/* get the polygon as a tri/quad */
			int mp_vi[4];
			float v1[3], v2[3], v3[3], v4[3];
			char string[MAX_PROPSTRING];
			int characters, i, glattrib = -1, badtex = 0;


			/* TEXFACE */
			ME_MTEXFACE_CPY(&tmp_tf, mtpoly);

			if (glsl) {
				GPU_enable_material(matnr + 1, &gattribs);

				for (i = 0; i < gattribs.totlayer; i++) {
					if (gattribs.layer[i].type == CD_MTFACE) {
						glattrib = gattribs.layer[i].glindex;
						break;
					}
				}
			}
			else {
				badtex = set_draw_settings_cached(0, &tmp_tf, mat, Gtexdraw);
				if (badtex) {
					continue;
				}
			}

			mp_vi[0] = me->mloop[mp->loopstart + 0].v;
			mp_vi[1] = me->mloop[mp->loopstart + 1].v;
			mp_vi[2] = me->mloop[mp->loopstart + 2].v;
			mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0;

			/* UV */
			luv = &mloopuv[mp->loopstart];
			copy_v2_v2(tmp_tf.uv[0], luv->uv); luv++;
			copy_v2_v2(tmp_tf.uv[1], luv->uv); luv++;
			copy_v2_v2(tmp_tf.uv[2], luv->uv); luv++;
			if (mp->totloop >= 4) {
				copy_v2_v2(tmp_tf.uv[3], luv->uv);
			}

			/* COLOR */
			if (mloopcol) {
				unsigned int totloop_clamp = min_ii(4, mp->totloop);
				unsigned int j;
				lcol = &mloopcol[mp->loopstart];

				for (j = 0; j < totloop_clamp; j++, lcol++) {
					MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
				}
			}

			/* LOCATION */
			ddm->getVertCo(ddm, mp_vi[0], v1);
			ddm->getVertCo(ddm, mp_vi[1], v2);
			ddm->getVertCo(ddm, mp_vi[2], v3);
			if (mp->totloop >= 4) {
				ddm->getVertCo(ddm, mp_vi[3], v4);
			}



			/* The BM_FONT handling is in the gpu module, shared with the
			 * game engine, was duplicated previously */

			BKE_bproperty_set_valstr(prop, string);
			characters = strlen(string);
			
			if (!BKE_image_has_ibuf(mtpoly->tpage, NULL))
				characters = 0;

			if (!mf_smooth) {
				float nor[3];

				normal_tri_v3(nor, v1, v2, v3);

				glNormal3fv(nor);
			}

			GPU_render_text(&tmp_tf, mode, string, characters,
			                (unsigned int *)tmp_mcol_pt, v1, v2, v3, (mp->totloop >= 4 ? v4 : NULL), glattrib);
		}
	}

	ddm->release(ddm);
}
Beispiel #6
0
/* Draw all kind of tracks. */
static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, MovieClip *clip,
                                 int width, int height, float zoomx, float zoomy)
{
	float x, y;
	MovieTracking *tracking = &clip->tracking;
	ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
	ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking);
	MovieTrackingTrack *track, *act_track;
	MovieTrackingPlaneTrack *plane_track, *active_plane_track;
	MovieTrackingMarker *marker;
	int framenr = ED_space_clip_get_clip_frame_number(sc);
	int undistort = sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
	float *marker_pos = NULL, *fp, *active_pos = NULL, cur_pos[2];

	/* ** find window pixel coordinates of origin ** */

	/* UI_view2d_view_to_region_no_clip return integer values, this could
	 * lead to 1px flickering when view is locked to selection during playback.
	 * to avoid this flickering, calculate base point in the same way as it happens
	 * in UI_view2d_view_to_region_no_clip, but do it in floats here */

	UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);

	glPushMatrix();
	glTranslatef(x, y, 0);

	glPushMatrix();
	glScalef(zoomx, zoomy, 0);
	glMultMatrixf(sc->stabmat);
	glScalef(width, height, 0);

	act_track = BKE_tracking_track_get_active(tracking);

	/* Draw plane tracks */
	active_plane_track = BKE_tracking_plane_track_get_active(tracking);
	for (plane_track = plane_tracks_base->first;
	     plane_track;
	     plane_track = plane_track->next)
	{
		if ((plane_track->flag & PLANE_TRACK_HIDDEN) == 0) {
			draw_plane_track(sc, scene, plane_track, framenr, plane_track == active_plane_track, width, height);
		}
	}

	if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) {
		int count = 0;

		/* count */
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker))
					count++;
			}

			track = track->next;
		}

		/* undistort */
		if (count) {
			marker_pos = MEM_callocN(2 * sizeof(float) * count, "draw_tracking_tracks marker_pos");

			track = tracksbase->first;
			fp = marker_pos;
			while (track) {
				if ((track->flag & TRACK_HIDDEN) == 0) {
					marker = BKE_tracking_marker_get(track, framenr);

					if (MARKER_VISIBLE(sc, track, marker)) {
						ED_clip_point_undistorted_pos(sc, marker->pos, fp);

						if (track == act_track)
							active_pos = fp;

						fp += 2;
					}
				}

				track = track->next;
			}
		}
	}

	if (sc->flag & SC_SHOW_TRACK_PATH) {
		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0)
				draw_track_path(sc, clip, track);

			track = track->next;
		}
	}

	/* markers outline and non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				copy_v2_v2(cur_pos, fp ? fp : marker->pos);

				draw_marker_outline(sc, track, marker, cur_pos, width, height);
				draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
				draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* selected areas only, so selection wouldn't be overlapped by
	 * non-selected areas */
	track = tracksbase->first;
	fp = marker_pos;
	while (track) {
		if ((track->flag & TRACK_HIDDEN) == 0) {
			int act = track == act_track;
			marker = BKE_tracking_marker_get(track, framenr);

			if (MARKER_VISIBLE(sc, track, marker)) {
				if (!act) {
					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
					draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
				}

				if (fp)
					fp += 2;
			}
		}

		track = track->next;
	}

	/* active marker would be displayed on top of everything else */
	if (act_track) {
		if ((act_track->flag & TRACK_HIDDEN) == 0) {
			marker = BKE_tracking_marker_get(act_track, framenr);

			if (MARKER_VISIBLE(sc, act_track, marker)) {
				copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);

				draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
				draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
			}
		}
	}

	if (sc->flag & SC_SHOW_BUNDLES) {
		MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
		float pos[4], vec[4], mat[4][4], aspy;

		glEnable(GL_POINT_SMOOTH);
		glPointSize(3.0f);

		aspy = 1.0f / clip->tracking.camera.pixel_aspect;
		BKE_tracking_get_projection_matrix(tracking, object, framenr, width, height, mat);

		track = tracksbase->first;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0 && track->flag & TRACK_HAS_BUNDLE) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					float npos[2];
					copy_v3_v3(vec, track->bundle_pos);
					vec[3] = 1;

					mul_v4_m4v4(pos, mat, vec);

					pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width;
					pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy;

					BKE_tracking_distort_v2(tracking, pos, npos);

					if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) {
						vec[0] = (marker->pos[0] + track->offset[0]) * width;
						vec[1] = (marker->pos[1] + track->offset[1]) * height * aspy;

						sub_v2_v2(vec, npos);

						if (len_squared_v2(vec) < (3.0f * 3.0f))
							glColor3f(0.0f, 1.0f, 0.0f);
						else
							glColor3f(1.0f, 0.0f, 0.0f);

						glBegin(GL_POINTS);
						if (undistort)
							glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
						else
							glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
						glEnd();
					}
				}
			}

			track = track->next;
		}

		glDisable(GL_POINT_SMOOTH);
	}

	glPopMatrix();

	if (sc->flag & SC_SHOW_NAMES) {
		/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
		track = tracksbase->first;
		fp = marker_pos;
		while (track) {
			if ((track->flag & TRACK_HIDDEN) == 0) {
				marker = BKE_tracking_marker_get(track, framenr);

				if (MARKER_VISIBLE(sc, track, marker)) {
					int act = track == act_track;

					copy_v2_v2(cur_pos, fp ? fp : marker->pos);

					draw_marker_texts(sc, track, marker, cur_pos, act, width, height, zoomx, zoomy);

					if (fp)
						fp += 2;
				}
			}

			track = track->next;
		}
	}

	glPopMatrix();

	if (marker_pos)
		MEM_freeN(marker_pos);
}
Beispiel #7
0
static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent *event)
{
	if (event->type == TIMER && event->customdata == walk->timer) {
		walk->redraw = true;
	}
	else if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) {

#ifdef USE_TABLET_SUPPORT
		if (walk->is_cursor_first) {
			/* wait until we get the 'warp' event */
			if ((walk->center_mval[0] == event->mval[0]) &&
			    (walk->center_mval[1] == event->mval[1]))
			{
				walk->is_cursor_first = false;
			}
			else {
				/* note, its possible the system isn't giving us the warp event
				 * ideally we shouldn't have to worry about this, see: T45361 */
				wmWindow *win = CTX_wm_window(C);
				WM_cursor_warp(win,
				               walk->ar->winrct.xmin + walk->center_mval[0],
				               walk->ar->winrct.ymin + walk->center_mval[1]);
			}
			return;
		}

		if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) {
			walk->is_cursor_absolute = true;
			copy_v2_v2_int(walk->prev_mval, event->mval);
			copy_v2_v2_int(walk->center_mval, event->mval);
			/* without this we can't turn 180d */
			CLAMP_MIN(walk->mouse_speed, 4.0f);
		}
#endif  /* USE_TABLET_SUPPORT */


		walk->moffset[0] += event->mval[0] - walk->prev_mval[0];
		walk->moffset[1] += event->mval[1] - walk->prev_mval[1];

		copy_v2_v2_int(walk->prev_mval, event->mval);

		if ((walk->center_mval[0] != event->mval[0]) ||
		    (walk->center_mval[1] != event->mval[1]))
		{
			walk->redraw = true;

#ifdef USE_TABLET_SUPPORT
			if (walk->is_cursor_absolute) {
				/* pass */
			}
			else
#endif
			if (wm_event_is_last_mousemove(event)) {
				wmWindow *win = CTX_wm_window(C);

#ifdef __APPLE__
				if ((abs(walk->prev_mval[0] - walk->center_mval[0]) > walk->center_mval[0] / 2) ||
				    (abs(walk->prev_mval[1] - walk->center_mval[1]) > walk->center_mval[1] / 2))
#endif
				{
					WM_cursor_warp(win,
					               walk->ar->winrct.xmin + walk->center_mval[0],
					               walk->ar->winrct.ymin + walk->center_mval[1]);
					copy_v2_v2_int(walk->prev_mval, walk->center_mval);
				}
			}
		}
	}
	else if (event->type == NDOF_MOTION) {
		/* do these automagically get delivered? yes. */
		// puts("ndof motion detected in walk mode!");
		// static const char *tag_name = "3D mouse position";

		const wmNDOFMotionData *incoming_ndof = event->customdata;
		switch (incoming_ndof->progress) {
			case P_STARTING:
				/* start keeping track of 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				puts("start keeping track of 3D mouse position");
#endif
				/* fall-through */
			case P_IN_PROGRESS:
				/* update 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				putchar('.'); fflush(stdout);
#endif
				if (walk->ndof == NULL) {
					// walk->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name);
					walk->ndof = MEM_dupallocN(incoming_ndof);
					// walk->ndof = malloc(sizeof(wmNDOFMotionData));
				}
				else {
					memcpy(walk->ndof, incoming_ndof, sizeof(wmNDOFMotionData));
				}
				break;
			case P_FINISHING:
				/* stop keeping track of 3D mouse position */
#ifdef NDOF_WALK_DEBUG
				puts("stop keeping track of 3D mouse position");
#endif
				if (walk->ndof) {
					MEM_freeN(walk->ndof);
					// free(walk->ndof);
					walk->ndof = NULL;
				}

				/* update the time else the view will jump when 2D mouse/timer resume */
				walk->time_lastdraw = PIL_check_seconds_timer();

				break;
			default:
				break; /* should always be one of the above 3 */
		}
	}
	/* handle modal keymap first */
	else if (event->type == EVT_MODAL_MAP) {
		switch (event->val) {
			case WALK_MODAL_CANCEL:
				walk->state = WALK_CANCEL;
				break;
			case WALK_MODAL_CONFIRM:
				walk->state = WALK_CONFIRM;
				break;

			case WALK_MODAL_ACCELERATE:
				base_speed *= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
				break;
			case WALK_MODAL_DECELERATE:
				base_speed /= 1.0f + (walk->is_slow ? 0.01f : 0.1f);
				break;

			/* implement WASD keys */
			case WALK_MODAL_DIR_FORWARD:
				walk->active_directions |= WALK_BIT_FORWARD;
				break;
			case WALK_MODAL_DIR_BACKWARD:
				walk->active_directions |= WALK_BIT_BACKWARD;
				break;
			case WALK_MODAL_DIR_LEFT:
				walk->active_directions |= WALK_BIT_LEFT;
				break;
			case WALK_MODAL_DIR_RIGHT:
				walk->active_directions |= WALK_BIT_RIGHT;
				break;
			case WALK_MODAL_DIR_UP:
				walk->active_directions |= WALK_BIT_UP;
				break;
			case WALK_MODAL_DIR_DOWN:
				walk->active_directions |= WALK_BIT_DOWN;
				break;

			case WALK_MODAL_DIR_FORWARD_STOP:
				walk->active_directions &= ~WALK_BIT_FORWARD;
				break;
			case WALK_MODAL_DIR_BACKWARD_STOP:
				walk->active_directions &= ~WALK_BIT_BACKWARD;
				break;
			case WALK_MODAL_DIR_LEFT_STOP:
				walk->active_directions &= ~WALK_BIT_LEFT;
				break;
			case WALK_MODAL_DIR_RIGHT_STOP:
				walk->active_directions &= ~WALK_BIT_RIGHT;
				break;
			case WALK_MODAL_DIR_UP_STOP:
				walk->active_directions &= ~WALK_BIT_UP;
				break;
			case WALK_MODAL_DIR_DOWN_STOP:
				walk->active_directions &= ~WALK_BIT_DOWN;
				break;

			case WALK_MODAL_FAST_ENABLE:
				walk->is_fast = true;
				break;
			case WALK_MODAL_FAST_DISABLE:
				walk->is_fast = false;
				break;
			case WALK_MODAL_SLOW_ENABLE:
				walk->is_slow = true;
				break;
			case WALK_MODAL_SLOW_DISABLE:
				walk->is_slow = false;
				break;

#define JUMP_SPEED_MIN 1.0f
#define JUMP_TIME_MAX 0.2f /* s */
#define JUMP_SPEED_MAX sqrtf(2.0f * walk->gravity * walk->jump_height)

			case WALK_MODAL_JUMP_STOP:
				if (walk->gravity_state == WALK_GRAVITY_STATE_JUMP) {
					float t;

					/* delta time */
					t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);

					/* reduce the veolocity, if JUMP wasn't hold for long enough */
					t = min_ff(t, JUMP_TIME_MAX);
					walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX;

					/* when jumping, duration is how long it takes before we start going down */
					walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);

					/* no more increase of jump speed */
					walk->gravity_state = WALK_GRAVITY_STATE_ON;
				}
				break;
			case WALK_MODAL_JUMP:
				if ((walk->navigation_mode == WALK_MODE_GRAVITY) &&
				    (walk->gravity_state == WALK_GRAVITY_STATE_OFF) &&
				    (walk->teleport.state == WALK_TELEPORT_STATE_OFF))
				{
					/* no need to check for ground,
					 * walk->gravity wouldn't be off
					 * if we were over a hole */
					walk->gravity_state = WALK_GRAVITY_STATE_JUMP;
					walk->speed_jump = JUMP_SPEED_MAX;

					walk->teleport.initial_time = PIL_check_seconds_timer();
					copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);

					/* using previous vec because WASD keys are not called when SPACE is */
					copy_v2_v2(walk->teleport.direction, walk->dvec_prev);

					/* when jumping, duration is how long it takes before we start going down */
					walk->teleport.duration = getVelocityZeroTime(walk->gravity, walk->speed_jump);
				}

				break;

			case WALK_MODAL_TELEPORT:
			{
				float loc[3], nor[3];
				float distance;
				bool ret = walk_ray_cast(walk->rv3d, walk, loc, nor, &distance);

				/* in case we are teleporting middle way from a jump */
				walk->speed_jump = 0.0f;

				if (ret) {
					WalkTeleport *teleport = &walk->teleport;
					teleport->state = WALK_TELEPORT_STATE_ON;
					teleport->initial_time = PIL_check_seconds_timer();
					teleport->duration = U.walk_navigation.teleport_time;

					teleport->navigation_mode = walk->navigation_mode;
					walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);

					copy_v3_v3(teleport->origin, walk->rv3d->viewinv[3]);

					/* stop the camera from a distance (camera height) */
					normalize_v3(nor);
					mul_v3_fl(nor, walk->view_height);
					add_v3_v3(loc, nor);

					sub_v3_v3v3(teleport->direction, loc, teleport->origin);
				}
				else {
					walk->teleport.state = WALK_TELEPORT_STATE_OFF;
				}
				break;
			}

#undef JUMP_SPEED_MAX
#undef JUMP_TIME_MAX
#undef JUMP_SPEED_MIN

			case WALK_MODAL_TOGGLE:
				if (walk->navigation_mode == WALK_MODE_GRAVITY) {
					walk_navigation_mode_set(C, op, walk, WALK_MODE_FREE);
				}
				else { /* WALK_MODE_FREE */
					walk_navigation_mode_set(C, op, walk, WALK_MODE_GRAVITY);
				}
				break;
		}
	}
}
Beispiel #8
0
int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const float DXT[2], const float DYT[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
	TexResult texr;
	float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
	float maxd, pixsize, val1, val2, val3;
	int curmap, retval, imaprepeat, imapextend;

	/* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa() call,
	 * make a local copy here so that original vecs remain untouched */
	copy_v2_v2(dxt, DXT);
	copy_v2_v2(dyt, DYT);

	/* anisotropic filtering */
	if (tex->texfilter != TXF_BOX)
		return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);

	texres->tin= texres->ta= texres->tr= texres->tg= texres->tb= 0.0f;
	
	/* we need to set retval OK, otherwise texture code generates normals itself... */
	retval = texres->nor ? 3 : 1;
	
	/* quick tests */
	if (ibuf==NULL && ima==NULL)
		return retval;
	if (ima) {

		/* hack for icon render */
		if (skip_load_image && !BKE_image_has_loaded_ibuf(ima))
			return retval;
		
		ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);

		ima->flag|= IMA_USED_FOR_RENDER;
	}
	if (ibuf==NULL || (ibuf->rect==NULL && ibuf->rect_float==NULL)) {
		if (ima)
			BKE_image_pool_release_ibuf(ima, ibuf, pool);
		return retval;
	}
	
	/* mipmap test */
	image_mipmap_test(tex, ibuf);

	if (ima) {
		if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
			if ((tex->imaflag & TEX_CALCALPHA) == 0) {
				texres->talpha = true;
			}
		}
	}
	
	texr.talpha= texres->talpha;
	
	if (tex->imaflag & TEX_IMAROT) {
		fy= texvec[0];
		fx= texvec[1];
	}
	else {
		fx= texvec[0];
		fy= texvec[1];
	}
	
	if (ibuf->flags & IB_fields) {
		if (R.r.mode & R_FIELDS) {			/* field render */
			if (R.flag & R_SEC_FIELD) {		/* correction for 2nd field */
				/* fac1= 0.5/( (float)ibuf->y ); */
				/* fy-= fac1; */
			}
			else {				/* first field */
				fy+= 0.5f/( (float)ibuf->y );
			}
		}
	}
	
	/* pixel coordinates */

	minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
	maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
	miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
	maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);

	/* tex_sharper has been removed */
	minx= (maxx-minx)/2.0f;
	miny= (maxy-miny)/2.0f;
	
	if (tex->imaflag & TEX_FILTER_MIN) {
		/* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
		float addval= (0.5f * tex->filtersize) / (float) MIN2(ibuf->x, ibuf->y);

		if (addval > minx)
			minx= addval;
		if (addval > miny)
			miny= addval;
	}
	else if (tex->filtersize!=1.0f) {
		minx*= tex->filtersize;
		miny*= tex->filtersize;
		
		dxt[0]*= tex->filtersize;
		dxt[1]*= tex->filtersize;
		dyt[0]*= tex->filtersize;
		dyt[1]*= tex->filtersize;
	}

	if (tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny);
	
	if (minx>0.25f) minx= 0.25f;
	else if (minx<0.00001f) minx= 0.00001f;	/* side faces of unit-cube */
	if (miny>0.25f) miny= 0.25f;
	else if (miny<0.00001f) miny= 0.00001f;

	
	/* repeat and clip */
	imaprepeat= (tex->extend==TEX_REPEAT);
	imapextend= (tex->extend==TEX_EXTEND);

	if (tex->extend == TEX_REPEAT) {
		if (tex->flag & (TEX_REPEAT_XMIR|TEX_REPEAT_YMIR)) {
			imaprepeat= 0;
			imapextend= 1;
		}
	}

	if (tex->extend == TEX_CHECKER) {
		int xs, ys, xs1, ys1, xs2, ys2, boundary;
		
		xs= (int)floor(fx);
		ys= (int)floor(fy);
		
		/* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
		if ( (tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN) ) {
			fx-= xs;
			fy-= ys;
		}
		else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
		         (tex->flag & TEX_CHECKER_EVEN) == 0)
		{
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
		else {
			
			xs1= (int)floor(fx-minx);
			ys1= (int)floor(fy-miny);
			xs2= (int)floor(fx+minx);
			ys2= (int)floor(fy+miny);
			boundary= (xs1!=xs2) || (ys1!=ys2);

			if (boundary==0) {
				if ( (tex->flag & TEX_CHECKER_ODD)==0) {
					if ((xs + ys) & 1) {
						/* pass */
					}
					else {
						if (ima)
							BKE_image_pool_release_ibuf(ima, ibuf, pool);
						return retval;
					}
				}
				if ( (tex->flag & TEX_CHECKER_EVEN)==0) {
					if ((xs + ys) & 1) {
						if (ima)
							BKE_image_pool_release_ibuf(ima, ibuf, pool);
						return retval;
					}
				}
				fx-= xs;
				fy-= ys;
			}
			else {
				if (tex->flag & TEX_CHECKER_ODD) {
					if ((xs1+ys) & 1) fx-= xs2;
					else fx-= xs1;
					
					if ((ys1+xs) & 1) fy-= ys2;
					else fy-= ys1;
				}
				if (tex->flag & TEX_CHECKER_EVEN) {
					if ((xs1+ys) & 1) fx-= xs1;
					else fx-= xs2;
					
					if ((ys1+xs) & 1) fy-= ys1;
					else fy-= ys2;
				}
			}
		}

		/* scale around center, (0.5, 0.5) */
		if (tex->checkerdist<1.0f) {
			fx= (fx-0.5f)/(1.0f-tex->checkerdist) +0.5f;
			fy= (fy-0.5f)/(1.0f-tex->checkerdist) +0.5f;
			minx/= (1.0f-tex->checkerdist);
			miny/= (1.0f-tex->checkerdist);
		}
	}

	if (tex->extend == TEX_CLIPCUBE) {
		if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f || texvec[2]<-1.0f || texvec[2]>1.0f) {
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
	}
	else if (tex->extend==TEX_CLIP || tex->extend==TEX_CHECKER) {
		if (fx+minx<0.0f || fy+miny<0.0f || fx-minx>1.0f || fy-miny>1.0f) {
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
	}
	else {
		if (imapextend) {
			if (fx>1.0f) fx = 1.0f;
			else if (fx<0.0f) fx= 0.0f;
		}
		else {
			if (fx>1.0f) fx -= (int)(fx);
			else if (fx<0.0f) fx+= 1-(int)(fx);
		}
		
		if (imapextend) {
			if (fy>1.0f) fy = 1.0f;
			else if (fy<0.0f) fy= 0.0f;
		}
		else {
			if (fy>1.0f) fy -= (int)(fy);
			else if (fy<0.0f) fy+= 1-(int)(fy);
		}
	}

	/* warning no return! */
	if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
		ibuf->rect+= (ibuf->x*ibuf->y);
	}

	/* choice:  */
	if (tex->imaflag & TEX_MIPMAP) {
		ImBuf *previbuf, *curibuf;
		float bumpscale;
		
		dx = minx;
		dy = miny;
		maxd = max_ff(dx, dy);
		if (maxd > 0.5f) maxd = 0.5f;

		pixsize = 1.0f / (float) MIN2(ibuf->x, ibuf->y);
		
		bumpscale= pixsize/maxd;
		if (bumpscale>1.0f) bumpscale= 1.0f;
		else bumpscale*=bumpscale;
		
		curmap= 0;
		previbuf= curibuf= ibuf;
		while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
			if (maxd < pixsize) break;
			previbuf= curibuf;
			curibuf= ibuf->mipmap[curmap];
			pixsize= 1.0f / (float)MIN2(curibuf->x, curibuf->y);
			curmap++;
		}

		if (previbuf!=curibuf || (tex->imaflag & TEX_INTERPOL)) {
			/* sample at least 1 pixel */
			if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
			if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
		}
		
		if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
			/* a bit extra filter */
			//minx*= 1.35f;
			//miny*= 1.35f;
			
			boxsample(curibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
			val1= texres->tr+texres->tg+texres->tb;
			boxsample(curibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
			val2= texr.tr + texr.tg + texr.tb;
			boxsample(curibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
			val3= texr.tr + texr.tg + texr.tb;

			/* don't switch x or y! */
			texres->nor[0]= (val1-val2);
			texres->nor[1]= (val1-val3);
			
			if (previbuf!=curibuf) {  /* interpolate */
				
				boxsample(previbuf, fx-minx, fy-miny, fx+minx, fy+miny, &texr, imaprepeat, imapextend);
				
				/* calc rgb */
				dx= 2.0f*(pixsize-maxd)/pixsize;
				if (dx>=1.0f) {
					texres->ta= texr.ta; texres->tb= texr.tb;
					texres->tg= texr.tg; texres->tr= texr.tr;
				}
				else {
					dy= 1.0f-dx;
					texres->tb= dy*texres->tb+ dx*texr.tb;
					texres->tg= dy*texres->tg+ dx*texr.tg;
					texres->tr= dy*texres->tr+ dx*texr.tr;
					texres->ta= dy*texres->ta+ dx*texr.ta;
				}
				
				val1= dy*val1+ dx*(texr.tr + texr.tg + texr.tb);
				boxsample(previbuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
				val2= dy*val2+ dx*(texr.tr + texr.tg + texr.tb);
				boxsample(previbuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
				val3= dy*val3+ dx*(texr.tr + texr.tg + texr.tb);
				
				texres->nor[0]= (val1-val2);	/* vals have been interpolated above! */
				texres->nor[1]= (val1-val3);
				
				if (dx<1.0f) {
					dy= 1.0f-dx;
					texres->tb= dy*texres->tb+ dx*texr.tb;
					texres->tg= dy*texres->tg+ dx*texr.tg;
					texres->tr= dy*texres->tr+ dx*texr.tr;
					texres->ta= dy*texres->ta+ dx*texr.ta;
				}
			}
			texres->nor[0]*= bumpscale;
			texres->nor[1]*= bumpscale;
		}
		else {
			maxx= fx+minx;
			minx= fx-minx;
			maxy= fy+miny;
			miny= fy-miny;

			boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);

			if (previbuf!=curibuf) {  /* interpolate */
				boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
				
				fx= 2.0f*(pixsize-maxd)/pixsize;
				
				if (fx>=1.0f) {
					texres->ta= texr.ta; texres->tb= texr.tb;
					texres->tg= texr.tg; texres->tr= texr.tr;
				}
				else {
					fy= 1.0f-fx;
					texres->tb= fy*texres->tb+ fx*texr.tb;
					texres->tg= fy*texres->tg+ fx*texr.tg;
					texres->tr= fy*texres->tr+ fx*texr.tr;
					texres->ta= fy*texres->ta+ fx*texr.ta;
				}
			}
		}
	}
	else {
		const int intpol = tex->imaflag & TEX_INTERPOL;
		if (intpol) {
			/* sample 1 pixel minimum */
			if (minx < 0.5f / ibuf->x) minx = 0.5f / ibuf->x;
			if (miny < 0.5f / ibuf->y) miny = 0.5f / ibuf->y;
		}

		if (texres->nor && (tex->imaflag & TEX_NORMALMAP)==0) {
			boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
			val1= texres->tr+texres->tg+texres->tb;
			boxsample(ibuf, fx-minx+dxt[0], fy-miny+dxt[1], fx+minx+dxt[0], fy+miny+dxt[1], &texr, imaprepeat, imapextend);
			val2= texr.tr + texr.tg + texr.tb;
			boxsample(ibuf, fx-minx+dyt[0], fy-miny+dyt[1], fx+minx+dyt[0], fy+miny+dyt[1], &texr, imaprepeat, imapextend);
			val3= texr.tr + texr.tg + texr.tb;

			/* don't switch x or y! */
			texres->nor[0]= (val1-val2);
			texres->nor[1]= (val1-val3);
		}
		else
			boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, texres, imaprepeat, imapextend);
	}
	
	if (tex->imaflag & TEX_CALCALPHA) {
		texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
	}
	else {
		texres->tin = texres->ta;
	}

	if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta;
	
	if ( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) {
		ibuf->rect-= (ibuf->x*ibuf->y);
	}

	if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {
		/* qdn: normal from color
		 * The invert of the red channel is to make
		 * the normal map compliant with the outside world.
		 * It needs to be done because in Blender
		 * the normal used in the renderer points inward. It is generated
		 * this way in calc_vertexnormals(). Should this ever change
		 * this negate must be removed. */
		texres->nor[0] = -2.f*(texres->tr - 0.5f);
		texres->nor[1] = 2.f*(texres->tg - 0.5f);
		texres->nor[2] = 2.f*(texres->tb - 0.5f);
	}

	/* de-premul, this is being premulled in shade_input_do_shade() */
	/* do not de-premul for generated alpha, it is already in straight */
	if (texres->ta!=1.0f && texres->ta>1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
		mul_v3_fl(&texres->tr, 1.0f / texres->ta);
	}

	if (ima)
		BKE_image_pool_release_ibuf(ima, ibuf, pool);

	BRICONTRGB;
	
	return retval;
}
int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
  EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
  EEVEE_StorageList *stl = vedata->stl;
  EEVEE_FramebufferList *fbl = vedata->fbl;
  EEVEE_TextureList *txl = vedata->txl;
  EEVEE_EffectsInfo *effects = stl->effects;
  const float *viewport_size = DRW_viewport_size_get();

  const DRWContextState *draw_ctx = DRW_context_state_get();
  const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);

  /* Compute pixel size, (shared with contact shadows) */
  copy_v2_v2(common_data->ssr_pixelsize, viewport_size);
  invert_v2(common_data->ssr_pixelsize);

  if (scene_eval->eevee.flag & SCE_EEVEE_SSR_ENABLED) {
    const bool use_refraction = (scene_eval->eevee.flag & SCE_EEVEE_SSR_REFRACTION) != 0;

    if (use_refraction) {
      /* TODO: Opti: Could be shared. */
      DRW_texture_ensure_fullscreen_2d(
          &txl->refract_color, GPU_R11F_G11F_B10F, DRW_TEX_FILTER | DRW_TEX_MIPMAP);

      GPU_framebuffer_ensure_config(
          &fbl->refract_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->refract_color)});
    }

    const bool is_persp = DRW_view_is_persp_get(NULL);
    if (effects->ssr_was_persp != is_persp) {
      effects->ssr_was_persp = is_persp;
      DRW_viewport_request_redraw();
      EEVEE_temporal_sampling_reset(vedata);
      stl->g_data->valid_double_buffer = false;
    }

    effects->reflection_trace_full = (scene_eval->eevee.flag & SCE_EEVEE_SSR_HALF_RESOLUTION) == 0;
    common_data->ssr_thickness = scene_eval->eevee.ssr_thickness;
    common_data->ssr_border_fac = scene_eval->eevee.ssr_border_fade;
    common_data->ssr_firefly_fac = scene_eval->eevee.ssr_firefly_fac;
    common_data->ssr_max_roughness = scene_eval->eevee.ssr_max_roughness;
    common_data->ssr_quality = 1.0f - 0.95f * scene_eval->eevee.ssr_quality;
    common_data->ssr_brdf_bias = 0.1f + common_data->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */

    if (common_data->ssr_firefly_fac < 1e-8f) {
      common_data->ssr_firefly_fac = FLT_MAX;
    }

    const int divisor = (effects->reflection_trace_full) ? 1 : 2;
    int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
    int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]};
    const bool high_qual_input = true; /* TODO dither low quality input */
    const eGPUTextureFormat format = (high_qual_input) ? GPU_RGBA16F : GPU_RGBA8;

    /* MRT for the shading pass in order to output needed data for the SSR pass. */
    effects->ssr_specrough_input = DRW_texture_pool_query_2d(
        size_fs[0], size_fs[1], format, &draw_engine_eevee_type);

    GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_specrough_input, 2, 0);

    /* Raytracing output */
    effects->ssr_hit_output = DRW_texture_pool_query_2d(
        tracing_res[0], tracing_res[1], GPU_RG16I, &draw_engine_eevee_type);
    effects->ssr_pdf_output = DRW_texture_pool_query_2d(
        tracing_res[0], tracing_res[1], GPU_R16F, &draw_engine_eevee_type);

    GPU_framebuffer_ensure_config(&fbl->screen_tracing_fb,
                                  {GPU_ATTACHMENT_NONE,
                                   GPU_ATTACHMENT_TEXTURE(effects->ssr_hit_output),
                                   GPU_ATTACHMENT_TEXTURE(effects->ssr_pdf_output)});

    /* Enable double buffering to be able to read previous frame color */
    return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER |
           ((use_refraction) ? EFFECT_REFRACT : 0);
  }

  /* Cleanup to release memory */
  GPU_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb);
  effects->ssr_specrough_input = NULL;
  effects->ssr_hit_output = NULL;
  effects->ssr_pdf_output = NULL;

  return 0;
}
Beispiel #10
0
/**
 * Copies data from loop/poly to face (assumes all triangles or quads, as generated by most subdivisions)
 */
static void loops_to_customdata_corners(DerivedMesh *output)
{
	int i, numPolys, numTex, numCol, hasPCol;

	MPoly *polys;
	
	//if (!CustomData_get_layer_n(&output->loopData, CD_MLOOPCOL, n)) {
		// Not sure how this works with "n" ? 
	//	CustomData_add_layer(&output->loopData, CD_MLOOPCOL, CD_CALLOC, NULL, output->numVertData);
	//}

	numCol = CustomData_number_of_layers(&output->loopData, CD_MLOOPCOL);
	numTex = CustomData_number_of_layers(&output->loopData, CD_MLOOPUV);
	hasPCol = CustomData_has_layer(&output->loopData, CD_PREVIEW_MLOOPCOL);
	
	polys = output->getPolyArray(output);
	numPolys = output->getNumPolys(output);

	for (i = 0; i < numTex; i++) {
		int k;
		MTexPoly *texpoly = CustomData_get_layer_n(&output->polyData, CD_MTEXPOLY, i);
		MLoopUV *mloopuv = CustomData_get_layer_n(&output->loopData, CD_MLOOPUV, i);
		MTFace *texface = CustomData_get_layer_n(&output->faceData, CD_MTFACE, i);
		if (!texface) {
			texface = CustomData_add_layer(&output->faceData, CD_MTFACE, CD_CALLOC, NULL, numPolys);
		}

		for (k = 0; k < numPolys; k++) {
			int j;
			MPoly *poly = &polys[k];
			MLoopUV *ml = &mloopuv[poly->loopstart];
			
			ME_MTEXFACE_CPY(&texface[k], &texpoly[k]);
			for (j = 0; j < poly->totloop; j++) {
				copy_v2_v2(texface[k].uv[j], ml[j].uv);
			}
		}
	}

	for (i = 0; i < numCol; i++) {
		int k;
		MLoopCol *mloopcol = CustomData_get_layer_n(&output->loopData, CD_MLOOPCOL, i);
		MCol *mcol = CustomData_get_layer_n(&output->faceData, CD_MCOL, i);
		if (!mcol) {
			mcol = CustomData_add_layer(&output->faceData, CD_MCOL, CD_CALLOC, NULL, numPolys * 4);
		}
		for (k = 0; k < numPolys; k++) {
			int j;
			MPoly *poly = &polys[k];
			MLoopCol *ml = &mloopcol[poly->loopstart];
			for (j = 0; j < poly->totloop; j++) {
				MESH_MLOOPCOL_TO_MCOL(&ml[j], &mcol[j]);
			}
			mcol += 4;
		}
	}
	
	if (hasPCol) {
		int k;
		MLoopCol *mloopcol = CustomData_get_layer(&output->loopData, CD_PREVIEW_MLOOPCOL);
		MCol *mcol = CustomData_get_layer(&output->faceData, CD_PREVIEW_MCOL);
		if (!mcol) {
			mcol = CustomData_add_layer(&output->faceData, CD_MCOL, CD_CALLOC, NULL, numPolys * 4);
		}
		for (k = 0; k < numPolys; k++) {
			int j;
			MPoly *poly = &polys[k];
			MLoopCol *ml = &mloopcol[poly->loopstart];
			for (j = 0; j < poly->totloop; j++) {
				MESH_MLOOPCOL_TO_MCOL(&ml[j], &mcol[j]);
			}
			mcol += 4;
		}
	}
}
Beispiel #11
0
/**
 * This function populates pixel_array and returns TRUE if things are correct
 */
static bool cast_ray_highpoly(
        BVHTreeFromMesh *treeData, TriTessFace *triangles[], BakePixel *pixel_array, BakeHighPolyData *highpoly,
        const float co[3], const float dir[3], const int pixel_id, const int tot_highpoly,
        const float du_dx, const float du_dy, const float dv_dx, const float dv_dy)
{
	int i;
	int primitive_id = -1;
	float uv[2];
	int hit_mesh = -1;
	float hit_distance = FLT_MAX;

	BVHTreeRayHit *hits;
	hits = MEM_mallocN(sizeof(BVHTreeRayHit) * tot_highpoly, "Bake Highpoly to Lowpoly: BVH Rays");

	for (i = 0; i < tot_highpoly; i++) {
		float co_high[3], dir_high[3];

		hits[i].index = -1;
		/* TODO: we should use FLT_MAX here, but sweepsphere code isn't prepared for that */
		hits[i].dist = 10000.0f;

		/* transform the ray from the world space to the highpoly space */
		mul_v3_m4v3(co_high, highpoly[i].imat, co);

		/* rotates */
		mul_v3_mat3_m4v3(dir_high, highpoly[i].imat, dir);
		normalize_v3(dir_high);

		/* cast ray */
		if (treeData[i].tree) {
			BLI_bvhtree_ray_cast(treeData[i].tree, co_high, dir_high, 0.0f, &hits[i], treeData[i].raycast_callback, &treeData[i]);
		}

		if (hits[i].index != -1) {
			/* cull backface */
			const float dot = dot_v3v3(dir_high, hits[i].no);
			if (dot < 0.0f) {
				float distance;
				float hit_world[3];

				/* distance comparison in world space */
				mul_v3_m4v3(hit_world, highpoly[i].obmat, hits[i].co);
				distance = len_squared_v3v3(hit_world, co);

				if (distance < hit_distance) {
					hit_mesh = i;
					hit_distance = distance;
				}
			}
		}
	}

	if (hit_mesh != -1) {
		calc_barycentric_from_point(triangles[hit_mesh], hits[hit_mesh].index, hits[hit_mesh].co, &primitive_id, uv);
		pixel_array[pixel_id].primitive_id = primitive_id;
		pixel_array[pixel_id].object_id = hit_mesh;
		copy_v2_v2(pixel_array[pixel_id].uv, uv);

		/* the differentials are relative to the UV/image space, so the highpoly differentials
		 * are the same as the low poly differentials */
		pixel_array[pixel_id].du_dx = du_dx;
		pixel_array[pixel_id].du_dy = du_dy;
		pixel_array[pixel_id].dv_dx = dv_dx;
		pixel_array[pixel_id].dv_dy = dv_dy;
	}
	else {
		pixel_array[pixel_id].primitive_id = -1;
		pixel_array[pixel_id].object_id = -1;
	}

	MEM_freeN(hits);
	return hit_mesh != -1;
}
Beispiel #12
0
static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2],
                                        int num_points, char handle_type)
{
	ScrArea *sa = CTX_wm_area(C);
	Scene *scene = CTX_data_scene(C);
	Mask *mask;
	MaskLayer *mask_layer;
	MaskSpline *new_spline;
	float scale, location[2], frame_size[2];
	int i, width, height;
	int size = RNA_float_get(op->ptr, "size");

	ED_mask_get_size(sa, &width, &height);
	scale = (float)size / max_ii(width, height);

	/* Get location in mask space. */
	frame_size[0] = width;
	frame_size[1] = height;
	RNA_float_get_array(op->ptr, "location", location);
	location[0] /= width;
	location[1] /= height;
	BKE_mask_coord_from_frame(location, location, frame_size);

	/* Make it so new primitive is centered to mouse location. */
	location[0] -= 0.5f * scale;
	location[1] -= 0.5f * scale;

	mask_layer = ED_mask_layer_ensure(C);
	mask = CTX_data_edit_mask(C);

	ED_mask_select_toggle_all(mask, SEL_DESELECT);

	new_spline = BKE_mask_spline_add(mask_layer);
	new_spline->flag = MASK_SPLINE_CYCLIC | SELECT;
	new_spline->tot_point = num_points;
	new_spline->points = MEM_recallocN(new_spline->points,
	                                   sizeof(MaskSplinePoint) * new_spline->tot_point);

	mask_layer->act_spline = new_spline;
	mask_layer->act_point = NULL;

	for (i = 0; i < num_points; i++) {
		MaskSplinePoint *new_point = &new_spline->points[i];
		BKE_mask_parent_init(&new_point->parent);

		copy_v2_v2(new_point->bezt.vec[1], points[i]);
		mul_v2_fl(new_point->bezt.vec[1], scale);
		add_v2_v2(new_point->bezt.vec[1], location);

		new_point->bezt.h1 = handle_type;
		new_point->bezt.h2 = handle_type;
		BKE_mask_point_select_set(new_point, true);
	}

	WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask);

	/* TODO: only update this spline */
	BKE_mask_update_display(mask, CFRA);

	return OPERATOR_FINISHED;
}
Beispiel #13
0
static void setup_vertex_point(
        Mask *mask, MaskSpline *spline, MaskSplinePoint *new_point,
        const float point_co[2], const float u, const float ctime,
        const MaskSplinePoint *reference_point, const bool reference_adjacent)
{
	const MaskSplinePoint *reference_parent_point = NULL;
	BezTriple *bezt;
	float co[3];

	copy_v2_v2(co, point_co);
	co[2] = 0.0f;

	/* point coordinate */
	bezt = &new_point->bezt;

	bezt->h1 = bezt->h2 = HD_ALIGN;

	if (reference_point) {
		if (reference_point->bezt.h1 == HD_VECT && reference_point->bezt.h2 == HD_VECT) {
			/* If the reference point is sharp try using some smooth point as reference
			 * for handles.
			 */
			int point_index = reference_point - spline->points;
			int delta = new_point == spline->points ? 1 : -1;
			int i = 0;
			for (i = 0; i < spline->tot_point - 1; ++i) {
				MaskSplinePoint *current_point;

				point_index += delta;
				if (point_index == -1 || point_index >= spline->tot_point) {
					if (spline->flag & MASK_SPLINE_CYCLIC) {
						if (point_index == -1) {
							point_index = spline->tot_point - 1;
						}
						else if (point_index >= spline->tot_point) {
							point_index = 0;
						}
					}
					else {
						break;
					}
				}

				current_point = &spline->points[point_index];
				if (current_point->bezt.h1 != HD_VECT || current_point->bezt.h2 != HD_VECT) {
					bezt->h1 = bezt->h2 = MAX2(current_point->bezt.h2, current_point->bezt.h1);
					break;
				}
			}
		}
		else {
			bezt->h1 = bezt->h2 = MAX2(reference_point->bezt.h2, reference_point->bezt.h1);
		}

		reference_parent_point = reference_point;
	}
	else if (reference_adjacent) {
		if (spline->tot_point != 1) {
			MaskSplinePoint *prev_point, *next_point, *close_point;

			const int index = (int)(new_point - spline->points);
			if (spline->flag & MASK_SPLINE_CYCLIC) {
				prev_point = &spline->points[mod_i(index - 1, spline->tot_point)];
				next_point = &spline->points[mod_i(index + 1, spline->tot_point)];
			}
			else {
				prev_point = (index != 0)                     ? &spline->points[index - 1] : NULL;
				next_point = (index != spline->tot_point - 1) ? &spline->points[index + 1] : NULL;
			}

			if (prev_point && next_point) {
				close_point = (len_squared_v2v2(new_point->bezt.vec[1], prev_point->bezt.vec[1]) <
				               len_squared_v2v2(new_point->bezt.vec[1], next_point->bezt.vec[1])) ?
				               prev_point : next_point;
			}
			else {
				close_point = prev_point ? prev_point : next_point;
			}

			/* handle type */
			char handle_type = 0;
			if (prev_point) {
				handle_type = prev_point->bezt.h2;
			}
			if (next_point) {
				handle_type = MAX2(next_point->bezt.h2, handle_type);
			}
			bezt->h1 = bezt->h2 = handle_type;

			/* parent */
			reference_parent_point = close_point;

			/* note, we may want to copy other attributes later, radius? pressure? color? */
		}
	}

	copy_v3_v3(bezt->vec[0], co);
	copy_v3_v3(bezt->vec[1], co);
	copy_v3_v3(bezt->vec[2], co);

	if (reference_parent_point) {
		new_point->parent = reference_parent_point->parent;

		if (new_point->parent.id) {
			float parent_matrix[3][3];
			BKE_mask_point_parent_matrix_get(new_point, ctime, parent_matrix);
			invert_m3(parent_matrix);
			mul_m3_v2(parent_matrix, new_point->bezt.vec[1]);
		}
	}
	else {
		BKE_mask_parent_init(&new_point->parent);
	}

	if (spline->tot_point != 1) {
		BKE_mask_calc_handle_adjacent_interp(spline, new_point, u);
	}

	/* select new point */
	MASKPOINT_SEL_ALL(new_point);
	ED_mask_select_flush_all(mask);
}
Beispiel #14
0
static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
                                         Object *ob, DerivedMesh *dm)
{
	float (*coords)[3], (*co)[3];
	MLoopUV *mloop_uv;
	MTexPoly *mtexpoly, *mt = NULL;
	int i, numVerts, numPolys, numLoops;
	Image *image = umd->image;
	MPoly *mpoly, *mp;
	MLoop *mloop;
	const bool override_image = (umd->flags & MOD_UVPROJECT_OVERRIDEIMAGE) != 0;
	Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
	int num_projectors = 0;
	char uvname[MAX_CUSTOMDATA_LAYER_NAME];
	float aspx = umd->aspectx ? umd->aspectx : 1.0f;
	float aspy = umd->aspecty ? umd->aspecty : 1.0f;
	float scax = umd->scalex ? umd->scalex : 1.0f;
	float scay = umd->scaley ? umd->scaley : 1.0f;
	int free_uci = 0;

	for (i = 0; i < umd->num_projectors; ++i)
		if (umd->projectors[i])
			projectors[num_projectors++].ob = umd->projectors[i];

	if (num_projectors == 0) return dm;

	/* make sure there are UV Maps available */

	if (!CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) return dm;

	/* make sure we're using an existing layer */
	CustomData_validate_layer_name(&dm->loopData, CD_MLOOPUV, umd->uvlayer_name, uvname);

	/* calculate a projection matrix and normal for each projector */
	for (i = 0; i < num_projectors; ++i) {
		float tmpmat[4][4];
		float offsetmat[4][4];
		Camera *cam = NULL;
		/* calculate projection matrix */
		invert_m4_m4(projectors[i].projmat, projectors[i].ob->obmat);

		projectors[i].uci = NULL;

		if (projectors[i].ob->type == OB_CAMERA) {
			
			cam = (Camera *)projectors[i].ob->data;
			if (cam->type == CAM_PANO) {
				projectors[i].uci = BLI_uvproject_camera_info(projectors[i].ob, NULL, aspx, aspy);
				BLI_uvproject_camera_info_scale(projectors[i].uci, scax, scay);
				free_uci = 1;
			}
			else {
				CameraParams params;

				/* setup parameters */
				BKE_camera_params_init(&params);
				BKE_camera_params_from_object(&params, projectors[i].ob);

				/* compute matrix, viewplane, .. */
				BKE_camera_params_compute_viewplane(&params, 1, 1, aspx, aspy);

				/* scale the view-plane */
				params.viewplane.xmin *= scax;
				params.viewplane.xmax *= scax;
				params.viewplane.ymin *= scay;
				params.viewplane.ymax *= scay;

				BKE_camera_params_compute_matrix(&params);
				mul_m4_m4m4(tmpmat, params.winmat, projectors[i].projmat);
			}
		}
		else {
			copy_m4_m4(tmpmat, projectors[i].projmat);
		}

		unit_m4(offsetmat);
		mul_mat3_m4_fl(offsetmat, 0.5);
		offsetmat[3][0] = offsetmat[3][1] = offsetmat[3][2] = 0.5;

		mul_m4_m4m4(projectors[i].projmat, offsetmat, tmpmat);

		/* calculate worldspace projector normal (for best projector test) */
		projectors[i].normal[0] = 0;
		projectors[i].normal[1] = 0;
		projectors[i].normal[2] = 1;
		mul_mat3_m4_v3(projectors[i].ob->obmat, projectors[i].normal);
	}

	numPolys = dm->getNumPolys(dm);
	numLoops = dm->getNumLoops(dm);

	/* make sure we are not modifying the original UV map */
	mloop_uv = CustomData_duplicate_referenced_layer_named(&dm->loopData,
	                                                       CD_MLOOPUV, uvname, numLoops);

	/* can be NULL */
	mt = mtexpoly = CustomData_duplicate_referenced_layer_named(&dm->polyData,
	                                                            CD_MTEXPOLY, uvname, numPolys);

	numVerts = dm->getNumVerts(dm);

	coords = MEM_malloc_arrayN(numVerts, sizeof(*coords),
	                     "uvprojectModifier_do coords");
	dm->getVertCos(dm, coords);

	/* convert coords to world space */
	for (i = 0, co = coords; i < numVerts; ++i, ++co)
		mul_m4_v3(ob->obmat, *co);
	
	/* if only one projector, project coords to UVs */
	if (num_projectors == 1 && projectors[0].uci == NULL)
		for (i = 0, co = coords; i < numVerts; ++i, ++co)
			mul_project_m4_v3(projectors[0].projmat, *co);

	mpoly = dm->getPolyArray(dm);
	mloop = dm->getLoopArray(dm);

	/* apply coords as UVs, and apply image if tfaces are new */
	for (i = 0, mp = mpoly; i < numPolys; ++i, ++mp, ++mt) {
		if (override_image || !image || (mtexpoly == NULL || mt->tpage == image)) {
			if (num_projectors == 1) {
				if (projectors[0].uci) {
					unsigned int fidx = mp->totloop - 1;
					do {
						unsigned int lidx = mp->loopstart + fidx;
						unsigned int vidx = mloop[lidx].v;
						BLI_uvproject_from_camera(mloop_uv[lidx].uv, coords[vidx], projectors[0].uci);
					} while (fidx--);
				}
				else {
					/* apply transformed coords as UVs */
					unsigned int fidx = mp->totloop - 1;
					do {
						unsigned int lidx = mp->loopstart + fidx;
						unsigned int vidx = mloop[lidx].v;
						copy_v2_v2(mloop_uv[lidx].uv, coords[vidx]);
					} while (fidx--);
				}
			}
			else {
				/* multiple projectors, select the closest to face normal direction */
				float face_no[3];
				int j;
				Projector *best_projector;
				float best_dot;

				/* get the untransformed face normal */
				BKE_mesh_calc_poly_normal_coords(mp, mloop + mp->loopstart, (const float (*)[3])coords, face_no);

				/* find the projector which the face points at most directly
				 * (projector normal with largest dot product is best)
				 */
				best_dot = dot_v3v3(projectors[0].normal, face_no);
				best_projector = &projectors[0];

				for (j = 1; j < num_projectors; ++j) {
					float tmp_dot = dot_v3v3(projectors[j].normal,
					                         face_no);
					if (tmp_dot > best_dot) {
						best_dot = tmp_dot;
						best_projector = &projectors[j];
					}
				}

				if (best_projector->uci) {
					unsigned int fidx = mp->totloop - 1;
					do {
						unsigned int lidx = mp->loopstart + fidx;
						unsigned int vidx = mloop[lidx].v;
						BLI_uvproject_from_camera(mloop_uv[lidx].uv, coords[vidx], best_projector->uci);
					} while (fidx--);
				}
				else {
					unsigned int fidx = mp->totloop - 1;
					do {
						unsigned int lidx = mp->loopstart + fidx;
						unsigned int vidx = mloop[lidx].v;
						mul_v2_project_m4_v3(mloop_uv[lidx].uv, best_projector->projmat, coords[vidx]);
					} while (fidx--);
				}
			}
		}

		if (override_image && mtexpoly) {
			mt->tpage = image;
		}
	}

	MEM_freeN(coords);
	
	if (free_uci) {
		int j;
		for (j = 0; j < num_projectors; ++j) {
			if (projectors[j].uci) {
				MEM_freeN(projectors[j].uci);
			}
		}
	}

	/* Mark tessellated CD layers as dirty. */
	dm->dirty |= DM_DIRTY_TESS_CDLAYERS;

	return dm;
}
Beispiel #15
0
static int walkApply(bContext *C, wmOperator *op, WalkInfo *walk)
{
#define WALK_ROTATE_FAC 2.2f /* more is faster */
#define WALK_TOP_LIMIT DEG2RADF(85.0f)
#define WALK_BOTTOM_LIMIT DEG2RADF(-80.0f)
#define WALK_MOVE_SPEED base_speed
#define WALK_BOOST_FACTOR ((void)0, walk->speed_factor)

	/* walk mode - Ctrl+Shift+F
	 * a walk loop where the user can move move the view as if they are in a walk game
	 */
	RegionView3D *rv3d = walk->rv3d;
	ARegion *ar = walk->ar;

	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	float dvec[3] = {0.0f, 0.0f, 0.0f}; /* this is the direction that's added to the view offset per redraw */

	int moffset[2]; /* mouse offset from the views center */
	float tmp_quat[4]; /* used for rotating the view */

#ifdef NDOF_WALK_DEBUG
	{
		static unsigned int iteration = 1;
		printf("walk timer %d\n", iteration++);
	}
#endif

	{
		/* mouse offset from the center */
		copy_v2_v2_int(moffset, walk->moffset);

		/* apply moffset so we can re-accumulate */
		walk->moffset[0] = 0;
		walk->moffset[1] = 0;

		/* revert mouse */
		if (walk->is_reversed) {
			moffset[1] = -moffset[1];
		}

		/* Should we redraw? */
		if ((walk->active_directions) ||
		    moffset[0] || moffset[1] ||
		    walk->teleport.state == WALK_TELEPORT_STATE_ON ||
		    walk->gravity_state != WALK_GRAVITY_STATE_OFF)
		{
			float dvec_tmp[3];

			/* time how fast it takes for us to redraw,
			 * this is so simple scenes don't walk too fast */
			double time_current;
			float time_redraw;
#ifdef NDOF_WALK_DRAW_TOOMUCH
			walk->redraw = 1;
#endif
			time_current = PIL_check_seconds_timer();
			time_redraw = (float)(time_current - walk->time_lastdraw);

			walk->time_lastdraw = time_current;

			/* base speed in m/s */
			walk->speed = WALK_MOVE_SPEED;

			if (walk->is_fast) {
				walk->speed *= WALK_BOOST_FACTOR;
			}
			else if (walk->is_slow) {
				walk->speed *= 1.0f / WALK_BOOST_FACTOR;
			}

			copy_m3_m4(mat, rv3d->viewinv);

			{
				/* rotate about the X axis- look up/down */
				if (moffset[1]) {
					float upvec[3];
					float angle;
					float y;

					/* relative offset */
					y = (float) moffset[1] / ar->winy;

					/* speed factor */
					y *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					y *= walk->mouse_speed;

					/* clamp the angle limits */
					/* it ranges from 90.0f to -90.0f */
					angle = -asinf(rv3d->viewmat[2][2]);

					if (angle > WALK_TOP_LIMIT && y > 0.0f)
						y = 0.0f;

					else if (angle < WALK_BOTTOM_LIMIT && y < 0.0f)
						y = 0.0f;

					copy_v3_fl3(upvec, 1.0f, 0.0f, 0.0f);
					mul_m3_v3(mat, upvec);
					/* Rotate about the relative up vec */
					axis_angle_to_quat(tmp_quat, upvec, -y);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}

				/* rotate about the Y axis- look left/right */
				if (moffset[0]) {
					float upvec[3];
					float x;

					/* if we're upside down invert the moffset */
					copy_v3_fl3(upvec, 0.0f, 1.0f, 0.0f);
					mul_m3_v3(mat, upvec);

					if (upvec[2] < 0.0f)
						moffset[0] = -moffset[0];

					/* relative offset */
					x = (float) moffset[0] / ar->winx;

					/* speed factor */
					x *= WALK_ROTATE_FAC;

					/* user adjustement factor */
					x *= walk->mouse_speed;

					/* Rotate about the relative up vec */
					axis_angle_to_quat_single(tmp_quat, 'Z', x);
					mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat);
				}
			}

			/* WASD - 'move' translation code */
			if ((walk->active_directions) &&
			    (walk->gravity_state == WALK_GRAVITY_STATE_OFF))
			{

				short direction;
				zero_v3(dvec);

				if ((walk->active_directions & WALK_BIT_FORWARD) ||
				    (walk->active_directions & WALK_BIT_BACKWARD))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_FORWARD))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_BACKWARD))
						direction -= 1;

					copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
					mul_m3_v3(mat, dvec_tmp);

					if (walk->navigation_mode == WALK_MODE_GRAVITY) {
						dvec_tmp[2] = 0.0f;
					}

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_LEFT) ||
				    (walk->active_directions & WALK_BIT_RIGHT))
				{

					direction = 0;

					if ((walk->active_directions & WALK_BIT_LEFT))
						direction += 1;

					if ((walk->active_directions & WALK_BIT_RIGHT))
						direction -= 1;

					dvec_tmp[0] = direction * rv3d->viewinv[0][0];
					dvec_tmp[1] = direction * rv3d->viewinv[0][1];
					dvec_tmp[2] = 0.0f;

					normalize_v3(dvec_tmp);
					add_v3_v3(dvec, dvec_tmp);

				}

				if ((walk->active_directions & WALK_BIT_UP) ||
				    (walk->active_directions & WALK_BIT_DOWN))
				{

					if (walk->navigation_mode == WALK_MODE_FREE) {

						direction = 0;

						if ((walk->active_directions & WALK_BIT_UP))
							direction -= 1;

						if ((walk->active_directions & WALK_BIT_DOWN))
							direction = 1;

						copy_v3_fl3(dvec_tmp, 0.0f, 0.0f, direction);
						add_v3_v3(dvec, dvec_tmp);
					}
				}

				/* apply movement */
				mul_v3_fl(dvec, walk->speed * time_redraw);
			}

			/* stick to the floor */
			if (walk->navigation_mode == WALK_MODE_GRAVITY &&
			    ELEM(walk->gravity_state,
			         WALK_GRAVITY_STATE_OFF,
			         WALK_GRAVITY_STATE_START))
			{

				bool ret;
				float ray_distance;
				float difference = -100.0f;
				float fall_distance;

				ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);

				if (ret) {
					difference = walk->view_height - ray_distance;
				}

				/* the distance we would fall naturally smoothly enough that we
				 * can manually drop the object without activating gravity */
				fall_distance = time_redraw * walk->speed * WALK_BOOST_FACTOR;

				if (fabsf(difference) < fall_distance) {
					/* slope/stairs */
					dvec[2] -= difference;

					/* in case we switched from FREE to GRAVITY too close to the ground */
					if (walk->gravity_state == WALK_GRAVITY_STATE_START)
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
				}
				else {
					/* hijack the teleport variables */
					walk->teleport.initial_time = PIL_check_seconds_timer();
					walk->gravity_state = WALK_GRAVITY_STATE_ON;
					walk->teleport.duration = 0.0f;

					copy_v3_v3(walk->teleport.origin, walk->rv3d->viewinv[3]);
					copy_v2_v2(walk->teleport.direction, dvec);

				}
			}

			/* Falling or jumping) */
			if (ELEM(walk->gravity_state, WALK_GRAVITY_STATE_ON, WALK_GRAVITY_STATE_JUMP)) {
				float t;
				float z_cur, z_new;
				bool ret;
				float ray_distance, difference = -100.0f;

				/* delta time */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);

				/* keep moving if we were moving */
				copy_v2_v2(dvec, walk->teleport.direction);

				z_cur = walk->rv3d->viewinv[3][2];
				z_new = walk->teleport.origin[2] - getFreeFallDistance(walk->gravity, t) * walk->grid;

				/* jump */
				z_new += t * walk->speed_jump * walk->grid;

				/* duration is the jump duration */
				if (t > walk->teleport.duration) {

					/* check to see if we are landing */
					ret = walk_floor_distance_get(rv3d, walk, dvec, &ray_distance);

					if (ret) {
						difference = walk->view_height - ray_distance;
					}

					if (difference > 0.0f) {
						/* quit falling, lands at "view_height" from the floor */
						dvec[2] -= difference;
						walk->gravity_state = WALK_GRAVITY_STATE_OFF;
						walk->speed_jump = 0.0f;
					}
					else {
						/* keep falling */
						dvec[2] = z_cur - z_new;
					}
				}
				else {
					/* keep going up (jump) */
					dvec[2] = z_cur - z_new;
				}
			}

			/* Teleport */
			else if (walk->teleport.state == WALK_TELEPORT_STATE_ON) {
				float t; /* factor */
				float new_loc[3];
				float cur_loc[3];

				/* linear interpolation */
				t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time);
				t /= walk->teleport.duration;

				/* clamp so we don't go past our limit */
				if (t >= 1.0f) {
					t = 1.0f;
					walk->teleport.state = WALK_TELEPORT_STATE_OFF;
					walk_navigation_mode_set(C, op, walk, walk->teleport.navigation_mode);
				}

				mul_v3_v3fl(new_loc, walk->teleport.direction, t);
				add_v3_v3(new_loc, walk->teleport.origin);

				copy_v3_v3(cur_loc, walk->rv3d->viewinv[3]);
				sub_v3_v3v3(dvec, cur_loc, new_loc);
			}

			if (rv3d->persp == RV3D_CAMOB) {
				Object *lock_ob = ED_view3d_cameracontrol_object_get(walk->v3d_camera_control);
				if (lock_ob->protectflag & OB_LOCK_LOCX) dvec[0] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCY) dvec[1] = 0.0f;
				if (lock_ob->protectflag & OB_LOCK_LOCZ) dvec[2] = 0.0f;
			}

			/* scale the movement to the scene size */
			mul_v3_v3fl(dvec_tmp, dvec, walk->grid);
			add_v3_v3(rv3d->ofs, dvec_tmp);

			if (rv3d->persp == RV3D_CAMOB) {
				const bool do_rotate = (moffset[0] || moffset[1]);
				const bool do_translate = (walk->speed != 0.0f);
				walkMoveCamera(C, walk, do_rotate, do_translate);
			}
		}
		else {
			/* we're not redrawing but we need to update the time else the view will jump */
			walk->time_lastdraw = PIL_check_seconds_timer();
		}
		/* end drawing */
		copy_v3_v3(walk->dvec_prev, dvec);
	}

	return OPERATOR_FINISHED;
#undef WALK_ROTATE_FAC
#undef WALK_ZUP_CORRECT_FAC
#undef WALK_ZUP_CORRECT_ACCEL
#undef WALK_SMOOTH_FAC
#undef WALK_TOP_LIMIT
#undef WALK_BOTTOM_LIMIT
#undef WALK_MOVE_SPEED
#undef WALK_BOOST_FACTOR
}
Beispiel #16
0
static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
{
	SlidePointData *data = (SlidePointData *)op->customdata;
	BezTriple *bezt = &data->point->bezt;
	float co[2], dco[2];

	switch (event->type) {
		case LEFTCTRLKEY:
		case RIGHTCTRLKEY:
		case LEFTSHIFTKEY:
		case RIGHTSHIFTKEY:
			if (ELEM(event->type, LEFTCTRLKEY, RIGHTCTRLKEY)) {
				if (data->action == SLIDE_ACTION_FEATHER)
					data->overall_feather = event->val == KM_PRESS;
				else
					data->curvature_only = event->val == KM_PRESS;
			}

			if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY))
				data->accurate = event->val == KM_PRESS;

		/* no break! update CV position */

		case MOUSEMOVE:
		{
			ScrArea *sa = CTX_wm_area(C);
			ARegion *ar = CTX_wm_region(C);

			ED_mask_mouse_pos(sa, ar, event, co);
			sub_v2_v2v2(dco, co, data->co);

			if (data->action == SLIDE_ACTION_HANDLE) {
				float delta[2], offco[2];

				sub_v2_v2v2(delta, data->handle, data->co);

				sub_v2_v2v2(offco, co, data->co);
				if (data->accurate)
					mul_v2_fl(offco, 0.2f);
				add_v2_v2(offco, data->co);
				add_v2_v2(offco, delta);

				BKE_mask_point_set_handle(data->point, offco, data->curvature_only, data->handle, data->vec);
			}
			else if (data->action == SLIDE_ACTION_POINT) {
				float delta[2];

				copy_v2_v2(delta, dco);
				if (data->accurate)
					mul_v2_fl(delta, 0.2f);

				add_v2_v2v2(bezt->vec[0], data->vec[0], delta);
				add_v2_v2v2(bezt->vec[1], data->vec[1], delta);
				add_v2_v2v2(bezt->vec[2], data->vec[2], delta);
			}
			else if (data->action == SLIDE_ACTION_FEATHER) {
				float vec[2], no[2], p[2], c[2], w, offco[2];
				float *weight = NULL;
				float weight_scalar = 1.0f;
				int overall_feather = data->overall_feather || data->initial_feather;

				add_v2_v2v2(offco, data->feather, dco);

				if (data->uw) {
					/* project on both sides and find the closest one,
					 * prevents flickering when projecting onto both sides can happen */
					const float u_pos = BKE_mask_spline_project_co(data->spline, data->point,
					                                               data->uw->u, offco, MASK_PROJ_NEG);
					const float u_neg = BKE_mask_spline_project_co(data->spline, data->point,
					                                               data->uw->u, offco, MASK_PROJ_POS);
					float dist_pos = FLT_MAX;
					float dist_neg = FLT_MAX;
					float co_pos[2];
					float co_neg[2];
					float u;

					if (u_pos > 0.0f && u_pos < 1.0f) {
						BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
						dist_pos = len_squared_v2v2(offco, co_pos);
					}

					if (u_neg > 0.0f && u_neg < 1.0f) {
						BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
						dist_neg = len_squared_v2v2(offco, co_neg);
					}

					u = dist_pos < dist_neg ? u_pos : u_neg;

					if (u > 0.0f && u < 1.0f) {
						data->uw->u = u;

						data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
						weight = &data->uw->w;
						weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
						if (weight_scalar != 0.0f) {
							weight_scalar = 1.0f / weight_scalar;
						}

						BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
						BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
					}
				}
				else {
					weight = &bezt->weight;
					/* weight_scalar = 1.0f; keep as is */
					copy_v2_v2(no, data->no);
					copy_v2_v2(p, bezt->vec[1]);
				}

				if (weight) {
					sub_v2_v2v2(c, offco, p);
					project_v2_v2v2(vec, c, no);

					w = len_v2(vec);

					if (overall_feather) {
						float delta;

						if (dot_v2v2(no, vec) <= 0.0f)
							w = -w;

						delta = w - data->weight * data->weight_scalar;

						if (data->orig_spline == NULL) {
							/* restore weight for currently sliding point, so orig_spline would be created
							 * with original weights used
							 */
							*weight = data->weight;

							data->orig_spline = BKE_mask_spline_copy(data->spline);
						}

						slide_point_delta_all_feather(data, delta);
					}
					else {
						if (dot_v2v2(no, vec) <= 0.0f)
							w = 0.0f;

						if (data->orig_spline) {
							/* restore possible overall feather changes */
							slide_point_restore_spline(data);

							BKE_mask_spline_free(data->orig_spline);
							data->orig_spline = NULL;
						}

						if (weight_scalar != 0.0f) {
							*weight = w * weight_scalar;
						}
					}
				}
			}

			WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
			DAG_id_tag_update(&data->mask->id, 0);

			break;
		}

		case LEFTMOUSE:
			if (event->val == KM_RELEASE) {
				Scene *scene = CTX_data_scene(C);

				/* dont key sliding feather uw's */
				if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == FALSE) {
					if (IS_AUTOKEY_ON(scene)) {
						ED_mask_layer_shape_auto_key(data->masklay, CFRA);
					}
				}

				WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
				DAG_id_tag_update(&data->mask->id, 0);

				free_slide_point_data(op->customdata); /* keep this last! */
				return OPERATOR_FINISHED;
			}

			break;

		case ESCKEY:
			cancel_slide_point(op->customdata);

			WM_event_add_notifier(C, NC_MASK | NA_EDITED, data->mask);
			DAG_id_tag_update(&data->mask->id, 0);

			free_slide_point_data(op->customdata); /* keep this last! */
			return OPERATOR_CANCELLED;
	}

	return OPERATOR_RUNNING_MODAL;
}
Beispiel #17
0
static void cancel_mouse_slide_plane_marker(SlidePlaneMarkerData *data)
{
  copy_v2_v2(data->corner, data->old_corner);
}
Beispiel #18
0
static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], float dxt[2], float dyt[2], TexResult *texres, struct ImagePool *pool, const bool skip_load_image)
{
	TexResult texr;
	float fx, fy, minx, maxx, miny, maxy;
	float maxd, val1, val2, val3;
	int curmap, retval, intpol, extflag = 0;
	afdata_t AFD;

	void (*filterfunc)(TexResult*, ImBuf*, float, float, afdata_t*);
	switch (tex->texfilter) {
		case TXF_EWA:
			filterfunc = ewa_eval;
			break;
		case TXF_FELINE:
			filterfunc = feline_eval;
			break;
		case TXF_AREA:
		default:
			filterfunc = area_sample;
	}

	texres->tin = texres->ta = texres->tr = texres->tg = texres->tb = 0.f;

	/* we need to set retval OK, otherwise texture code generates normals itself... */
	retval = texres->nor ? 3 : 1;

	/* quick tests */
	if (ibuf==NULL && ima==NULL) return retval;

	if (ima) {	/* hack for icon render */
		if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
			return retval;
		}
		ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
	}

	if ((ibuf == NULL) || ((ibuf->rect == NULL) && (ibuf->rect_float == NULL))) {
		if (ima)
			BKE_image_pool_release_ibuf(ima, ibuf, pool);
		return retval;
	}

	if (ima) {
		ima->flag |= IMA_USED_FOR_RENDER;
	}

	/* mipmap test */
	image_mipmap_test(tex, ibuf);
	
	if (ima) {
		if ((tex->imaflag & TEX_USEALPHA) && (ima->flag & IMA_IGNORE_ALPHA) == 0) {
			if ((tex->imaflag & TEX_CALCALPHA) == 0) {
				texres->talpha = 1;
			}
		}
	}
	texr.talpha = texres->talpha;

	if (tex->imaflag & TEX_IMAROT) {
		fy = texvec[0];
		fx = texvec[1];
	}
	else {
		fx = texvec[0];
		fy = texvec[1];
	}

	if (ibuf->flags & IB_fields) {
		if (R.r.mode & R_FIELDS) {			/* field render */
			if (R.flag & R_SEC_FIELD) {		/* correction for 2nd field */
				/* fac1= 0.5/( (float)ibuf->y ); */
				/* fy-= fac1; */
			}
			else 	/* first field */
				fy += 0.5f/( (float)ibuf->y );
		}
	}

	/* pixel coordinates */
	minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
	maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
	miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
	maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);

	/* tex_sharper has been removed */
	minx = (maxx - minx)*0.5f;
	miny = (maxy - miny)*0.5f;

	if (tex->imaflag & TEX_FILTER_MIN) {
		/* make sure the filtersize is minimal in pixels (normal, ref map can have miniature pixel dx/dy) */
		const float addval = (0.5f * tex->filtersize) / (float)MIN2(ibuf->x, ibuf->y);
		if (addval > minx) minx = addval;
		if (addval > miny) miny = addval;
	}
	else if (tex->filtersize != 1.f) {
		minx *= tex->filtersize;
		miny *= tex->filtersize;
		dxt[0] *= tex->filtersize;
		dxt[1] *= tex->filtersize;
		dyt[0] *= tex->filtersize;
		dyt[1] *= tex->filtersize;
	}

	if (tex->imaflag & TEX_IMAROT) {
		float t;
		SWAP(float, minx, miny);
		/* must rotate dxt/dyt 90 deg
		 * yet another blender problem is that swapping X/Y axes (or any tex proj switches) should do something similar,
		 * but it doesn't, it only swaps coords, so filter area will be incorrect in those cases. */
		t = dxt[0];
		dxt[0] = dxt[1];
		dxt[1] = -t;
		t = dyt[0];
		dyt[0] = dyt[1];
		dyt[1] = -t;
	}

	/* side faces of unit-cube */
	minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
	miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);

	/* repeat and clip */

	if (tex->extend == TEX_REPEAT) {
		if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR))
			extflag = TXC_EXTD;
		else if (tex->flag & TEX_REPEAT_XMIR)
			extflag = TXC_XMIR;
		else if (tex->flag & TEX_REPEAT_YMIR)
			extflag = TXC_YMIR;
		else
			extflag = TXC_REPT;
	}
	else if (tex->extend == TEX_EXTEND)
		extflag = TXC_EXTD;

	if (tex->extend == TEX_CHECKER) {
		int xs = (int)floorf(fx), ys = (int)floorf(fy);
		/* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
		if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
			fx -= xs;
			fy -= ys;
		}
		else if ((tex->flag & TEX_CHECKER_ODD) == 0 &&
		         (tex->flag & TEX_CHECKER_EVEN) == 0)
		{
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
		else {
			int xs1 = (int)floorf(fx - minx);
			int ys1 = (int)floorf(fy - miny);
			int xs2 = (int)floorf(fx + minx);
			int ys2 = (int)floorf(fy + miny);
			if ((xs1 != xs2) || (ys1 != ys2)) {
				if (tex->flag & TEX_CHECKER_ODD) {
					fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
					fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
				}
				if (tex->flag & TEX_CHECKER_EVEN) {
					fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
					fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
				}
			}
			else {
				if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
					if (ima)
						BKE_image_pool_release_ibuf(ima, ibuf, pool);
					return retval;
				}
				if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
					if (ima)
						BKE_image_pool_release_ibuf(ima, ibuf, pool);
					return retval;
				}
				fx -= xs;
				fy -= ys;
			}
		}
		/* scale around center, (0.5, 0.5) */
		if (tex->checkerdist < 1.f) {
			const float omcd = 1.f / (1.f - tex->checkerdist);
			fx = (fx - 0.5f)*omcd + 0.5f;
			fy = (fy - 0.5f)*omcd + 0.5f;
			minx *= omcd;
			miny *= omcd;
		}
	}

	if (tex->extend == TEX_CLIPCUBE) {
		if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f || texvec[2] < -1.f || texvec[2] > 1.f) {
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
	}
	else if (tex->extend == TEX_CLIP || tex->extend == TEX_CHECKER) {
		if ((fx + minx) < 0.f || (fy + miny) < 0.f || (fx - minx) > 1.f || (fy - miny) > 1.f) {
			if (ima)
				BKE_image_pool_release_ibuf(ima, ibuf, pool);
			return retval;
		}
	}
	else {
		if (tex->extend == TEX_EXTEND) {
			fx = (fx > 1.f) ? 1.f : ((fx < 0.f) ? 0.f : fx);
			fy = (fy > 1.f) ? 1.f : ((fy < 0.f) ? 0.f : fy);
		}
		else {
			fx -= floorf(fx);
			fy -= floorf(fy);
		}
	}

	intpol = tex->imaflag & TEX_INTERPOL;

	/* warning no return! */
	if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
		ibuf->rect += ibuf->x*ibuf->y;

	/* struct common data */
	copy_v2_v2(AFD.dxt, dxt);
	copy_v2_v2(AFD.dyt, dyt);
	AFD.intpol = intpol;
	AFD.extflag = extflag;

	/* brecht: added stupid clamping here, large dx/dy can give very large
	 * filter sizes which take ages to render, it may be better to do this
	 * more intelligently later in the code .. probably it's not noticeable */
	if (AFD.dxt[0]*AFD.dxt[0] + AFD.dxt[1]*AFD.dxt[1] > 2.0f*2.0f)
		mul_v2_fl(AFD.dxt, 2.0f/len_v2(AFD.dxt));
	if (AFD.dyt[0]*AFD.dyt[0] + AFD.dyt[1]*AFD.dyt[1] > 2.0f*2.0f)
		mul_v2_fl(AFD.dyt, 2.0f/len_v2(AFD.dyt));

	/* choice: */
	if (tex->imaflag & TEX_MIPMAP) {
		ImBuf *previbuf, *curibuf;
		float levf;
		int maxlev;
		ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];

		/* modify ellipse minor axis if too eccentric, use for area sampling as well
		 * scaling dxt/dyt as done in pbrt is not the same
		 * (as in ewa_eval(), scale by sqrt(ibuf->x) to maximize precision) */
		const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
		const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
		const float A = Vx*Vx + Vy*Vy;
		const float B = -2.f*(Ux*Vx + Uy*Vy);
		const float C = Ux*Ux + Uy*Uy;
		const float F = A*C - B*B*0.25f;
		float a, b, th, ecc;
		BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
		if (tex->texfilter == TXF_FELINE) {
			float fProbes;
			a *= ff;
			b *= ff;
			a = max_ff(a, 1.0f);
			b = max_ff(b, 1.0f);
			fProbes = 2.f*(a / b) - 1.f;
			AFD.iProbes = round_fl_to_int(fProbes);
			AFD.iProbes = MIN2(AFD.iProbes, tex->afmax);
			if (AFD.iProbes < fProbes)
				b = 2.f*a / (float)(AFD.iProbes + 1);
			AFD.majrad = a/ff;
			AFD.minrad = b/ff;
			AFD.theta = th;
			AFD.dusc = 1.f/ff;
			AFD.dvsc = ff / (float)ibuf->y;
		}
		else {	/* EWA & area */
			if (ecc > (float)tex->afmax) b = a / (float)tex->afmax;
			b *= ff;
		}
		maxd = max_ff(b, 1e-8f);
		levf = ((float)M_LOG2E) * logf(maxd);

		curmap = 0;
		maxlev = 1;
		mipmaps[0] = ibuf;
		while (curmap < IMB_MIPMAP_LEVELS) {
			mipmaps[curmap + 1] = ibuf->mipmap[curmap];
			if (ibuf->mipmap[curmap]) maxlev++;
			curmap++;
		}

		/* mipmap level */
		if (levf < 0.f) {  /* original image only */
			previbuf = curibuf = mipmaps[0];
			levf = 0.f;
		}
		else if (levf >= maxlev - 1) {
			previbuf = curibuf = mipmaps[maxlev - 1];
			levf = 0.f;
			if (tex->texfilter == TXF_FELINE) AFD.iProbes = 1;
		}
		else {
			const int lev = isnan(levf) ? 0 : (int)levf;
			curibuf = mipmaps[lev];
			previbuf = mipmaps[lev + 1];
			levf -= floorf(levf);
		}

		/* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */

		if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
			/* color & normal */
			filterfunc(texres, curibuf, fx, fy, &AFD);
			val1 = texres->tr + texres->tg + texres->tb;
			filterfunc(&texr, curibuf, fx + dxt[0], fy + dxt[1], &AFD);
			val2 = texr.tr + texr.tg + texr.tb;
			filterfunc(&texr, curibuf, fx + dyt[0], fy + dyt[1], &AFD);
			val3 = texr.tr + texr.tg + texr.tb;
			/* don't switch x or y! */
			texres->nor[0] = val1 - val2;
			texres->nor[1] = val1 - val3;
			if (previbuf != curibuf) {  /* interpolate */
				filterfunc(&texr, previbuf, fx, fy, &AFD);
				/* rgb */
				texres->tr += levf*(texr.tr - texres->tr);
				texres->tg += levf*(texr.tg - texres->tg);
				texres->tb += levf*(texr.tb - texres->tb);
				texres->ta += levf*(texr.ta - texres->ta);
				/* normal */
				val1 += levf*((texr.tr + texr.tg + texr.tb) - val1);
				filterfunc(&texr, previbuf, fx + dxt[0], fy + dxt[1], &AFD);
				val2 += levf*((texr.tr + texr.tg + texr.tb) - val2);
				filterfunc(&texr, previbuf, fx + dyt[0], fy + dyt[1], &AFD);
				val3 += levf*((texr.tr + texr.tg + texr.tb) - val3);
				texres->nor[0] = val1 - val2;  /* vals have been interpolated above! */
				texres->nor[1] = val1 - val3;
			}
		}
		else {  /* color */
			filterfunc(texres, curibuf, fx, fy, &AFD);
			if (previbuf != curibuf) {  /* interpolate */
				filterfunc(&texr, previbuf, fx, fy, &AFD);
				texres->tr += levf*(texr.tr - texres->tr);
				texres->tg += levf*(texr.tg - texres->tg);
				texres->tb += levf*(texr.tb - texres->tb);
				texres->ta += levf*(texr.ta - texres->ta);
			}

			if (tex->texfilter != TXF_EWA) {
				alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
			}
		}
	}
	else {	/* no mipmap */
		/* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
		if (tex->texfilter == TXF_FELINE) {
			const float ff = sqrtf(ibuf->x), q = ibuf->y/ff;
			const float Ux = dxt[0]*ff, Vx = dxt[1]*q, Uy = dyt[0]*ff, Vy = dyt[1]*q;
			const float A = Vx*Vx + Vy*Vy;
			const float B = -2.f*(Ux*Vx + Uy*Vy);
			const float C = Ux*Ux + Uy*Uy;
			const float F = A*C - B*B*0.25f;
			float a, b, th, ecc, fProbes;
			BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
			a *= ff;
			b *= ff;
			a = max_ff(a, 1.0f);
			b = max_ff(b, 1.0f);
			fProbes = 2.f*(a / b) - 1.f;
			/* no limit to number of Probes here */
			AFD.iProbes = round_fl_to_int(fProbes);
			if (AFD.iProbes < fProbes) b = 2.f*a / (float)(AFD.iProbes + 1);
			AFD.majrad = a/ff;
			AFD.minrad = b/ff;
			AFD.theta = th;
			AFD.dusc = 1.f/ff;
			AFD.dvsc = ff / (float)ibuf->y;
		}
		if (texres->nor && ((tex->imaflag & TEX_NORMALMAP) == 0)) {
			/* color & normal */
			filterfunc(texres, ibuf, fx, fy, &AFD);
			val1 = texres->tr + texres->tg + texres->tb;
			filterfunc(&texr, ibuf, fx + dxt[0], fy + dxt[1], &AFD);
			val2 = texr.tr + texr.tg + texr.tb;
			filterfunc(&texr, ibuf, fx + dyt[0], fy + dyt[1], &AFD);
			val3 = texr.tr + texr.tg + texr.tb;
			/* don't switch x or y! */
			texres->nor[0] = val1 - val2;
			texres->nor[1] = val1 - val3;
		}
		else {
			filterfunc(texres, ibuf, fx, fy, &AFD);
			if (tex->texfilter != TXF_EWA) {
				alpha_clip_aniso(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, extflag, texres);
			}
		}
	}

	if (tex->imaflag & TEX_CALCALPHA)
		texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb);
	else
		texres->tin = texres->ta;
	if (tex->flag & TEX_NEGALPHA) texres->ta = 1.f - texres->ta;
	
	if ((R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields))
		ibuf->rect -= ibuf->x*ibuf->y;

	if (texres->nor && (tex->imaflag & TEX_NORMALMAP)) {	/* normal from color */
		/* The invert of the red channel is to make
		 * the normal map compliant with the outside world.
		 * It needs to be done because in Blender
		 * the normal used in the renderer points inward. It is generated
		 * this way in calc_vertexnormals(). Should this ever change
		 * this negate must be removed. */
		texres->nor[0] = -2.f*(texres->tr - 0.5f);
		texres->nor[1] = 2.f*(texres->tg - 0.5f);
		texres->nor[2] = 2.f*(texres->tb - 0.5f);
	}

	/* de-premul, this is being premulled in shade_input_do_shade()
	 * TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode, so for now commented out
	 * also disabled in imagewraposa() to be able to compare results with blender's default texture filtering */

	/* brecht: tried to fix this, see "TXF alpha" comments */

	/* do not de-premul for generated alpha, it is already in straight */
	if (texres->ta!=1.0f && texres->ta>1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
		fx = 1.f/texres->ta;
		texres->tr *= fx;
		texres->tg *= fx;
		texres->tb *= fx;
	}

	if (ima)
		BKE_image_pool_release_ibuf(ima, ibuf, pool);

	BRICONTRGB;
	
	return retval;
}
Beispiel #19
0
static int slide_plane_marker_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
  SpaceClip *sc = CTX_wm_space_clip(C);
  MovieClip *clip = ED_space_clip_get_clip(sc);
  SlidePlaneMarkerData *data = (SlidePlaneMarkerData *)op->customdata;
  float dx, dy, mdelta[2];
  int next_corner_index, prev_corner_index, diag_corner_index;
  const float *next_corner, *prev_corner, *diag_corner;
  float next_edge[2], prev_edge[2], next_diag_edge[2], prev_diag_edge[2];

  switch (event->type) {
    case LEFTCTRLKEY:
    case RIGHTCTRLKEY:
    case LEFTSHIFTKEY:
    case RIGHTSHIFTKEY:
      if (ELEM(event->type, LEFTSHIFTKEY, RIGHTSHIFTKEY)) {
        data->accurate = event->val == KM_PRESS;
      }
      ATTR_FALLTHROUGH;
    case MOUSEMOVE:
      mdelta[0] = event->mval[0] - data->previous_mval[0];
      mdelta[1] = event->mval[1] - data->previous_mval[1];

      dx = mdelta[0] / data->width / sc->zoom;
      dy = mdelta[1] / data->height / sc->zoom;

      if (data->accurate) {
        dx /= 5.0f;
        dy /= 5.0f;
      }

      data->corner[0] = data->previous_corner[0] + dx;
      data->corner[1] = data->previous_corner[1] + dy;

      /*
       *                              prev_edge
       *   (Corner 3, current) <-----------------------   (Corner 2, previous)
       *           |                                              ^
       *           |                                              |
       *           |                                              |
       *           |                                              |
       * next_edge |                                              | next_diag_edge
       *           |                                              |
       *           |                                              |
       *           |                                              |
       *           v                                              |
       *    (Corner 0, next)   ----------------------->   (Corner 1, diagonal)
       *                             prev_diag_edge
       */

      next_corner_index = (data->corner_index + 1) % 4;
      prev_corner_index = (data->corner_index + 3) % 4;
      diag_corner_index = (data->corner_index + 2) % 4;

      next_corner = data->plane_marker->corners[next_corner_index];
      prev_corner = data->plane_marker->corners[prev_corner_index];
      diag_corner = data->plane_marker->corners[diag_corner_index];

      sub_v2_v2v2(next_edge, next_corner, data->corner);
      sub_v2_v2v2(prev_edge, data->corner, prev_corner);
      sub_v2_v2v2(next_diag_edge, prev_corner, diag_corner);
      sub_v2_v2v2(prev_diag_edge, diag_corner, next_corner);

      if (cross_v2v2(prev_edge, next_edge) < 0.0f) {
        closest_to_line_v2(data->corner, data->corner, prev_corner, next_corner);
      }

      if (cross_v2v2(next_diag_edge, prev_edge) < 0.0f) {
        closest_to_line_v2(data->corner, data->corner, prev_corner, diag_corner);
      }

      if (cross_v2v2(next_edge, prev_diag_edge) < 0.0f) {
        closest_to_line_v2(data->corner, data->corner, next_corner, diag_corner);
      }

      data->previous_mval[0] = event->mval[0];
      data->previous_mval[1] = event->mval[1];
      copy_v2_v2(data->previous_corner, data->corner);

      DEG_id_tag_update(&sc->clip->id, 0);

      WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL);

      break;

    case LEFTMOUSE:
    case RIGHTMOUSE:
      if (event->type == data->event_type && event->val == KM_RELEASE) {
        /* Marker is now keyframed. */
        data->plane_marker->flag &= ~PLANE_MARKER_TRACKED;

        slide_plane_marker_update_homographies(sc, data);

        free_slide_plane_marker_data(op->customdata);

        clip_tracking_show_cursor(C);

        DEG_id_tag_update(&sc->clip->id, 0);
        WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);

        return OPERATOR_FINISHED;
      }

      break;

    case ESCKEY:
      cancel_mouse_slide_plane_marker(op->customdata);

      free_slide_plane_marker_data(op->customdata);

      clip_tracking_show_cursor(C);

      WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip);

      return OPERATOR_CANCELLED;
  }

  return OPERATOR_RUNNING_MODAL;
}
Beispiel #20
0
static void voronoi_removeParabola(VoronoiProcess *process, VoronoiEvent *event)
{
  VoronoiParabola *p1 = event->parabola;

  VoronoiParabola *xl = voronoiParabola_getLeftParent(p1);
  VoronoiParabola *xr = voronoiParabola_getRightParent(p1);

  VoronoiParabola *p0 = voronoiParabola_getLeftChild(xl);
  VoronoiParabola *p2 = voronoiParabola_getRightChild(xr);

  VoronoiParabola *higher = NULL, *par, *gparent;

  float p[2];

  if (p0->event) {
    BLI_freelinkN(&process->queue, p0->event);
    p0->event = NULL;
  }

  if (p2->event) {
    BLI_freelinkN(&process->queue, p2->event);
    p2->event = NULL;
  }

  p[0] = event->site[0];
  p[1] = voronoi_getY(process, p1->site, event->site[0]);

  copy_v2_v2(xl->edge->end, p);
  copy_v2_v2(xr->edge->end, p);

  par = p1;
  while (par != process->root) {
    par = par->parent;

    if (par == xl) {
      higher = xl;
    }
    if (par == xr) {
      higher = xr;
    }
  }

  higher->edge = voronoiEdge_new(p, p0->site, p2->site);
  BLI_addtail(&process->edges, higher->edge);

  gparent = p1->parent->parent;
  if (p1->parent->left == p1) {
    if (gparent->left == p1->parent) {
      voronoiParabola_setLeft(gparent, p1->parent->right);
    }
    if (gparent->right == p1->parent) {
      voronoiParabola_setRight(gparent, p1->parent->right);
    }
  }
  else {
    if (gparent->left == p1->parent) {
      voronoiParabola_setLeft(gparent, p1->parent->left);
    }
    if (gparent->right == p1->parent) {
      voronoiParabola_setRight(gparent, p1->parent->left);
    }
  }

  MEM_freeN(p1->parent);
  MEM_freeN(p1);

  voronoi_checkCircle(process, p0);
  voronoi_checkCircle(process, p2);
}
static void stencil_restore(StencilControlData *scd)
{
	copy_v2_v2(scd->dim_target, scd->init_sdim);
	copy_v2_v2(scd->pos_target, scd->init_spos);
	*scd->rot_target = scd->init_rot;
}
Beispiel #22
0
static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
                            int width, int height, float zoomx, float zoomy)
{
	float x, y;
	const int n = 10;
	int i, j, a;
	float pos[2], tpos[2], grid[11][11][2];
	MovieTracking *tracking = &clip->tracking;
	bGPdata *gpd = NULL;
	float aspy = 1.0f / tracking->camera.pixel_aspect;
	float dx = (float)width / n, dy = (float)height / n * aspy;
	float offsx = 0.0f, offsy = 0.0f;

	if (!tracking->camera.focal)
		return;

	if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0)
		return;

	UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);

	glPushMatrix();
	glTranslatef(x, y, 0);
	glScalef(zoomx, zoomy, 0);
	glMultMatrixf(sc->stabmat);
	glScalef(width, height, 0);

	/* grid */
	if (sc->flag & SC_SHOW_GRID) {
		float val[4][2], idx[4][2];
		float min[2], max[2];

		for (a = 0; a < 4; a++) {
			if (a < 2)
				val[a][a % 2] = FLT_MAX;
			else
				val[a][a % 2] = -FLT_MAX;
		}

		zero_v2(pos);
		for (i = 0; i <= n; i++) {
			for (j = 0; j <= n; j++) {
				if (i == 0 || j == 0 || i == n || j == n) {
					BKE_tracking_distort_v2(tracking, pos, tpos);

					for (a = 0; a < 4; a++) {
						int ok;

						if (a < 2)
							ok = tpos[a % 2] < val[a][a % 2];
						else
							ok = tpos[a % 2] > val[a][a % 2];

						if (ok) {
							copy_v2_v2(val[a], tpos);
							idx[a][0] = j;
							idx[a][1] = i;
						}
					}
				}

				pos[0] += dx;
			}

			pos[0] = 0.0f;
			pos[1] += dy;
		}

		INIT_MINMAX2(min, max);

		for (a = 0; a < 4; a++) {
			pos[0] = idx[a][0] * dx;
			pos[1] = idx[a][1] * dy;

			BKE_tracking_undistort_v2(tracking, pos, tpos);

			minmax_v2v2_v2(min, max, tpos);
		}

		copy_v2_v2(pos, min);
		dx = (max[0] - min[0]) / n;
		dy = (max[1] - min[1]) / n;

		for (i = 0; i <= n; i++) {
			for (j = 0; j <= n; j++) {
				BKE_tracking_distort_v2(tracking, pos, grid[i][j]);

				grid[i][j][0] /= width;
				grid[i][j][1] /= height * aspy;

				pos[0] += dx;
			}

			pos[0] = min[0];
			pos[1] += dy;
		}

		glColor3f(1.0f, 0.0f, 0.0f);

		for (i = 0; i <= n; i++) {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j <= n; j++) {
				glVertex2fv(grid[i][j]);
			}
			glEnd();
		}

		for (j = 0; j <= n; j++) {
			glBegin(GL_LINE_STRIP);
			for (i = 0; i <= n; i++) {
				glVertex2fv(grid[i][j]);
			}
			glEnd();
		}
	}

	if (sc->gpencil_src != SC_GPENCIL_SRC_TRACK) {
		gpd = clip->gpd;
	}

	if (sc->flag & SC_MANUAL_CALIBRATION && gpd) {
		bGPDlayer *layer = gpd->layers.first;

		while (layer) {
			bGPDframe *frame = layer->frames.first;

			if (layer->flag & GP_LAYER_HIDE) {
				layer = layer->next;
				continue;
			}

			glColor4fv(layer->color);
			glLineWidth(layer->thickness);
			glPointSize((float)(layer->thickness + 2));

			while (frame) {
				bGPDstroke *stroke = frame->strokes.first;

				while (stroke) {
					if (stroke->flag & GP_STROKE_2DSPACE) {
						if (stroke->totpoints > 1) {
							glBegin(GL_LINE_STRIP);
							for (i = 0; i < stroke->totpoints - 1; i++) {
								float npos[2], dpos[2], len;
								int steps;

								pos[0] = (stroke->points[i].x + offsx) * width;
								pos[1] = (stroke->points[i].y + offsy) * height * aspy;

								npos[0] = (stroke->points[i + 1].x + offsx) * width;
								npos[1] = (stroke->points[i + 1].y + offsy) * height * aspy;

								len = len_v2v2(pos, npos);
								steps = ceil(len / 5.0f);

								/* we want to distort only long straight lines */
								if (stroke->totpoints == 2) {
									BKE_tracking_undistort_v2(tracking, pos, pos);
									BKE_tracking_undistort_v2(tracking, npos, npos);
								}

								sub_v2_v2v2(dpos, npos, pos);
								mul_v2_fl(dpos, 1.0f / steps);

								for (j = 0; j <= steps; j++) {
									BKE_tracking_distort_v2(tracking, pos, tpos);
									glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));

									add_v2_v2(pos, dpos);
								}
							}
							glEnd();
						}
						else if (stroke->totpoints == 1) {
							glBegin(GL_POINTS);
							glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
							glEnd();
						}
					}

					stroke = stroke->next;
				}

				frame = frame->next;
			}

			layer = layer->next;
		}
	}

	glPopMatrix();
}
Beispiel #23
0
/* return non-zero if spline is selected */
static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
                               const char UNUSED(draw_flag), const char draw_type)
{
	const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
	unsigned char rgb_spline[4];
	MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
	SpaceClip *sc = CTX_wm_space_clip(C);
	int undistort = FALSE;

	int i, hsize, tot_feather_point;
	float (*feather_points)[2], (*fp)[2];

	if (!spline->tot_point)
		return;

	if (sc)
		undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;

	/* TODO, add this to sequence editor */
	hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */

	glPointSize(hsize);

	mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);

	/* feather points */
	feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
	for (i = 0; i < spline->tot_point; i++) {

		/* watch it! this is intentionally not the deform array, only check for sel */
		MaskSplinePoint *point = &spline->points[i];

		int j;

		for (j = 0; j <= point->tot_uw; j++) {
			float feather_point[2];
			int sel = FALSE;

			copy_v2_v2(feather_point, *fp);

			if (undistort)
				mask_point_undistort_pos(sc, feather_point, feather_point);

			if (j == 0) {
				sel = MASKPOINT_ISSEL_ANY(point);
			}
			else {
				sel = point->uw[j - 1].flag & SELECT;
			}

			if (sel) {
				if (point == masklay->act_point)
					glColor3f(1.0f, 1.0f, 1.0f);
				else
					glColor3f(1.0f, 1.0f, 0.0f);
			}
			else {
				glColor3f(0.5f, 0.5f, 0.0f);
			}

			glBegin(GL_POINTS);
			glVertex2fv(feather_point);
			glEnd();

			fp++;
		}
	}
	MEM_freeN(feather_points);

	/* control points */
	for (i = 0; i < spline->tot_point; i++) {

		/* watch it! this is intentionally not the deform array, only check for sel */
		MaskSplinePoint *point = &spline->points[i];
		MaskSplinePoint *point_deform = &points_array[i];
		BezTriple *bezt = &point_deform->bezt;

		float handle[2];
		float vert[2];
		const bool has_handle = BKE_mask_point_has_handle(point);

		copy_v2_v2(vert, bezt->vec[1]);
		BKE_mask_point_handle(point_deform, handle);

		if (undistort) {
			mask_point_undistort_pos(sc, vert, vert);
			mask_point_undistort_pos(sc, handle, handle);
		}

		/* draw handle segment */
		if (has_handle) {

			/* this could be split into its own loop */
			if (draw_type == MASK_DT_OUTLINE) {
				const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
				glLineWidth(3);
				glColor4ubv(rgb_gray);
				glBegin(GL_LINES);
				glVertex2fv(vert);
				glVertex2fv(handle);
				glEnd();
				glLineWidth(1);
			}

			glColor3ubv(rgb_spline);
			glBegin(GL_LINES);
			glVertex2fv(vert);
			glVertex2fv(handle);
			glEnd();
		}

		/* draw CV point */
		if (MASKPOINT_ISSEL_KNOT(point)) {
			if (point == masklay->act_point)
				glColor3f(1.0f, 1.0f, 1.0f);
			else
				glColor3f(1.0f, 1.0f, 0.0f);
		}
		else
			glColor3f(0.5f, 0.5f, 0.0f);

		glBegin(GL_POINTS);
		glVertex2fv(vert);
		glEnd();

		/* draw handle points */
		if (has_handle) {
			if (MASKPOINT_ISSEL_HANDLE(point)) {
				if (point == masklay->act_point)
					glColor3f(1.0f, 1.0f, 1.0f);
				else
					glColor3f(1.0f, 1.0f, 0.0f);
			}
			else {
				glColor3f(0.5f, 0.5f, 0.0f);
			}

			glBegin(GL_POINTS);
			glVertex2fv(handle);
			glEnd();
		}
	}

	glPointSize(1.0f);
}