Example #1
0
static qboolean
load_iqm_meshes (model_t *mod, const iqmheader *hdr, byte *buffer)
{
	iqm_t      *iqm = (iqm_t *) mod->aliashdr;
	iqmtriangle *tris;
	iqmmesh    *meshes;
	iqmjoint   *joints;
	uint32_t    i;

	if (!load_iqm_vertex_arrays (mod, hdr, buffer))
		return false;
	if (!(tris = get_triangles (hdr, buffer)))
		return false;
	iqm->num_elements = hdr->num_triangles * 3;
	iqm->elements = malloc (hdr->num_triangles * 3 * sizeof (uint16_t));
	for (i = 0; i < hdr->num_triangles; i++)
		VectorCopy (tris[i].vertex, iqm->elements + i * 3);
	if (!(meshes = get_meshes (hdr, buffer)))
		return false;
	iqm->num_meshes = hdr->num_meshes;
	iqm->meshes = malloc (hdr->num_meshes * sizeof (iqmmesh));
	memcpy (iqm->meshes, meshes, hdr->num_meshes * sizeof (iqmmesh));
	if (!(joints = get_joints (hdr, buffer)))
		return false;
	iqm->num_joints = hdr->num_joints;
	iqm->joints = malloc (iqm->num_joints * sizeof (iqmjoint));
	iqm->baseframe = malloc (iqm->num_joints * sizeof (mat4_t));
	iqm->inverse_baseframe = malloc (iqm->num_joints * sizeof (mat4_t));
	memcpy (iqm->joints, joints, iqm->num_joints * sizeof (iqmjoint));
	for (i = 0; i < hdr->num_joints; i++) {
		iqmjoint   *j = &iqm->joints[i];
		mat4_t     *bf = &iqm->baseframe[i];
		mat4_t     *ibf = &iqm->inverse_baseframe[i];
		quat_t      t;
		float       ilen;
		ilen = 1.0 / sqrt(QDotProduct (j->rotate, j->rotate));
		QuatScale (j->rotate, ilen, t);
		Mat4Init (t, j->scale, j->translate, *bf);
		Mat4Inverse (*bf, *ibf);
		if (j->parent >= 0) {
			Mat4Mult (iqm->baseframe[j->parent], *bf, *bf);
			Mat4Mult (*ibf, iqm->inverse_baseframe[j->parent], *ibf);
		}
	}
	return true;
}
Example #2
0
/*
	PR_ExecuteProgram

	The interpretation main loop
*/
VISIBLE void
PR_ExecuteProgram (progs_t * pr, func_t fnum)
{
	int         exitdepth, profile, startprofile;
	pr_uint_t   pointer;
	dstatement_t *st;
	edict_t    *ed;
	pr_type_t  *ptr;
	pr_type_t   old_val = {0}, *watch = 0;

	// make a stack frame
	exitdepth = pr->pr_depth;
	startprofile = profile = 0;

	Sys_PushSignalHook (signal_hook, pr);

	if (!PR_CallFunction (pr, fnum)) {
		// called a builtin instead of progs code
		Sys_PopSignalHook ();
		return;
	}
	st = pr->pr_statements + pr->pr_xstatement;

	if (pr->watch) {
		watch = pr->watch;
		old_val = *watch;
	}

	while (1) {
		pr_type_t  *op_a, *op_b, *op_c;

		st++;
		++pr->pr_xstatement;
		if (pr->pr_xstatement != st - pr->pr_statements)
			PR_RunError (pr, "internal error");
		if (++profile > 1000000 && !pr->no_exec_limit) {
			PR_RunError (pr, "runaway loop error");
		}

		op_a = pr->pr_globals + st->a;
		op_b = pr->pr_globals + st->b;
		op_c = pr->pr_globals + st->c;

		if (pr->pr_trace)
			PR_PrintStatement (pr, st, 1);

		switch (st->op) {
			case OP_ADD_F:
				OPC.float_var = OPA.float_var + OPB.float_var;
				break;
			case OP_ADD_V:
				VectorAdd (OPA.vector_var, OPB.vector_var, OPC.vector_var);
				break;
			case OP_ADD_Q:
				QuatAdd (OPA.quat_var, OPB.quat_var, OPC.quat_var);
				break;
			case OP_ADD_S:
				OPC.string_var = PR_CatStrings (pr,
												PR_GetString (pr,
															  OPA.string_var),
												PR_GetString (pr,
															  OPB.string_var));
				break;
			case OP_SUB_F:
				OPC.float_var = OPA.float_var - OPB.float_var;
				break;
			case OP_SUB_V:
				VectorSubtract (OPA.vector_var, OPB.vector_var, OPC.vector_var);
				break;
			case OP_SUB_Q:
				QuatSubtract (OPA.quat_var, OPB.quat_var, OPC.quat_var);
				break;
			case OP_MUL_F:
				OPC.float_var = OPA.float_var * OPB.float_var;
				break;
			case OP_MUL_V:
				OPC.float_var = DotProduct (OPA.vector_var, OPB.vector_var);
				break;
			case OP_MUL_FV:
				{
					// avoid issues with the likes of x = x.x * x;
					// makes for faster code, too
					float       scale = OPA.float_var;
					VectorScale (OPB.vector_var, scale, OPC.vector_var);
				}
				break;
			case OP_MUL_VF:
				{
					// avoid issues with the likes of x = x * x.x;
					// makes for faster code, too
					float       scale = OPB.float_var;
					VectorScale (OPA.vector_var, scale, OPC.vector_var);
				}
				break;
			case OP_MUL_Q:
				QuatMult (OPA.quat_var, OPB.quat_var, OPC.quat_var);
				break;
			case OP_MUL_QV:
				QuatMultVec (OPA.quat_var, OPB.vector_var, OPC.vector_var);
				break;
			case OP_MUL_FQ:
				{
					// avoid issues with the likes of x = x.s * x;
					// makes for faster code, too
					float       scale = OPA.float_var;
					QuatScale (OPB.quat_var, scale, OPC.quat_var);
				}
				break;
			case OP_MUL_QF:
				{
					// avoid issues with the likes of x = x * x.s;
					// makes for faster code, too
					float       scale = OPB.float_var;
					QuatScale (OPA.quat_var, scale, OPC.quat_var);
				}
				break;
			case OP_CONJ_Q:
				QuatConj (OPA.quat_var, OPC.quat_var);
				break;
			case OP_DIV_F:
				OPC.float_var = OPA.float_var / OPB.float_var;
				break;
			case OP_BITAND:
				OPC.float_var = (int) OPA.float_var & (int) OPB.float_var;
				break;
			case OP_BITOR:
				OPC.float_var = (int) OPA.float_var | (int) OPB.float_var;
				break;
			case OP_BITXOR_F:
				OPC.float_var = (int) OPA.float_var ^ (int) OPB.float_var;
				break;
			case OP_BITNOT_F:
				OPC.float_var = ~ (int) OPA.float_var;
				break;
			case OP_SHL_F:
				OPC.float_var = (int) OPA.float_var << (int) OPB.float_var;
				break;
			case OP_SHR_F:
				OPC.float_var = (int) OPA.float_var >> (int) OPB.float_var;
				break;
			case OP_SHL_I:
				OPC.integer_var = OPA.integer_var << OPB.integer_var;
				break;
			case OP_SHR_I:
				OPC.integer_var = OPA.integer_var >> OPB.integer_var;
				break;
			case OP_SHR_U:
				OPC.uinteger_var = OPA.uinteger_var >> OPB.integer_var;
				break;
			case OP_GE_F:
				OPC.float_var = OPA.float_var >= OPB.float_var;
				break;
			case OP_LE_F:
				OPC.float_var = OPA.float_var <= OPB.float_var;
				break;
			case OP_GT_F:
				OPC.float_var = OPA.float_var > OPB.float_var;
				break;
			case OP_LT_F:
				OPC.float_var = OPA.float_var < OPB.float_var;
				break;
			case OP_AND:	// OPA and OPB have to be float for -0.0
				OPC.integer_var = FNZ (OPA) && FNZ (OPB);
				break;
			case OP_OR:		// OPA and OPB have to be float for -0.0
				OPC.integer_var = FNZ (OPA) || FNZ (OPB);
				break;
			case OP_NOT_F:
				OPC.integer_var = !FNZ (OPA);
				break;
			case OP_NOT_V:
				OPC.integer_var = VectorIsZero (OPA.vector_var);
				break;
			case OP_NOT_Q:
				OPC.integer_var = QuatIsZero (OPA.quat_var);
				break;
			case OP_NOT_S:
				OPC.integer_var = !OPA.string_var ||
					!*PR_GetString (pr, OPA.string_var);
				break;
			case OP_NOT_FN:
				OPC.integer_var = !OPA.func_var;
				break;
			case OP_NOT_ENT:
				OPC.integer_var = !OPA.entity_var;
				break;
			case OP_EQ_F:
				OPC.integer_var = OPA.float_var == OPB.float_var;
				break;
			case OP_EQ_V:
				OPC.integer_var = VectorCompare (OPA.vector_var,
												 OPB.vector_var);
				break;
			case OP_EQ_Q:
				OPC.integer_var = QuatCompare (OPA.quat_var, OPB.quat_var);
				break;
			case OP_EQ_E:
				OPC.integer_var = OPA.integer_var == OPB.integer_var;
				break;
			case OP_EQ_FN:
				OPC.integer_var = OPA.func_var == OPB.func_var;
				break;
			case OP_NE_F:
				OPC.integer_var = OPA.float_var != OPB.float_var;
				break;
			case OP_NE_V:
				OPC.integer_var = !VectorCompare (OPA.vector_var,
												  OPB.vector_var);
				break;
			case OP_NE_Q:
				OPC.integer_var = !QuatCompare (OPA.quat_var, OPB.quat_var);
				break;
			case OP_LE_S:
			case OP_GE_S:
			case OP_LT_S:
			case OP_GT_S:
			case OP_NE_S:
			case OP_EQ_S:
				{
					int cmp = strcmp (PR_GetString (pr, OPA.string_var),
									  PR_GetString (pr, OPB.string_var));
					switch (st->op) {
						case OP_LE_S: cmp = (cmp <= 0); break;
						case OP_GE_S: cmp = (cmp >= 0); break;
						case OP_LT_S: cmp = (cmp < 0); break;
						case OP_GT_S: cmp = (cmp > 0); break;
						case OP_NE_S: break;
						case OP_EQ_S: cmp = !cmp; break;
						default:      break;
					}
					OPC.integer_var = cmp;
				}
				break;
			case OP_NE_E:
				OPC.integer_var = OPA.integer_var != OPB.integer_var;
				break;
			case OP_NE_FN:
				OPC.integer_var = OPA.func_var != OPB.func_var;
				break;

			// ==================
			case OP_STORE_F:
			case OP_STORE_ENT:
			case OP_STORE_FLD:			// integers
			case OP_STORE_S:
			case OP_STORE_FN:			// pointers
			case OP_STORE_I:
			case OP_STORE_P:
				OPB.integer_var = OPA.integer_var;
				break;
			case OP_STORE_V:
				VectorCopy (OPA.vector_var, OPB.vector_var);
				break;
			case OP_STORE_Q:
				QuatCopy (OPA.quat_var, OPB.quat_var);
				break;

			case OP_STOREP_F:
			case OP_STOREP_ENT:
			case OP_STOREP_FLD:		// integers
			case OP_STOREP_S:
			case OP_STOREP_FN:		// pointers
			case OP_STOREP_I:
			case OP_STOREP_P:
				pointer = OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				ptr->integer_var = OPA.integer_var;
				break;
			case OP_STOREP_V:
				pointer = OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_vector);
				}
				ptr = pr->pr_globals + pointer;
				VectorCopy (OPA.vector_var, ptr->vector_var);
				break;
			case OP_STOREP_Q:
				pointer = OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_quat);
				}
				ptr = pr->pr_globals + pointer;
				QuatCopy (OPA.quat_var, ptr->quat_var);
				break;

			case OP_ADDRESS:
				if (pr_boundscheck->int_val) {
					if (OPA.entity_var < 0
						|| OPA.entity_var >= pr->pr_edictareasize)
						PR_RunError (pr, "Progs attempted to address an out "
									 "of bounds edict");
					if (OPA.entity_var == 0 && pr->null_bad)
						PR_RunError (pr, "assignment to world entity");
					if (OPB.uinteger_var >= pr->progs->entityfields)
						PR_RunError (pr, "Progs attempted to address an "
									 "invalid field in an edict");
				}
				ed = PROG_TO_EDICT (pr, OPA.entity_var);
				OPC.integer_var = &ed->v[OPB.integer_var] - pr->pr_globals;
				break;
			case OP_ADDRESS_VOID:
			case OP_ADDRESS_F:
			case OP_ADDRESS_V:
			case OP_ADDRESS_Q:
			case OP_ADDRESS_S:
			case OP_ADDRESS_ENT:
			case OP_ADDRESS_FLD:
			case OP_ADDRESS_FN:
			case OP_ADDRESS_I:
			case OP_ADDRESS_P:
				OPC.integer_var = st->a;
				break;

			case OP_LOAD_F:
			case OP_LOAD_FLD:
			case OP_LOAD_ENT:
			case OP_LOAD_S:
			case OP_LOAD_FN:
			case OP_LOAD_I:
			case OP_LOAD_P:
				if (pr_boundscheck->int_val) {
					if (OPA.entity_var < 0
						|| OPA.entity_var >= pr->pr_edictareasize)
						PR_RunError (pr, "Progs attempted to read an out of "
									 "bounds edict number");
					if (OPB.uinteger_var >= pr->progs->entityfields)
						PR_RunError (pr, "Progs attempted to read an invalid "
									 "field in an edict");
				}
				ed = PROG_TO_EDICT (pr, OPA.entity_var);
				OPC.integer_var = ed->v[OPB.integer_var].integer_var;
				break;
			case OP_LOAD_V:
				if (pr_boundscheck->int_val) {
					if (OPA.entity_var < 0
						|| OPA.entity_var >= pr->pr_edictareasize)
						PR_RunError (pr, "Progs attempted to read an out of "
									 "bounds edict number");
					if (OPB.uinteger_var + 2 >= pr->progs->entityfields)
						PR_RunError (pr, "Progs attempted to read an invalid "
									 "field in an edict");
				}
				ed = PROG_TO_EDICT (pr, OPA.entity_var);
				memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC));
				break;
			case OP_LOAD_Q:
				if (pr_boundscheck->int_val) {
					if (OPA.entity_var < 0
						|| OPA.entity_var >= pr->pr_edictareasize)
						PR_RunError (pr, "Progs attempted to read an out of "
									 "bounds edict number");
					if (OPB.uinteger_var + 3 >= pr->progs->entityfields)
						PR_RunError (pr, "Progs attempted to read an invalid "
									 "field in an edict");
				}
				ed = PROG_TO_EDICT (pr, OPA.entity_var);
				memcpy (&OPC, &ed->v[OPB.integer_var], 3 * sizeof (OPC));
				break;

			case OP_LOADB_F:
			case OP_LOADB_S:
			case OP_LOADB_ENT:
			case OP_LOADB_FLD:
			case OP_LOADB_FN:
			case OP_LOADB_I:
			case OP_LOADB_P:
				pointer = OPA.integer_var + OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				OPC.integer_var = ptr->integer_var;
				break;
			case OP_LOADB_V:
				pointer = OPA.integer_var + OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_vector);
				}
				ptr = pr->pr_globals + pointer;
				VectorCopy (ptr->vector_var, OPC.vector_var);
				break;
			case OP_LOADB_Q:
				pointer = OPA.integer_var + OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_quat);
				}
				ptr = pr->pr_globals + pointer;
				QuatCopy (ptr->quat_var, OPC.quat_var);
				break;

			case OP_LOADBI_F:
			case OP_LOADBI_S:
			case OP_LOADBI_ENT:
			case OP_LOADBI_FLD:
			case OP_LOADBI_FN:
			case OP_LOADBI_I:
			case OP_LOADBI_P:
				pointer = OPA.integer_var + (short) st->b;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				OPC.integer_var = ptr->integer_var;
				break;
			case OP_LOADBI_V:
				pointer = OPA.integer_var + (short) st->b;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_vector);
				}
				ptr = pr->pr_globals + pointer;
				VectorCopy (ptr->vector_var, OPC.vector_var);
				break;
			case OP_LOADBI_Q:
				pointer = OPA.integer_var + (short) st->b;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_quat);
				}
				ptr = pr->pr_globals + pointer;
				QuatCopy (ptr->quat_var, OPC.quat_var);
				break;

			case OP_LEA:
				pointer = OPA.integer_var + OPB.integer_var;
				OPC.integer_var = pointer;
				break;

			case OP_LEAI:
				pointer = OPA.integer_var + (short) st->b;
				OPC.integer_var = pointer;
				break;

			case OP_STOREB_F:
			case OP_STOREB_S:
			case OP_STOREB_ENT:
			case OP_STOREB_FLD:
			case OP_STOREB_FN:
			case OP_STOREB_I:
			case OP_STOREB_P:
				pointer = OPB.integer_var + OPC.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				ptr->integer_var = OPA.integer_var;
				break;
			case OP_STOREB_V:
				pointer = OPB.integer_var + OPC.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_vector);
				}
				ptr = pr->pr_globals + pointer;
				VectorCopy (OPA.vector_var, ptr->vector_var);
				break;
			case OP_STOREB_Q:
				pointer = OPB.integer_var + OPC.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_quat);
				}
				ptr = pr->pr_globals + pointer;
				QuatCopy (OPA.quat_var, ptr->quat_var);
				break;

			case OP_STOREBI_F:
			case OP_STOREBI_S:
			case OP_STOREBI_ENT:
			case OP_STOREBI_FLD:
			case OP_STOREBI_FN:
			case OP_STOREBI_I:
			case OP_STOREBI_P:
				pointer = OPB.integer_var + (short) st->c;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				ptr->integer_var = OPA.integer_var;
				break;
			case OP_STOREBI_V:
				pointer = OPB.integer_var + (short) st->c;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_vector);
				}
				ptr = pr->pr_globals + pointer;
				VectorCopy (OPA.vector_var, ptr->vector_var);
				break;
			case OP_STOREBI_Q:
				pointer = OPB.integer_var + (short) st->c;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_quat);
				}
				ptr = pr->pr_globals + pointer;
				QuatCopy (OPA.quat_var, ptr->quat_var);
				break;

			// ==================
			case OP_IFNOT:
				if (!OPA.integer_var) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_IF:
				if (OPA.integer_var) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_IFBE:
				if (OPA.integer_var <= 0) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_IFB:
				if (OPA.integer_var < 0) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_IFAE:
				if (OPA.integer_var >= 0) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_IFA:
				if (OPA.integer_var > 0) {
					pr->pr_xstatement += (short)st->b - 1;	// offset the st++
					st = pr->pr_statements + pr->pr_xstatement;
				}
				break;
			case OP_GOTO:
				pr->pr_xstatement += (short)st->a - 1;		// offset the st++
				st = pr->pr_statements + pr->pr_xstatement;
				break;
			case OP_JUMP:
				if (pr_boundscheck->int_val
					&& (OPA.uinteger_var >= pr->progs->numstatements)) {
					PR_RunError (pr, "Invalid jump destination");
				}
				pr->pr_xstatement = OPA.uinteger_var - 1;	// offset the st++
				st = pr->pr_statements + pr->pr_xstatement;
				break;
			case OP_JUMPB:
				pointer = st->a + OPB.integer_var;
				if (pr_boundscheck->int_val) {
					PR_BoundsCheck (pr, pointer, ev_integer);
				}
				ptr = pr->pr_globals + pointer;
				pointer = ptr->integer_var;
				if (pr_boundscheck->int_val
					&& (pointer >= pr->progs->numstatements)) {
					PR_RunError (pr, "Invalid jump destination");
				}
				pr->pr_xstatement = pointer - 1;			// offset the st++
				st = pr->pr_statements + pr->pr_xstatement;
				break;

			case OP_RCALL2:
			case OP_RCALL3:
			case OP_RCALL4:
			case OP_RCALL5:
			case OP_RCALL6:
			case OP_RCALL7:
			case OP_RCALL8:
				pr->pr_params[1] = &OPC;
				goto op_rcall;
			case OP_RCALL1:
				pr->pr_params[1] = pr->pr_real_params[1];
op_rcall:
				pr->pr_params[0] = &OPB;
				pr->pr_argc = st->op - OP_RCALL1 + 1;
				goto op_call;
			case OP_CALL0:
			case OP_CALL1:
			case OP_CALL2:
			case OP_CALL3:
			case OP_CALL4:
			case OP_CALL5:
			case OP_CALL6:
			case OP_CALL7:
			case OP_CALL8:
				PR_RESET_PARAMS (pr);
				pr->pr_argc = st->op - OP_CALL0;
op_call:
				pr->pr_xfunction->profile += profile - startprofile;
				startprofile = profile;
				PR_CallFunction (pr, OPA.func_var);
				st = pr->pr_statements + pr->pr_xstatement;
				break;
			case OP_DONE:
			case OP_RETURN:
				if (!st->a)
					memset (&R_INT (pr), 0,
							pr->pr_param_size * sizeof (OPA));
				else if (&R_INT (pr) != &OPA.integer_var)
					memcpy (&R_INT (pr), &OPA,
							pr->pr_param_size * sizeof (OPA));
				// fallthrough
			case OP_RETURN_V:
				pr->pr_xfunction->profile += profile - startprofile;
				startprofile = profile;
				PR_LeaveFunction (pr);
				st = pr->pr_statements + pr->pr_xstatement;
				if (pr->pr_depth == exitdepth) {
					if (pr->pr_trace && pr->pr_depth <= pr->pr_trace_depth)
						pr->pr_trace = false;
					Sys_PopSignalHook ();
					return;					// all done
				}
				break;
			case OP_STATE:
				ed = PROG_TO_EDICT (pr, *pr->globals.self);
				ed->v[pr->fields.nextthink].float_var = *pr->globals.time +
					0.1;
				ed->v[pr->fields.frame].float_var = OPA.float_var;
				ed->v[pr->fields.think].func_var = OPB.func_var;
				break;
			case OP_STATE_F:
				ed = PROG_TO_EDICT (pr, *pr->globals.self);
				ed->v[pr->fields.nextthink].float_var = *pr->globals.time +
					OPC.float_var;
				ed->v[pr->fields.frame].float_var = OPA.float_var;
				ed->v[pr->fields.think].func_var = OPB.func_var;
				break;
			case OP_ADD_I:
				OPC.integer_var = OPA.integer_var + OPB.integer_var;
				break;
			case OP_SUB_I:
				OPC.integer_var = OPA.integer_var - OPB.integer_var;
				break;
			case OP_MUL_I:
				OPC.integer_var = OPA.integer_var * OPB.integer_var;
				break;
/*
			case OP_DIV_VF:
				{
					float       temp = 1.0f / OPB.float_var;
					VectorScale (OPA.vector_var, temp, OPC.vector_var);
				}
				break;
*/
			case OP_DIV_I:
				OPC.integer_var = OPA.integer_var / OPB.integer_var;
				break;
			case OP_MOD_I:
				OPC.integer_var = OPA.integer_var % OPB.integer_var;
				break;
			case OP_MOD_F:
				OPC.float_var = (int) OPA.float_var % (int) OPB.float_var;
				break;
			case OP_CONV_IF:
				OPC.float_var = OPA.integer_var;
				break;
			case OP_CONV_FI:
				OPC.integer_var = OPA.float_var;
				break;
			case OP_BITAND_I:
				OPC.integer_var = OPA.integer_var & OPB.integer_var;
				break;
			case OP_BITOR_I:
				OPC.integer_var = OPA.integer_var | OPB.integer_var;
				break;
			case OP_BITXOR_I:
				OPC.integer_var = OPA.integer_var ^ OPB.integer_var;
				break;
			case OP_BITNOT_I:
				OPC.integer_var = ~OPA.integer_var;
				break;

			case OP_GE_I:
			case OP_GE_P:
				OPC.integer_var = OPA.integer_var >= OPB.integer_var;
				break;
			case OP_GE_U:
				OPC.integer_var = OPA.uinteger_var >= OPB.uinteger_var;
				break;
			case OP_LE_I:
			case OP_LE_P:
				OPC.integer_var = OPA.integer_var <= OPB.integer_var;
				break;
			case OP_LE_U:
				OPC.integer_var = OPA.uinteger_var <= OPB.uinteger_var;
				break;
			case OP_GT_I:
			case OP_GT_P:
				OPC.integer_var = OPA.integer_var > OPB.integer_var;
				break;
			case OP_GT_U:
				OPC.integer_var = OPA.uinteger_var > OPB.uinteger_var;
				break;
			case OP_LT_I:
			case OP_LT_P:
				OPC.integer_var = OPA.integer_var < OPB.integer_var;
				break;
			case OP_LT_U:
				OPC.integer_var = OPA.uinteger_var < OPB.uinteger_var;
				break;

			case OP_AND_I:
				OPC.integer_var = OPA.integer_var && OPB.integer_var;
				break;
			case OP_OR_I:
				OPC.integer_var = OPA.integer_var || OPB.integer_var;
				break;
			case OP_NOT_I:
			case OP_NOT_P:
				OPC.integer_var = !OPA.integer_var;
				break;
			case OP_EQ_I:
			case OP_EQ_P:
				OPC.integer_var = OPA.integer_var == OPB.integer_var;
				break;
			case OP_NE_I:
			case OP_NE_P:
				OPC.integer_var = OPA.integer_var != OPB.integer_var;
				break;

			case OP_MOVEI:
				memmove (&OPC, &OPA, st->b * 4);
				break;
			case OP_MOVEP:
				if (pr_boundscheck->int_val) {
					PR_BoundsCheckSize (pr, OPC.integer_var, OPB.uinteger_var);
					PR_BoundsCheckSize (pr, OPA.integer_var, OPB.uinteger_var);
				}
				memmove (pr->pr_globals + OPC.integer_var,
						 pr->pr_globals + OPA.integer_var,
						 OPB.uinteger_var * 4);
				break;
			case OP_MOVEPI:
				if (pr_boundscheck->int_val) {
					PR_BoundsCheckSize (pr, OPC.integer_var, st->b);
					PR_BoundsCheckSize (pr, OPA.integer_var, st->b);
				}
				memmove (pr->pr_globals + OPC.integer_var,
						 pr->pr_globals + OPA.integer_var,
						 st->b * 4);
				break;

// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized
/*
			case OP_BOUNDCHECK:
				if (OPA.integer_var < 0 || OPA.integer_var >= st->b) {
					PR_RunError (pr, "Progs boundcheck failed at line number "
					"%d, value is < 0 or >= %d", st->b, st->c);
				}
				break;

*/
			default:
				PR_RunError (pr, "Bad opcode %i", st->op);
		}
		if (watch && watch->integer_var != old_val.integer_var
			&& (!pr->wp_conditional
				|| watch->integer_var == pr->wp_val.integer_var))
			PR_RunError (pr, "watchpoint hit: %d -> %d", old_val.integer_var,
						 watch->integer_var);
	}
}
Example #3
0
float *AttitudeUpdate(float dt,float _beta, float _zeta, float a_x,float a_y, float a_z,float w_x, float w_y, float w_z,float m_x, float m_y, float m_z)
{

	float qConj[4];
	float unbiasedGyro[4];
	float qDot[4];
	float beta,zeta;
	float F[6];
	float J[6*4];
	float step[4];
	float North,East,Down;
	float b2,b4;

    
    float q1 = q[0]; float q2 = q[1]; float q3 = q[2]; float q4 = q[3];
    float _error[4];
    
    float accel[] = {0,-a_x,-a_y,-a_z};
    float mag[] = {0,m_x,m_y,m_z};
    

    
    // Direction cosine matrix from quaternion
    float qdcm13 = 2.0f*(q2*q4 - q1*q3);
    float qdcm23 = 2.0f*(q3*q4 + q1*q2);
    float qdcm33 = 2.0f*(0.5f - q2*q2 - q3*q3);
    
    float qdcm12 = 2.0f*(q2*q3 + q1*q4);
    float qdcm22 = 2.0f*(0.5f - q2*q2 - q4*q4);
    float qdcm32 = 2.0f*(q3*q4 - q1*q2);
    
    float qdcm11 = 2.0f*(0.5f - q3*q3 - q4*q4);
    float qdcm21 = 2.0f*(q2*q3 - q1*q4);
    float qdcm31 = 2.0f*(q2*q4 + q1*q3);
    
    counter += dt;
       QuatNormalize(accel);
       QuatNormalize(mag);
    // Earth's field
    North = qdcm11*mag[1] + qdcm21*mag[2] + qdcm31*mag[3];
    East =  qdcm12*mag[1] + qdcm22*mag[2] + qdcm32*mag[3];
    Down =  qdcm13*mag[1] + qdcm23*mag[2] + qdcm33*mag[3];

    b2 = sqrtf(North*North + East*East);
    b4 = Down;
    
    
    
    // 6 x 1
    F[0] =        qdcm13 - accel[1];
    F[1] =        qdcm23 - accel[2];
    F[2] =        qdcm33 - accel[3];
    F[3] =        b2*qdcm11 + b4*qdcm13 - mag[1];
    F[4] =        b2*qdcm21 + b4*qdcm23 - mag[2];
    F[5] =        b2*qdcm31 + b4*qdcm33 - mag[3];

    // 6 x 4

    J[0] = -2*q3; 			J[1] =  2*q4; 			J[2] = -2*q1; 			J[3] =  2*q2;
    J[4] =  2*q2;        	J[5] =	2*q1;        	J[6] =	2*q4;        	J[7] =	2*q3;
    J[8] =     0;       	J[9] =	-4*q2;       	J[10]=	-4*q3;          J[11] = 0;
    J[12]=-2*b4*q3;         J[13]=  2*b4*q4;        J[14]=-4*b2*q3-2*b4*q1; J[15]= -4*b2*q4+2*b4*q2;
    J[16]=-2*b2*q4+2*b4*q2; J[17]=  2*b2*q3+2*b4*q1;J[18]= 2*b2*q2+2*b4*q4; J[19]=-2*b2*q1+2*b4*q3;
    J[20]=2*b2*q3;          J[21]=  2*b2*q4-4*b4*q2;J[22]= 2*b2*q1-4*b4*q3; J[23] =2*b2*q2;

    
    //float Jt[4*6];
    //vDSP_mtrans(J,1,Jt,1,4,6);
    
    // step = J'*F
    //       4 x 6 * 6 x 1
    //vDSP_mmul( Jt,1,F,1,step,1,4,1,6);
    step[0] = J[0]*F[0] + J[4]*F[1] + J[8]*F[2] + J[12]*F[3] + J[16]*F[4] + J[20]*F[5];
    step[1] = J[1]*F[0] + J[5]*F[1] + J[9]*F[2] + J[13]*F[3] + J[17]*F[4] + J[21]*F[5];
    step[2] = J[2]*F[0] + J[6]*F[1] + J[10]*F[2] + J[14]*F[3] + J[18]*F[4] + J[22]*F[5];
    step[3] = J[3]*F[0] + J[7]*F[1] + J[11]*F[2] + J[15]*F[3] + J[19]*F[4] + J[23]*F[5];
    
    // normalize step 
    QuatNormalize(step);
    
    qConj[0] = q[0]; qConj[1] = -q[1]; qConj[2]=-q[2]; qConj[3]=-q[3];
    // Error
    QuatMultiply(qConj,step,_error);
    QuatScale(_error,(2.0f*dt));

    // update gyro biases
    w_bx += zeta*_error[1]; w_by += zeta*_error[2]; w_bz += zeta*_error[3];

    // quaternion dynamics
    unbiasedGyro[0] = 0; unbiasedGyro[1] = (w_x-w_bx); unbiasedGyro[2]= (w_y-w_by); unbiasedGyro[3] = (w_z-w_bz);
    QuatMultiply(q,unbiasedGyro,qDot);
    
    
    // higher gain during startup
    if(counter < 5.0f)
    {
        beta = 1.0f;
        zeta = 1.0f;
    }
    else
    {
        beta = _beta;
        zeta = _zeta;
    }
    
    qDot[0] = 0.5f*qDot[0] - beta*step[0];
    qDot[1] = 0.5f*qDot[1] - beta*step[1];
    qDot[2] = 0.5f*qDot[2] - beta*step[2];
    qDot[3] = 0.5f*qDot[3] - beta*step[3];
    
    q[0] += qDot[0]*dt;
    q[1] += qDot[1]*dt;
    q[2] += qDot[2]*dt;
    q[3] += qDot[3]*dt;

    QuatNormalize(q);
return q;



}
Example #4
0
static qboolean
load_iqm_anims (model_t *mod, const iqmheader *hdr, byte *buffer)
{
	iqm_t      *iqm = (iqm_t *) mod->aliashdr;
	iqmanim    *anims;
	iqmpose    *poses;
	uint16_t   *framedata;
	uint32_t    i, j;

	if (hdr->num_poses != hdr->num_joints)
		return false;

	iqm->num_anims = hdr->num_anims;
	iqm->anims = malloc (hdr->num_anims * sizeof (iqmanim));
	anims = (iqmanim *) (buffer + hdr->ofs_anims);
	for (i = 0; i < hdr->num_anims; i++) {
		iqm->anims[i].name = LittleLong (anims[i].name);
		iqm->anims[i].first_frame = LittleLong (anims[i].first_frame);
		iqm->anims[i].num_frames = LittleLong (anims[i].num_frames);
		iqm->anims[i].framerate = LittleFloat (anims[i].framerate);
		iqm->anims[i].flags = LittleLong (anims[i].flags);
	}

	poses = (iqmpose *) (buffer + hdr->ofs_poses);
	for (i = 0; i < hdr->num_poses; i++) {
		poses[i].parent = LittleLong (poses[i].parent);
		poses[i].mask = LittleLong (poses[i].mask);
		for (j = 0; j < 10; j++) {
			poses[i].channeloffset[j] = LittleFloat(poses[i].channeloffset[j]);
			poses[i].channelscale[j] = LittleFloat (poses[i].channelscale[j]);
		}
	}

	framedata = (uint16_t *) (buffer + hdr->ofs_frames);
	for (i = 0; i < hdr->num_frames * hdr->num_framechannels; i++)
		framedata[i] = LittleShort (framedata[i]);

	iqm->num_frames = hdr->num_frames;
	iqm->frames = malloc (hdr->num_frames * sizeof (iqmframe_t *));
	iqm->frames[0] = malloc (hdr->num_frames * hdr->num_poses
							 * sizeof (iqmframe_t));

	for (i = 0; i < hdr->num_frames; i++) {
		iqm->frames[i] = iqm->frames[0] + i * hdr->num_poses;
		for (j = 0; j < hdr->num_poses; j++) {
			iqmframe_t *frame = &iqm->frames[i][j];
			iqmpose    *p = &poses[j];
			quat_t      rotation;
			vec3_t      scale, translation;
			mat4_t      mat;
			float       ilen;

			translation[0] = p->channeloffset[0];
			if (p->mask & 0x001)
				translation[0] += *framedata++ * p->channelscale[0];
			translation[1] = p->channeloffset[1];
			if (p->mask & 0x002)
				translation[1] += *framedata++ * p->channelscale[1];
			translation[2] = p->channeloffset[2];
			if (p->mask & 0x004)
				translation[2] += *framedata++ * p->channelscale[2];

			// QF's quaternions are wxyz while IQM's quaternions are xyzw
			rotation[1] = p->channeloffset[3];
			if (p->mask & 0x008)
				rotation[1] += *framedata++ * p->channelscale[3];
			rotation[2] = p->channeloffset[4];
			if (p->mask & 0x010)
				rotation[2] += *framedata++ * p->channelscale[4];
			rotation[3] = p->channeloffset[5];
			if (p->mask & 0x020)
				rotation[3] += *framedata++ * p->channelscale[5];
			rotation[0] = p->channeloffset[6];
			if (p->mask & 0x040)
				rotation[0] += *framedata++ * p->channelscale[6];

			scale[0] = p->channeloffset[7];
			if (p->mask & 0x080)
				scale[0] += *framedata++ * p->channelscale[7];
			scale[1] = p->channeloffset[8];
			if (p->mask & 0x100)
				scale[1] += *framedata++ * p->channelscale[8];
			scale[2] = p->channeloffset[9];
			if (p->mask & 0x200)
				scale[2] += *framedata++ * p->channelscale[9];

			ilen = 1.0 / sqrt(QDotProduct (rotation, rotation));
			QuatScale (rotation, ilen, rotation);
			Mat4Init (rotation, scale, translation, mat);
			if (p->parent >= 0)
				Mat4Mult (iqm->baseframe[p->parent], mat, mat);
#if 0
			Mat4Mult (mat, iqm->inverse_baseframe[j], mat);
			// convert the matrix to dual quaternion + shear + scale
			Mat4Decompose (mat, frame->rt.q0.q, frame->shear, frame->scale,
						   frame->rt.qe.sv.v);
			frame->rt.qe.sv.s = 0;
			// apply the inverse of scale and shear to translation so
			// everything works out properly in the shader.
			// Normally v' = T*Sc*Sh*R*v, but with the dual quaternion, we get
			// v' = Sc*Sh*T'*R*v
			VectorCompDiv (frame->rt.qe.sv.v, frame->scale, frame->rt.qe.sv.v);
			VectorUnshear (frame->shear, frame->rt.qe.sv.v, frame->rt.qe.sv.v);
			// Dual quaternions need 1/2 translation.
			VectorScale (frame->rt.qe.sv.v, 0.5, frame->rt.qe.sv.v);
			// and tranlation * rotation
			QuatMult (frame->rt.qe.q, frame->rt.q0.q, frame->rt.qe.q);
#else
			Mat4Mult (mat, iqm->inverse_baseframe[j], (float *)frame);
#endif
		}
	}
	return true;
}