コード例 #1
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
// [7/8/2012] Renamed to Brush_ClipLineToFace ~hogsy
BOOL Brush_ClipLineToFace(vec3_t p1,vec3_t p2,face_t *f)
{
	float	d1,d2,fr,*v;
	int		i;

	d1 = Math_DotProduct(p1,f->plane.normal)-f->plane.dist;
	d2 = Math_DotProduct(p2, f->plane.normal)-f->plane.dist;

	if (d1 >= 0 && d2 >= 0)
		return FALSE;		// totally outside
	else if(d1 <= 0 && d2 <= 0)
		return TRUE;		// totally inside

	fr = d1 / (d1 - d2);

	if (d1 > 0)
		v = p1;
	else
		v = p2;

	for (i=0 ; i<3 ; i++)
		v[i] = p1[i] + fr*(p2[i] - p1[i]);

	return TRUE;
}
コード例 #2
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
void _EmitTextureCoordinates(vec3_t v,qtexture_t *q)
{
	float	s, t;

	s = Math_DotProduct(v,vecs[0]);
	t = Math_DotProduct(v,vecs[1]);

	s += shift[0];
	t += shift[1];

	s /= q->width;
	t /= q->height;

	glTexCoord2f(s,t);
}
コード例 #3
0
ファイル: select.c プロジェクト: Acidburn0zzz/KatanaEngine
void Select_AplyMatrix (void)
{
	brush_t	*b;
	face_t	*f;
	int		i, j;
	vec3_t	temp;

	for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
	{
		for (f=b->brush_faces ; f ; f=f->next)
		{
			for (i=0 ; i<3 ; i++)
			{
				Math_VectorSubtract(f->planepts[i],select_origin, temp);
				for (j=0 ; j<3 ; j++)
					f->planepts[i][j] = Math_DotProduct(temp,select_matrix[j])
						+ select_origin[j];
			}

			if (select_fliporder)
			{
				Math_VectorCopy(f->planepts[0],temp);
				Math_VectorCopy(f->planepts[2],f->planepts[0]);
				Math_VectorCopy(temp,f->planepts[2]);
			}
		}
		Brush_Build( b );
	}
	Sys_UpdateWindows (W_ALL);
}
コード例 #4
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
/*	Itersects a ray with a brush
	Returns the face hit and the distance along the ray the intersection occured at
	Returns NULL and 0 if not hit at all
*/
face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
{
	face_t	*f, *firstface=NULL;
	vec3_t	p1, p2;
	float	frac, d1, d2;
	int		i;

	Math_VectorCopy(origin,p1);
	for (i=0 ; i<3 ; i++)
		p2[i] = p1[i] + dir[i]*16384;

	for (f=b->brush_faces ; f ; f=f->next)
	{
		d1 = Math_DotProduct(p1,f->plane.normal)-f->plane.dist;
		d2 = Math_DotProduct(p2,f->plane.normal)-f->plane.dist;
		if (d1 >= 0 && d2 >= 0)
		{
			*dist = 0;
			return NULL;	// ray is on front side of face
		}
		if (d1 <=0 && d2 <= 0)
			continue;
	// clip the ray to the plane
		frac = d1 / (d1 - d2);
		if (d1 > 0)
		{
			firstface = f;
			for (i=0 ; i<3 ; i++)
				p1[i] = p1[i] + frac *(p2[i] - p1[i]);
		}
		else
		{
			for (i=0 ; i<3 ; i++)
				p2[i] = p1[i] + frac *(p2[i] - p1[i]);
		}
	}

	// find distance p1 is along dir
	Math_VectorSubtract(p1,origin,p1);
	d1 = Math_DotProduct(p1,dir);

	*dist = d1;

	return firstface;
}
コード例 #5
0
void Physics_WallFriction(ServerEntity_t *eEntity, trace_t *trLine)
{
	MathVector3f_t forward, right, up;
	float d, i;
	MathVector3f_t into, side;

	Math_AngleVectors(eEntity->v.v_angle, forward, right, up);
	d = Math_DotProduct(trLine->plane.normal, forward);

	d += 0.5;
	if (d >= 0)
		return;

	// Cut the tangential velocity.
	i = Math_DotProduct(trLine->plane.normal, eEntity->v.velocity);
	Math_VectorScale(trLine->plane.normal, i, into);
	Math_VectorSubtract(eEntity->v.velocity, into, side);

	eEntity->v.velocity[0] = side[0] * (1 + d);
	eEntity->v.velocity[1] = side[1] * (1 + d);
}
コード例 #6
0
void SV_WallFriction (edict_t *ent, trace_t *trace)
{
	vec3_t		forward, right, up;
	float		d, i;
	vec3_t		into, side;

	Math_AngleVectors(ent->v.v_angle, forward, right, up);
	d = Math_DotProduct (trace->plane.normal, forward);

	d += 0.5;
	if (d >= 0)
		return;

	// Cut the tangential velocity
	i = Math_DotProduct (trace->plane.normal, ent->v.velocity);
	Math_VectorScale (trace->plane.normal, i, into);
	Math_VectorSubtract (ent->v.velocity, into, side);

	ent->v.velocity[0] = side[0] * (1 + d);
	ent->v.velocity[1] = side[1] * (1 + d);
}
コード例 #7
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
/*	Returns the visible polygon on a face
*/
winding_t *MakeFaceWinding(brush_t *b,face_t *face)
{
	winding_t	*w;
	face_t		*clip;
	plane_t		plane;
	BOOL		past;

	// get a poly that covers an effectively infinite area
	w = BasePolyForPlane (&face->plane);

	// chop the poly by all of the other faces
	past = FALSE;
	for (clip = b->brush_faces ; clip && w ; clip=clip->next)
	{
		if (clip == face)
		{
			past = TRUE;
			continue;
		}
		if(Math_DotProduct (face->plane.normal, clip->plane.normal) > 0.999
			&& fabs(face->plane.dist - clip->plane.dist) < 0.01 )
		{	// identical plane, use the later one
			if (past)
			{
				free (w);
				return NULL;
			}
			continue;
		}

		// flip the plane, because we want to keep the back side
		Math_VectorSubtract(vec3_origin,clip->plane.normal,plane.normal);
		plane.dist = -clip->plane.dist;

		w = ClipWinding(w,&plane,FALSE);
		if (!w)
			return w;
	}

	if (w->numpoints < 3)
	{
		free(w);
		w = NULL;
	}

	if (!w)
		printf ("unused plane\n");

	return w;
}
コード例 #8
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
void EmitTextureCoordinates(float *xyzst,qtexture_t *q,face_t *f)
{
	float		s,t,ns,nt,ang,sinv,cosv;
	vec3_t		vecs[2];
	texdef_t	*td;

	// get natural texture axis
	TextureAxisFromPlane(&f->plane, vecs[0], vecs[1]);

	td = &f->texdef;

	ang		= td->rotate/180.0f*pMath_PI;
	sinv	= sin(ang);
	cosv	= cos(ang);

	if (!td->scale[0])
		td->scale[0] = 1.0f;
	if (!td->scale[1])
		td->scale[1] = 1.0f;

	s = Math_DotProduct(xyzst,vecs[0]);
	t = Math_DotProduct(xyzst,vecs[1]);

	ns = cosv * s - sinv * t;
	nt = sinv * s +  cosv * t;

	s = ns/td->scale[0] + td->shift[0];
	t = nt/td->scale[1] + td->shift[1];

	// gl scales everything from 0 to 1
	s /= q->width;
	t /= q->height;

	xyzst[3] = s;
	xyzst[4] = t;
}
コード例 #9
0
void R_SetFrustum (float fovx, float fovy)
{
	int		i;

	if (r_stereo.value)
		fovx += 10; //silly hack so that polygons don't drop out becuase of stereo skew

	TurnVector(frustum[0].normal, vpn, vright, fovx/2 - 90); //left plane
	TurnVector(frustum[1].normal, vpn, vright, 90 - fovx/2); //right plane
	TurnVector(frustum[2].normal, vpn, vup, 90 - fovy/2); //bottom plane
	TurnVector(frustum[3].normal, vpn, vup, fovy/2 - 90); //top plane

	for (i=0 ; i<4 ; i++)
	{
		frustum[i].type = PLANE_ANYZ;
		frustum[i].dist = Math_DotProduct(r_origin, frustum[i].normal); //FIXME: shouldn't this always be zero?
		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
	}
}
コード例 #10
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
void TextureAxisFromPlane(plane_t *pln,vec3_t xv,vec3_t yv)
{
	int		bestaxis,i;
	float	dot,best;

	best = 0;
	bestaxis = 0;

	for(i = 0; i < 6; i++)
	{
		dot = Math_DotProduct(pln->normal,baseaxis[i*3]);
		if (dot > best)
		{
			best = dot;
			bestaxis = i;
		}
	}

	Math_VectorCopy(baseaxis[bestaxis*3+1],xv);
	Math_VectorCopy(baseaxis[bestaxis*3+2],yv);
}
コード例 #11
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
void Brush_MakeFacePlanes (brush_t *b)
{
	face_t	*f;
	int		j;
	vec3_t	t1, t2, t3;

	for (f=b->brush_faces ; f ; f=f->next)
	{
		// convert to a vector / dist plane
		for (j=0 ; j<3 ; j++)
		{
			t1[j] = f->planepts[0][j] - f->planepts[1][j];
			t2[j] = f->planepts[2][j] - f->planepts[1][j];
			t3[j] = f->planepts[1][j];
		}

		Math_CrossProduct(t1,t2,f->plane.normal);
		if(Math_VectorCompare(f->plane.normal,vec3_origin))
			printf("WARNING: brush plane with no normal!\n");
		Math_VectorNormalize(f->plane.normal);
		f->plane.dist = Math_DotProduct(t3,f->plane.normal);
	}
}
コード例 #12
0
int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
{
	float	backoff;
	float	change;
	int		i, blocked;

	blocked = 0;
	if (normal[2] > 0)
		blocked |= 1;		// floor
	if (!normal[2])
		blocked |= 2;		// step

	backoff = Math_DotProduct (in, normal) * overbounce;

	for (i=0 ; i<3 ; i++)
	{
		change = normal[i]*backoff;
		out[i] = in[i] - change;
		if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
			out[i] = 0;
	}

	return blocked;
}
コード例 #13
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
winding_t *BasePolyForPlane (plane_t *p)
{
	int			i, x;
	vec_t		max, v;
	vec3_t		org, vright, vup;
	winding_t	*w;

	// find the major axis
	max = -BOGUS_RANGE;
	x = -1;
	for (i=0 ; i<3; i++)
	{
		v = fabs(p->normal[i]);
		if (v > max)
		{
			x = i;
			max = v;
		}
	}

	if (x==-1)
		Error("BasePolyForPlane: no axis found");

	Math_VectorCopy(vec3_origin,vup);
	switch (x)
	{
	case 0:
	case 1:
		vup[2] = 1;
		break;
	case 2:
		vup[0] = 1;
		break;
	}


	v = Math_DotProduct(vup,p->normal);
	Math_VectorMA(vup,-v,p->normal,vup);
	Math_VectorNormalize(vup);

	Math_VectorScale(p->normal,p->dist,org);

	Math_CrossProduct(vup,p->normal,vright);

	Math_VectorScale(vup,8192,vup);
	Math_VectorScale(vright,8192,vright);

// project a really big	axis aligned box onto the plane
	w = NewWinding (4);

	Math_VectorSubtract(org,vright,w->points[0]);
	Math_VectorAdd(w->points[0],vup,w->points[0]);

	Math_VectorAdd(org,vright,w->points[1]);
	Math_VectorAdd(w->points[1],vup,w->points[1]);

	Math_VectorAdd(org,vright,w->points[2]);
	Math_VectorSubtract(w->points[2],vup,w->points[2]);

	Math_VectorSubtract(org,vright,w->points[3]);
	Math_VectorSubtract(w->points[3],vup,w->points[3]);

	w->numpoints = 4;

	return w;
}
コード例 #14
0
void Sky_ClipPoly (int nump, MathVector3f_t vecs, int stage)
{
	bool			bFront	= false,
					bBack	= false;
	float			*norm,*v,
					d,e,dists[MAX_CLIP_VERTS];
	int				sides[MAX_CLIP_VERTS],
					newc[2],
					i,j;
	MathVector3f_t	vNew[2][MAX_CLIP_VERTS];

	if(nump > MAX_CLIP_VERTS-2)
		Sys_Error ("Sky_ClipPoly: MAX_CLIP_VERTS");
	else if(stage == 6) // fully clipped
	{
		Sky_ProjectPoly (nump, vecs);
		return;
	}

	norm = vSkyClip[stage];
	for (i=0, v = vecs ; i<nump ; i++, v+=3)
	{
		d = Math_DotProduct (v, norm);
		if (d > pMath_EPSILON_ON)
		{
			bFront = true;

			sides[i] = SIDE_FRONT;
		}
		else if (d < pMath_EPSILON_ON)
		{
			bBack = true;

			sides[i] = SIDE_BACK;
		}
		else
			sides[i] = SIDE_ON;
		dists[i] = d;
	}

	if(!bFront || !bBack)
	{
		// not clipped
		Sky_ClipPoly (nump, vecs, stage+1);
		return;
	}

	// clip it
	sides[i] = sides[0];
	dists[i] = dists[0];
	Math_VectorCopy (vecs, (vecs+(i*3)) );
	newc[0] = newc[1] = 0;

	for (i=0, v = vecs ; i<nump ; i++, v+=3)
	{
		switch (sides[i])
		{
		case SIDE_FRONT:
			Math_VectorCopy(v,vNew[0][newc[0]]);
			newc[0]++;
			break;
		case SIDE_BACK:
			Math_VectorCopy(v,vNew[1][newc[1]]);
			newc[1]++;
			break;
		case SIDE_ON:
			Math_VectorCopy(v,vNew[0][newc[0]]);
			newc[0]++;
			Math_VectorCopy(v,vNew[1][newc[1]]);
			newc[1]++;
			break;
		}

		if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

		d = dists[i]/(dists[i]-dists[i+1]);
		for (j=0 ; j<3 ; j++)
		{
			e = v[j] + d*(v[j+3] - v[j]);
			vNew[0][newc[0]][j] = e;
			vNew[1][newc[1]][j] = e;
		}
		newc[0]++;
		newc[1]++;
	}

	// Continue
	Sky_ClipPoly(newc[0],vNew[0][0],stage+1);
	Sky_ClipPoly(newc[1],vNew[1][0],stage+1);
}
コード例 #15
0
// [18/5/2013] TODO: Merge with SV_PushMove ~hogsy
static void Server_PushRotate(edict_t *pusher,float movetime)
{
	int		i,e,num_moved,slaves_moved;
	edict_t	*check,*block,*moved_edict[MAX_EDICTS],*ground,*slave,*master;
	vec3_t	move,a,amove,entorig,pushorig,moved_from[MAX_EDICTS],org,org2,forward,right,up;
	bool	bMoveIt;

	for (i = 0; i < 3; i++)
		amove[i] = pusher->v.avelocity[i] * movetime;

	Math_VectorNegate(amove,a);
	Math_AngleVectors(a,forward,right,up);

	Math_VectorCopy(pusher->v.angles,pushorig);

	// move the pusher to it's final position
	Math_VectorAdd(pusher->v.angles,amove,pusher->v.angles);

	pusher->v.ltime += movetime;
	SV_LinkEdict (pusher, false);

	slaves_moved = 0;
	master = pusher;
	while(master->v.aiment)
	{
		slave = PROG_TO_EDICT(master->v.aiment);

		slaves_moved++;
		Math_VectorCopy (slave->v.angles, moved_from[MAX_EDICTS - slaves_moved]);
		moved_edict[MAX_EDICTS - slaves_moved] = slave;

		if (slave->v.movedir[PITCH])
			slave->v.angles[PITCH] = master->v.angles[PITCH];
		else
			slave->v.angles[PITCH] += slave->v.avelocity[PITCH] * movetime;

		if (slave->v.movedir[YAW])
			slave->v.angles[YAW] = master->v.angles[YAW];
		else
			slave->v.angles[YAW] += slave->v.avelocity[YAW] * movetime;

		if (slave->v.movedir[ROLL])
			slave->v.angles[ROLL] = master->v.angles[ROLL];
		else
			slave->v.angles[ROLL] += slave->v.avelocity[ROLL] * movetime;

		slave->v.ltime = master->v.ltime;
		SV_LinkEdict(slave,false);

		master = slave;
	}

	// see if any solid entities are inside the final position
	num_moved = 0;
	check = NEXT_EDICT(sv.edicts);
	for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check))
	{
		if (check->free)
			continue;
		if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP)
			continue;

		// if the entity is standing on the pusher, it will definitely be moved
		bMoveIt = false;
		ground = check->v.groundentity;
		if(check->v.flags & FL_ONGROUND)
		{
			if (ground == pusher)
				bMoveIt = true;
			else
			{
				for (i = 0; i < slaves_moved; i++)
				{
					if (ground == moved_edict[MAX_EDICTS - i - 1])
					{
						bMoveIt = true;
						break;
					}
				}
			}
		}

		if(!bMoveIt)
		{
			if(	check->v.absmin[0] >= pusher->v.absmax[0]
			||	check->v.absmin[1] >= pusher->v.absmax[1]
			||	check->v.absmin[2] >= pusher->v.absmax[2]
			||	check->v.absmax[0] <= pusher->v.absmin[0]
			||	check->v.absmax[1] <= pusher->v.absmin[1]
			||	check->v.absmax[2] <= pusher->v.absmin[2])
			{
				for (i = 0; i < slaves_moved; i++)
				{
					slave = moved_edict[MAX_EDICTS-i-1];
					if( check->v.absmin[0] >= slave->v.absmax[0]
					||	check->v.absmin[1] >= slave->v.absmax[1]
					||	check->v.absmin[2] >= slave->v.absmax[2]
					||	check->v.absmax[0] <= slave->v.absmin[0]
					||	check->v.absmax[1] <= slave->v.absmin[1]
					||	check->v.absmax[2] <= slave->v.absmin[2] )
						continue;
				}
				if (i == slaves_moved)
					continue;
			}

			// See if the ent's bbox is inside the pusher's final position
			if(!SV_TestEntityPosition(check))
				continue;
		}

		// remove the onground flag for non-players
		if(check->v.movetype != MOVETYPE_WALK)
			check->v.flags = check->v.flags & ~FL_ONGROUND;

		Math_VectorCopy(check->v.origin,entorig);
		Math_VectorCopy(check->v.origin,moved_from[num_moved]);
		moved_edict[num_moved] = check;
		num_moved++;

		// calculate destination position
		Math_VectorSubtract(check->v.origin,pusher->v.origin,org);
		org2[0] = Math_DotProduct(org,forward);
		org2[1] = -Math_DotProduct(org,right);
		org2[2] = Math_DotProduct(org,up);
		Math_VectorSubtract (org2,org,move);

		// try moving the contacted entity
		pusher->Physics.iSolid = SOLID_NOT;
		SV_PushEntity (check, move);
	//@@TODO: do we ever want to do anybody's angles?  maybe just yaw???
		if(check->monster.iType != 1)
		{
#if 0
			vec3_t	vYaw;
			
			vYaw[YAW] = Math_AngleMod(pusher->v.angles[YAW]+check->v.angles[YAW]);

			Con_Printf("%i %i\n",(int)check->v.angles[YAW],(int)vYaw[YAW]);
			//check->v.angles[YAW] = vYaw[YAW];
			//check->v.angles[YAW] = Math_AngleMod(vYaw[YAW]);
#endif
			// move back any entities we already moved
			for (i = 0; i < num_moved; i++)
			{
				Math_VectorAdd(moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
				moved_edict[i]->v.angles[YAW] += amove[YAW]/2.0f;

				SV_LinkEdict(moved_edict[i],false);
			}
		}

		pusher->Physics.iSolid = SOLID_BSP;

		// If it is still inside the pusher, block
		block = SV_TestEntityPosition (check);
		if (block)
		{
			// fail the move
			if (check->v.mins[0] == check->v.maxs[0])
				continue;
			if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER)
			{
				// corpse
				check->v.mins[0] = check->v.mins[1] = 0;
				Math_VectorCopy(check->v.mins,check->v.maxs);
				continue;
			}

			Math_VectorCopy(entorig,check->v.origin);
			SV_LinkEdict(check,true);

			Math_VectorCopy(pushorig,pusher->v.angles);
			SV_LinkEdict(pusher,false);
			pusher->v.ltime -= movetime;

			for(i = 0; i < slaves_moved; i++)
			{
				slave = moved_edict[MAX_EDICTS - i - 1];
				Math_VectorCopy(moved_from[MAX_EDICTS - i - 1], slave->v.angles);
				SV_LinkEdict(slave,false);
				slave->v.ltime -= movetime;
			}

			// if the pusher has a "blocked" function, call it
			// otherwise, just stay in place until the obstacle is gone
			if (pusher->v.blocked)
				pusher->v.blocked(pusher,check);

			// move back any entities we already moved
			for (i = 0; i < num_moved; i++)
			{
				Math_VectorCopy (moved_from[i], moved_edict[i]->v.origin);
			//@@TODO:: see above
			//	if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER)))
				Math_VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
				moved_edict[i]->v.angles[YAW] -= amove[YAW];

				SV_LinkEdict(moved_edict[i],false);
			}
			return;
		}
	}
}
コード例 #16
0
int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
{
	int			bumpcount, numbumps;
	vec3_t		dir;
	float		d;
	int			numplanes;
	vec3_t		planes[MAX_CLIP_PLANES];
	vec3_t		primal_velocity, original_velocity, new_velocity;
	int			i, j;
	trace_t		trace;
	vec3_t		end;
	float		time_left;
	int			blocked;

	numbumps = 4;

	blocked = 0;
	Math_VectorCopy (ent->v.velocity, original_velocity);
	Math_VectorCopy (ent->v.velocity, primal_velocity);
	numplanes = 0;

	time_left = time;

	for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
	{
		if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
			break;

		for (i=0 ; i<3 ; i++)
			end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];

		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, FALSE, ent);
		if(trace.bAllSolid)
		{
			// Entity is trapped in another solid
			Math_VectorCopy(mv3Origin, ent->v.velocity);
			return 3;
		}

		if (trace.fraction > 0)
		{
			// Actually covered some distance
			Math_VectorCopy (trace.endpos, ent->v.origin);
			Math_VectorCopy (ent->v.velocity, original_velocity);
			numplanes = 0;
		}

		if (trace.fraction == 1)
			 break;		// moved the entire distance

		if(!trace.ent)
		{
			Sys_Error ("SV_FlyMove: !trace.ent");
			return 0;
		}

		if (trace.plane.normal[2] > 0.7)
		{
			blocked |= 1;		// floor
			if (trace.ent->Physics.iSolid == SOLID_BSP)
			{
				ent->v.flags		|= FL_ONGROUND;
				ent->v.groundentity = trace.ent;
			}
		}

		if (!trace.plane.normal[2])
		{
			blocked |= 2;		// step
			if (steptrace)
				*steptrace = trace;	// save for player extrafriction
		}

		// Run the impact function
		Physics_Impact(ent,trace.ent);
		if (ent->free)
			break;		// removed by the impact function

		time_left -= time_left * trace.fraction;

		// Cliped to another plane
		if(numplanes >= MAX_CLIP_PLANES)
		{
			// This shouldn't really happen
			Math_VectorCopy(mv3Origin, ent->v.velocity);
			return 3;
		}

		Math_VectorCopy (trace.plane.normal, planes[numplanes]);
		numplanes++;

		// Modify original_velocity so it parallels all of the clip planes
		for(i = 0; i < numplanes; i++)
		{
			ClipVelocity (original_velocity, planes[i], new_velocity, 1);
			for (j=0 ; j<numplanes ; j++)
				if (j != i)
				{
					if(Math_DotProduct(new_velocity,planes[j]) < 0)
						break;	// not ok
				}
			if (j == numplanes)
				break;
		}

		if (i != numplanes)
			Math_VectorCopy (new_velocity, ent->v.velocity);
		else
		{
			// Go along the crease
			if (numplanes != 2)
			{
				Math_VectorCopy(mv3Origin, ent->v.velocity);
				return 7;
			}

			Math_CrossProduct(planes[0], planes[1], dir);
			d = Math_DotProduct(dir, ent->v.velocity);
			Math_VectorScale(dir, d, ent->v.velocity);
		}

		// if original velocity is against the original velocity, stop dead
		// to avoid tiny occilations in sloping corners
		if(Math_DotProduct(ent->v.velocity,primal_velocity) <= 0)
		{
			Math_VectorCopy(mv3Origin,ent->v.velocity);
			return blocked;
		}
	}

	return blocked;
}
コード例 #17
0
void SubdividePolygon (int numverts, float *verts)
{
	int		i, j, k;
	vec3_t	mins, maxs;
	float	m;
	float	*v;
	vec3_t	front[64], back[64];
	int		f, b;
	float	dist[64];
	float	frac;
	glpoly_t	*poly;
	float	s, t;

	if(numverts > 60)
		Sys_Error ("numverts = %i", numverts);

	BoundPoly (numverts, verts, mins, maxs);

	for(i = 0; i < 3; i++)
	{
		m = (mins[i] + maxs[i]) * 0.5;
		m = gl_subdivide_size.value * floor (m/gl_subdivide_size.value + 0.5);
		if (maxs[i] - m < 8)
			continue;
		if (m - mins[i] < 8)
			continue;

		// cut it
		v = verts + i;
		for (j=0 ; j<numverts ; j++, v+= 3)
			dist[j] = *v - m;

		// wrap cases
		dist[j] = dist[0];
		v-=i;
		Math_VectorCopy (verts, v);

		f = b = 0;
		v = verts;
		for (j=0 ; j<numverts ; j++, v+= 3)
		{
			if (dist[j] >= 0)
			{
				Math_VectorCopy (v, front[f]);
				f++;
			}
			if (dist[j] <= 0)
			{
				Math_VectorCopy (v, back[b]);
				b++;
			}
			if (dist[j] == 0 || dist[j+1] == 0)
				continue;
			if ( (dist[j] > 0) != (dist[j+1] > 0) )
			{
				// clip point
				frac = dist[j] / (dist[j] - dist[j+1]);
				for (k=0 ; k<3 ; k++)
					front[f][k] = back[b][k] = v[k] + frac*(v[3+k] - v[k]);
				f++;
				b++;
			}
		}

		SubdividePolygon (f, front[0]);
		SubdividePolygon (b, back[0]);
		return;
	}

	poly = (glpoly_t*)Hunk_Alloc (sizeof(glpoly_t) + (numverts-4) * VERTEXSIZE*sizeof(float));
	poly->next = warpface->polys->next;
	warpface->polys->next = poly;
	poly->numverts = numverts;
	for (i=0 ; i<numverts ; i++, verts+= 3)
	{
		Math_VectorCopy (verts, poly->verts[i]);
		s = Math_DotProduct (verts, warpface->texinfo->vecs[0]);
		t = Math_DotProduct (verts, warpface->texinfo->vecs[1]);
		poly->verts[i][3] = s;
		poly->verts[i][4] = t;
	}
}
コード例 #18
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
/*	Clips the winding to the plane, returning the new winding on the positive side
	Frees the input winding.
	If keepon is TRUE, an exactly on-plane winding will be saved, otherwise
	it will be clipped away.
*/
winding_t *ClipWinding (winding_t *in, plane_t *split, bool keepon)
{
	vec_t		dists[MAX_POINTS_ON_WINDING];
	int			sides[MAX_POINTS_ON_WINDING];
	int			counts[3];
	vec_t		dot;
	int			i, j;
	vec_t		*p1, *p2;
	vec3_t		mid;
	winding_t	*neww;
	int			maxpts;

	counts[0] = counts[1] = counts[2] = 0;

// determine sides for each point
	for (i=0 ; i<in->numpoints ; i++)
	{
		dot = Math_DotProduct(in->points[i],split->normal);
		dot -= split->dist;
		dists[i] = dot;
		if (dot > ON_EPSILON)
			sides[i] = SIDE_FRONT;
		else if (dot < -ON_EPSILON)
			sides[i] = SIDE_BACK;
		else
			sides[i] = SIDE_ON;

		counts[sides[i]]++;
	}
	sides[i] = sides[0];
	dists[i] = dists[0];

	if (keepon && !counts[0] && !counts[1])
		return in;

	if (!counts[0])
	{
		FreeWinding (in);
		return NULL;
	}
	if (!counts[1])
		return in;

	maxpts = in->numpoints+4;	// can't use counts[0]+2 because
								// of fp grouping errors
	neww = NewWinding (maxpts);

	for (i=0 ; i<in->numpoints ; i++)
	{
		p1 = in->points[i];

		if (sides[i] == SIDE_ON)
		{
			Math_VectorCopy(p1,neww->points[neww->numpoints]);
			neww->numpoints++;
			continue;
		}

		if (sides[i] == SIDE_FRONT)
		{
			Math_VectorCopy(p1,neww->points[neww->numpoints]);
			neww->numpoints++;
		}

		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
			continue;

	// generate a split point
		p2 = in->points[(i+1)%in->numpoints];

		dot = dists[i] / (dists[i]-dists[i+1]);
		for (j=0 ; j<3 ; j++)
		{	// avoid round off error when possible
			if (split->normal[j] == 1)
				mid[j] = split->dist;
			else if (split->normal[j] == -1)
				mid[j] = -split->dist;
			else
				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
		}

		Math_VectorCopy(mid,neww->points[neww->numpoints]);
		neww->numpoints++;
	}

	if (neww->numpoints > maxpts)
		Error ("ClipWinding: points exceeded estimate");

// free the original winding
	FreeWinding (in);

	return neww;
}
コード例 #19
0
ファイル: brush.c プロジェクト: Acidburn0zzz/KatanaEngine
/*	Adds the faces planepts to move_points, and
	rotates and adds the planepts of adjacent face if shear is set
*/
void Brush_SelectFaceForDragging (brush_t *b, face_t *f, bool shear)
{
	int			i;
	face_t		*f2;
	winding_t	*w;
	float		d;
	brush_t		*b2;
	int			c;

	if(b->owner->eclass->fixedsize)
		return;

	c = 0;
	for (i=0 ; i<3 ; i++)
		c += AddPlanept (f->planepts[i]);
	if (c == 0)
		return;		// allready completely added

	// select all points on this plane in all brushes the selection
	for(b2 = selected_brushes.next; b2 != &selected_brushes; b2 = b2->next)
	{
		if (b2 == b)
			continue;
		for (f2=b2->brush_faces ; f2 ; f2=f2->next)
		{
			for (i=0 ; i<3 ; i++)
				if(fabs(Math_DotProduct(f2->planepts[i],f->plane.normal)
				-f->plane.dist) > ON_EPSILON)
					break;

			if(i == 3)
			{
				// move this face as well
				Brush_SelectFaceForDragging(b2, f2, shear);
				break;
			}
		}
	}

	// if shearing, take all the planes adjacent to
	// selected faces and rotate their points so the
	// edge clipped by a selcted face has two of the points
	if(!shear)
		return;

	for (f2=b->brush_faces ; f2 ; f2=f2->next)
	{
		if (f2 == f)
			continue;
		w = MakeFaceWinding (b, f2);
		if (!w)
			continue;

		// any points on f will become new control points
		for (i=0 ; i<w->numpoints ; i++)
		{
			d = Math_DotProduct(w->points[i],f->plane.normal)-f->plane.dist;
			if (d > -ON_EPSILON && d < ON_EPSILON)
				break;
		}

		//
		// if none of the points were on the plane,
		// leave it alone
		//
		if (i != w->numpoints)
		{
			if (i == 0)
			{
				// see if the first clockwise point was the
				// last point on the winding
				d = Math_DotProduct(w->points[w->numpoints-1],f->plane.normal)-f->plane.dist;
				if (d > -ON_EPSILON && d < ON_EPSILON)
					i = w->numpoints - 1;
			}

			AddPlanept (f2->planepts[0]);

			Math_VectorCopy(w->points[i],f2->planepts[0]);
			if (++i == w->numpoints)
				i = 0;

			// see if the next point is also on the plane
			d = Math_DotProduct(w->points[i]
				, f->plane.normal) - f->plane.dist;
			if (d > -ON_EPSILON && d < ON_EPSILON)
				AddPlanept (f2->planepts[1]);

			Math_VectorCopy(w->points[i],f2->planepts[1]);
			if (++i == w->numpoints)
				i = 0;

			// the third point is never on the plane
			Math_VectorCopy(w->points[i],f2->planepts[2]);
		}

		free(w);
	}
}
コード例 #20
0
void Sky_ProcessEntities(void)
{
	int				i,k,mark;
	unsigned int	j;
	float			dot;
	bool			bRotated;
	ClientEntity_t	*e;
	msurface_t		*s;
	glpoly_t		*p;
	MathVector3f_t	vTemp, forward, right, up;

	if (!r_drawentities.value)
		return;

	for (i=0 ; i<cl_numvisedicts ; i++)
	{
		e = cl_visedicts[i];

		if (e->model->type != MODEL_TYPE_LEVEL)
			continue;

		if(R_CullModelForEntity(e))
			continue;

		if(e->alpha == ENTALPHA_ZERO)
			continue;

		Math_VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
		if(e->angles[0] || e->angles[1] || e->angles[2])
		{
			bRotated = true;

			Math_AngleVectors(e->angles, forward, right, up);
			Math_VectorCopy(modelorg,vTemp);

			modelorg[0] = Math_DotProduct(vTemp,forward);
			modelorg[1] = -Math_DotProduct(vTemp,right);
			modelorg[2] = Math_DotProduct(vTemp,up);
		}
		else
			bRotated = false;

		s = &e->model->surfaces[e->model->firstmodelsurface];

		for (j=0 ; j<e->model->nummodelsurfaces ; j++, s++)
		{
			if (s->flags & SURF_DRAWSKY)
			{
				dot = Math_DotProduct (modelorg, s->plane->normal) - s->plane->dist;
				if (((s->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
					(!(s->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
				{
					//copy the polygon and translate manually, since Sky_ProcessPoly needs it to be in world space
					mark = Hunk_LowMark();
					p = (glpoly_t*)Hunk_Alloc (sizeof(*s->polys)); //FIXME: don't allocate for each poly
					p->numverts = s->polys->numverts;
					for (k=0; k<p->numverts; k++)
					{
						if(bRotated)
						{
							p->verts[k][0] = e->origin[0] + s->polys->verts[k][0] * forward[0]
														  - s->polys->verts[k][1] * right[0]
														  + s->polys->verts[k][2] * up[0];
							p->verts[k][1] = e->origin[1] + s->polys->verts[k][0] * forward[1]
														  - s->polys->verts[k][1] * right[1]
														  + s->polys->verts[k][2] * up[1];
							p->verts[k][2] = e->origin[2] + s->polys->verts[k][0] * forward[2]
														  - s->polys->verts[k][1] * right[2]
														  + s->polys->verts[k][2] * up[2];
						}
						else
							Math_VectorAdd(s->polys->verts[k], e->origin, p->verts[k]);
					}
					Sky_ProcessPoly (p);
					Hunk_FreeToLowMark (mark);
				}
			}
		}
	}
}