示例#1
0
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {
	matrix_4x4 mp;
	m4x4_zeros(&mp);

	int mode = ctr_state.matrix_current;
	int depth = ctr_state.matrix_depth[mode];
	matrix_4x4 *mat = &ctr_state.matrix[mode][depth];
	if (!mat) {
		return;
	}

	// Build standard orthogonal projection matrix
	mp.r[0].x = 2.0f / (right - left);
	mp.r[0].w = (left + right) / (left - right);
	mp.r[1].y = 2.0f / (top - bottom);
	mp.r[1].w = (bottom + top) / (bottom - top);
	mp.r[2].z = 2.0f / (zNear - zFar);
	mp.r[2].w = (zFar + zNear) / (zFar - zNear);
	mp.r[3].w = 1.0f;

	// Fix depth range to [-1, 0]
	matrix_4x4 mp2, mp3;
	m4x4_identity(&mp2);
	mp2.r[2].z = 0.5;
	mp2.r[2].w = -0.5;
	m4x4_multiply(&mp3, &mp2, &mp);

	// Fix the 3DS screens' orientation by swapping the X and Y axis
	m4x4_identity(&mp2);
	mp2.r[0].x = 0.0;
	mp2.r[0].y = 1.0;
	mp2.r[1].x = -1.0; // flipped
	mp2.r[1].y = 0.0;
	m4x4_multiply(mat, &mp2, &mp3);
}
示例#2
0
void m4x4_ortho_tilt(matrix_4x4* mtx, float left, float right, float bottom, float top, float near, float far)
{
	matrix_4x4 mp;
	m4x4_zeros(&mp);

	// Build standard orthogonal projection matrix
	mp.r[0].x = 2.0f / (right - left);
	mp.r[0].w = (left + right) / (left - right);
	mp.r[1].y = 2.0f / (top - bottom);
	mp.r[1].w = (bottom + top) / (bottom - top);
	mp.r[2].z = 2.0f / (near - far);
	mp.r[2].w = (far + near) / (far - near);
	mp.r[3].w = 1.0f;

	// Fix depth range to [-1, 0]
	matrix_4x4 mp2, mp3;
	m4x4_identity(&mp2);
	mp2.r[2].z = 0.5;
	mp2.r[2].w = -0.5;
	m4x4_multiply(&mp3, &mp2, &mp);

	// Fix the 3DS screens' orientation by swapping the X and Y axis
	m4x4_identity(&mp2);
	mp2.r[0].x = 0.0;
	mp2.r[0].y = 1.0;
	mp2.r[1].x = -1.0; // flipped
	mp2.r[1].y = 0.0;
	m4x4_multiply(mtx, &mp2, &mp3);
}
示例#3
0
void ctr_rend_matrix_init() {
	//initialize matrix stack
	ctr_state.matrix_depth[0] = 0;
	ctr_state.matrix_depth[1] = 0;
	ctr_state.matrix_depth[2] = 0;
	ctr_state.matrix_current = GL_MODELVIEW;
	m4x4_identity(&ctr_state.matrix[0][0]);
	m4x4_identity(&ctr_state.matrix[1][0]);
	m4x4_identity(&ctr_state.matrix[2][0]);
}
CEntityMiscModel::CEntityMiscModel ( entity_t *e ){
	refCount = 1;
	m_entity = e;
	m_model = NULL;
	VectorSet( m_translate, 0,0,0 );
	VectorSet( m_euler, 0,0,0 );
	VectorSet( m_scale, 1,1,1 );
	VectorSet( m_pivot, 0,0,0 );
	m4x4_identity( m_transform );
	m4x4_identity( m_inverse_transform );
}
示例#5
0
CEntityEclassModel::CEntityEclassModel ()
{
  refCount = 1;
  m_eclass = NULL;
  m_model = NULL;
  VectorSet(m_translate, 0,0,0);
  VectorSet(m_euler, 0,0,0);
  VectorSet(m_scale, 1,1,1);
  VectorSet(m_pivot, 0,0,0);
  m4x4_identity(m_transform);
  m4x4_identity(m_inverse_transform);
}
示例#6
0
/** 
 * Calculate a perspective projection transformation.
 * 
 * @param m the matrix to save the transformation in
 * @param fovy the field of view in the y direction
 * @param aspect the view aspect ratio
 * @param zNear the near clipping plane
 * @param zFar the far clipping plane
 */
void m4x4_perspective(GLfloat *m, GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
   GLfloat tmp[16];
   m4x4_identity(tmp);

   float sine, cosine, cotangent, deltaZ;
   GLfloat radians = fovy / 2.0 * M_PI / 180.0;

   deltaZ = zFar - zNear;
   sine = sinf(radians);
   cosine = cosf(radians);

   if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
      return;

   cotangent = cosine / sine;

   tmp[0] = cotangent / aspect;
   tmp[5] = cotangent;
   tmp[10] = -(zFar + zNear) / deltaZ;
   tmp[11] = -1;
   tmp[14] = -2 * zNear * zFar / deltaZ;
   tmp[15] = 0;

   m4x4_copy(m, tmp);
}
示例#7
0
void glLoadIdentity() {
	int mode = ctr_state.matrix_current;
	int depth = ctr_state.matrix_depth[mode];
	matrix_4x4 *mat = &ctr_state.matrix[mode][depth];
	if (mat == 0 || depth < 0 || depth > 31) {
		return;
	}
	m4x4_identity(mat);
}
void CEntityMiscModel::Rotate( const vec3_t pivot, const vec3_t rotation ){
	m4x4_t rotation_matrix;

	m4x4_identity( rotation_matrix );
	m4x4_pivoted_rotate_by_vec3( rotation_matrix, rotation, eXYZ, pivot );
	m4x4_transform_point( rotation_matrix, m_translate );

	VectorIncrement( rotation, m_euler );

	UpdateCachedData();
}
示例#9
0
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z)
{
	matrix_4x4 tm, om;

	m4x4_identity(&tm);
	tm.r[0].w = x;
	tm.r[1].w = y;
	tm.r[2].w = z;

	m4x4_multiply(&om, mtx, &tm);
	m4x4_copy(mtx, &om);
}
示例#10
0
void m4x4_translate(matrix_4x4* mtx, float x, float y, float z)
{
	matrix_4x4 tm, om;

	m4x4_identity(&tm);
	tm.m[3] = x;
	tm.m[7] = y;
	tm.m[11] = z;

	m4x4_multiply(&om, mtx, &tm);
	m4x4_copy(mtx, &om);
}
示例#11
0
/**
 * Inverts a 4x4 matrix.
 *
 * This function can currently handle only pure translation-rotation matrices.
 * Read http://www.gamedev.net/community/forums/topic.asp?topic_id=425118
 * for an explanation.
 */
static void m4x4_invert(GLfloat *m)
{
   GLfloat t[16];
   m4x4_identity(t);

   // Extract and invert the translation part 't'. The inverse of a
   // translation matrix can be calculated by negating the translation
   // coordinates.
   t[12] = -m[12]; t[13] = -m[13]; t[14] = -m[14];

   // Invert the rotation part 'r'. The inverse of a rotation matrix is
   // equal to its transpose.
   m[12] = m[13] = m[14] = 0;
   m4x4_transpose(m);

   // inv(m) = inv(r) * inv(t)
   m4x4_multiply(m, t);
}
示例#12
0
/** 
 * Draws the gears in GLES 2 mode.
 */
static void draw_sceneGLES2(void)
{
   GLfloat transform[16];
   m4x4_identity(transform);

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   /* Translate and rotate the view */
   m4x4_translate(transform, 0.9, 0.0, -state->viewDist);
   m4x4_rotate(transform, view_rotx, 1, 0, 0);
   m4x4_rotate(transform, view_roty, 0, 1, 0);
   m4x4_rotate(transform, view_rotz, 0, 0, 1);

   /* Draw the gears */
   draw_gearGLES2(state->gear1, transform, -3.0, -2.0, state->angle);
   draw_gearGLES2(state->gear2, transform, 3.1, -2.0, -2 * state->angle - 9.0);
   draw_gearGLES2(state->gear3, transform, -3.1, 4.2, -2 * state->angle - 25.0);
}
void CEntityMiscModel::UpdateCachedData(){
	aabb_t aabb_temp;

	m4x4_identity( m_transform );
	m4x4_pivoted_transform_by_vec3( m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot );
	memcpy( m_inverse_transform, m_transform, sizeof( m4x4_t ) );
	m4x4_invert( m_inverse_transform );

	aabb_clear( &aabb_temp );

	if ( m_model && m_model->pRender ) {
		aabb_extend_by_aabb( &aabb_temp, m_model->pRender->GetAABB() );
	}
	else{
		VectorSet( aabb_temp.extents, 8, 8, 8 );
	}

	aabb_for_transformed_aabb( &m_BBox, &aabb_temp, m_transform );
}
示例#14
0
void m4x4_persp_tilt(matrix_4x4* mtx, float fovx, float invaspect, float near, float far)
{
	// Notes:
	// We are passed "fovy" and the "aspect ratio". However, the 3DS screens are sideways,
	// and so are these parameters -- in fact, they are actually the fovx and the inverse
	// of the aspect ratio. Therefore the formula for the perspective projection matrix
	// had to be modified to be expressed in these terms instead.

	// Notes:
	// fovx = 2 atan(tan(fovy/2)*w/h)
	// fovy = 2 atan(tan(fovx/2)*h/w)
	// invaspect = h/w

	// a0,0 = h / (w*tan(fovy/2)) =
	//      = h / (w*tan(2 atan(tan(fovx/2)*h/w) / 2)) =
	//      = h / (w*tan( atan(tan(fovx/2)*h/w) )) =
	//      = h / (w * tan(fovx/2)*h/w) =
	//      = 1 / tan(fovx/2)

	// a1,1 = 1 / tan(fovy/2) = (...) = w / (h*tan(fovx/2))

	float fovx_tan = tanf(fovx / 2);
	matrix_4x4 mp;
	m4x4_zeros(&mp);

	// Build standard perspective projection matrix
	mp.r[0].x = 1.0f / fovx_tan;
	mp.r[1].y = 1.0f / (fovx_tan*invaspect);
	mp.r[2].z = (near + far) / (near - far);
	mp.r[2].w = (2 * near * far) / (near - far);
	mp.r[3].z = -1.0f;

	// Fix depth range to [-1, 0]
	matrix_4x4 mp2;
	m4x4_identity(&mp2);
	mp2.r[2].z = 0.5;
	mp2.r[2].w = -0.5;
	m4x4_multiply(mtx, &mp2, &mp);

	// Rotate the matrix one quarter of a turn CCW in order to fix the 3DS screens' orientation
	m4x4_rotate_z(mtx, M_PI / 2, true);
}
示例#15
0
void CEntityEclassModel::UpdateCachedData()
{
  aabb_t aabb_temp;

  aabb_clear(&aabb_temp);

  m4x4_identity(m_transform);
  m4x4_pivoted_transform_by_vec3(m_transform, m_translate, m_euler, eXYZ, m_scale, m_pivot);
  memcpy(m_inverse_transform, m_transform, sizeof(m4x4_t));
  if(m4x4_invert(m_inverse_transform) == 1) {
    Sys_Printf("ERROR: Singular Matrix, cannot invert");
  }

  if(m_eclass)
    aabb_construct_for_vec3(&aabb_temp, m_eclass->mins, m_eclass->maxs);
  else
    VectorSet(aabb_temp.extents, 8, 8, 8);

  aabb_for_transformed_aabb(&m_BBox, &aabb_temp, m_transform);
}
示例#16
0
qboolean FloodEntities( tree_t *tree )
{
    int			i, s;
    vec3_t		origin, offset, scale, angles;
    qboolean	r, inside, tripped, skybox;
    node_t		*headnode;
    entity_t	*e;
    const char	*value;


    headnode = tree->headnode;
    Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" );
    inside = qfalse;
    tree->outside_node.occupied = 0;

    tripped = qfalse;
    c_floodedleafs = 0;
    for( i = 1; i < numEntities; i++ )
    {
        /* get entity */
        e = &entities[ i ];

        /* get origin */
        GetVectorForKey( e, "origin", origin );
        if( VectorCompare( origin, vec3_origin ) )
            continue;

        /* handle skybox entities */
        value = ValueForKey( e, "classname" );
        if( !Q_stricmp( value, "_skybox" ) )
        {
            skybox = qtrue;
            skyboxPresent = qtrue;

            /* invert origin */
            VectorScale( origin, -1.0f, offset );

            /* get scale */
            VectorSet( scale, 64.0f, 64.0f, 64.0f );
            value = ValueForKey( e, "_scale" );
            if( value[ 0 ] != '\0' )
            {
                s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
                if( s == 1 )
                {
                    scale[ 1 ] = scale[ 0 ];
                    scale[ 2 ] = scale[ 0 ];
                }
            }

            /* get "angle" (yaw) or "angles" (pitch yaw roll) */
            VectorClear( angles );
            angles[ 2 ] = FloatForKey( e, "angle" );
            value = ValueForKey( e, "angles" );
            if( value[ 0 ] != '\0' )
                sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );

            /* set transform matrix (thanks spog) */
            m4x4_identity( skyboxTransform );
            m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
        }
        else
            skybox = qfalse;

        /* nudge off floor */
        origin[ 2 ] += 1;

        /* debugging code */
        //%	if( i == 1 )
        //%		origin[ 2 ] += 4096;

        /* find leaf */
        r = PlaceOccupant( headnode, origin, e, skybox );
        if( r )
            inside = qtrue;
        if( (!r || tree->outside_node.occupied) && !tripped )
        {
            xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
            tripped = qtrue;
        }
    }

    Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );

    if( !inside )
        Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
    else if( tree->outside_node.occupied )
        Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );

    return (qboolean) (inside && !tree->outside_node.occupied);
}
示例#17
0
文件: m4x4.c 项目: AEonZR/GtkRadiant
void m4x4_rotation_for_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order)
{
  double cx, sx, cy, sy, cz, sz;

  cx = cos(DEG2RAD(euler[0]));
  sx = sin(DEG2RAD(euler[0]));
  cy = cos(DEG2RAD(euler[1]));
  sy = sin(DEG2RAD(euler[1]));
  cz = cos(DEG2RAD(euler[2]));
  sz = sin(DEG2RAD(euler[2]));

  switch(order)
  {
  case eXYZ:

#if 1

    {
      matrix[0]  = (vec_t)(cy*cz);
      matrix[1]  = (vec_t)(cy*sz);
      matrix[2]  = (vec_t)-sy;
      matrix[4]  = (vec_t)(sx*sy*cz + cx*-sz);
      matrix[5]  = (vec_t)(sx*sy*sz + cx*cz);
      matrix[6]  = (vec_t)(sx*cy);
      matrix[8]  = (vec_t)(cx*sy*cz + sx*sz);
      matrix[9]  = (vec_t)(cx*sy*sz + -sx*cz);
      matrix[10] = (vec_t)(cx*cy);
    }

    matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
    matrix[15] =  1;

#else

    m4x4_identity(matrix);
    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;

    {
      m4x4_t temp;
      m4x4_identity(temp);
      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
      m4x4_premultiply_by_m4x4(matrix, temp);
      m4x4_identity(temp);
      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
      m4x4_premultiply_by_m4x4(matrix, temp);
    }
#endif

    break;

  case eYZX:
    m4x4_identity(matrix);
    matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
    matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;

    {
      m4x4_t temp;
      m4x4_identity(temp);
      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
      m4x4_premultiply_by_m4x4(matrix, temp);
      m4x4_identity(temp);
      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
      m4x4_premultiply_by_m4x4(matrix, temp);
    }
    break;

  case eZXY:
    m4x4_identity(matrix);
    matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
    matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;

    {
      m4x4_t temp;
      m4x4_identity(temp);
      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
      m4x4_premultiply_by_m4x4(matrix, temp);
      m4x4_identity(temp);
      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
      m4x4_premultiply_by_m4x4(matrix, temp);
    }
    break;

  case eXZY:
    m4x4_identity(matrix);
    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;

    {
      m4x4_t temp;
      m4x4_identity(temp);
      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
      m4x4_premultiply_by_m4x4(matrix, temp);
      m4x4_identity(temp);
      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
      m4x4_premultiply_by_m4x4(matrix, temp);
    }
    break;

  case eYXZ:

/* transposed
|  cy.cz + sx.sy.-sz + -cx.sy.0   0.cz + cx.-sz + sx.0   sy.cz + -sx.cy.-sz + cx.cy.0 |
|  cy.sz + sx.sy.cz + -cx.sy.0    0.sz + cx.cz + sx.0    sy.sz + -sx.cy.cz + cx.cy.0  |
|  cy.0 + sx.sy.0 + -cx.sy.1      0.0 + cx.0 + sx.1      sy.0 + -sx.cy.0 + cx.cy.1    |
*/

#if 1

  {
    matrix[0]  = (vec_t)(cy*cz + sx*sy*-sz);
    matrix[1]  = (vec_t)(cy*sz + sx*sy*cz);
    matrix[2]  = (vec_t)(-cx*sy);
    matrix[4]  = (vec_t)(cx*-sz);
    matrix[5]  = (vec_t)(cx*cz);
    matrix[6]  = (vec_t)(sx);
    matrix[8]  = (vec_t)(sy*cz + -sx*cy*-sz);
    matrix[9]  = (vec_t)(sy*sz + -sx*cy*cz);
    matrix[10] = (vec_t)(cx*cy);
  }

  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
  matrix[15] =  1;

#else

  m4x4_identity(matrix);
  matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
  matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;

  {
    m4x4_t temp;
    m4x4_identity(temp);
    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
    m4x4_premultiply_by_m4x4(matrix, temp);
    m4x4_identity(temp);
    temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
    temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
    m4x4_premultiply_by_m4x4(matrix, temp);
  }
#endif
  break;

  case eZYX:
#if 1

  {
    matrix[0]  = (vec_t)(cy*cz);
    matrix[4]  = (vec_t)(cy*-sz);
    matrix[8]  = (vec_t)sy;
    matrix[1]  = (vec_t)(sx*sy*cz + cx*sz);
    matrix[5]  = (vec_t)(sx*sy*-sz + cx*cz);
    matrix[9]  = (vec_t)(-sx*cy);
    matrix[2]  = (vec_t)(cx*-sy*cz + sx*sz);
    matrix[6]  = (vec_t)(cx*-sy*-sz + sx*cz);
    matrix[10] = (vec_t)(cx*cy);
  }

  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
  matrix[15] =  1;

#else

  m4x4_identity(matrix);
  matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
  matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;
  {
    m4x4_t temp;
    m4x4_identity(temp);
    temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
    temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
    m4x4_premultiply_by_m4x4(matrix, temp);
    m4x4_identity(temp);
    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
    m4x4_premultiply_by_m4x4(matrix, temp);
  }

#endif
  break;

  }

}
示例#18
0
static void PopulateTraceNodes( void ){
	int i, m, frame, castShadows;
	float temp;
	entity_t        *e;
	const char      *value;
	picoModel_t     *model;
	vec3_t origin, scale, angles;
	m4x4_t transform;


	/* add worldspawn triangles */
	m4x4_identity( transform );
	PopulateWithBSPModel( &bspModels[ 0 ], transform );

	/* walk each entity list */
	for ( i = 1; i < numEntities; i++ )
	{
		/* get entity */
		e = &entities[ i ];

		/* get shadow flags */
		castShadows = ENTITY_CAST_SHADOWS;
		GetEntityShadowFlags( e, NULL, &castShadows, NULL );

		/* early out? */
		if ( !castShadows ) {
			continue;
		}

		/* get entity origin */
		GetVectorForKey( e, "origin", origin );

		/* get scale */
		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
		temp = FloatForKey( e, "modelscale" );
		if ( temp != 0.0f ) {
			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
		}
		value = ValueForKey( e, "modelscale_vec" );
		if ( value[ 0 ] != '\0' ) {
			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
		}

		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
		angles[ 2 ] = FloatForKey( e, "angle" );
		value = ValueForKey( e, "angles" );
		if ( value[ 0 ] != '\0' ) {
			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
		}

		/* set transform matrix (thanks spog) */
		m4x4_identity( transform );
		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );

		/* hack: Stable-1_2 and trunk have differing row/column major matrix order
		   this transpose is necessary with Stable-1_2
		   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
		//%	m4x4_transpose( transform );

		/* get model */
		value = ValueForKey( e, "model" );

		/* switch on model type */
		switch ( value[ 0 ] )
		{
		/* no model */
		case '\0':
			break;

		/* bsp model */
		case '*':
			m = atoi( &value[ 1 ] );
			if ( m <= 0 || m >= numBSPModels ) {
				continue;
			}
			PopulateWithBSPModel( &bspModels[ m ], transform );
			break;

		/* external model */
		default:
			frame = 0;
			if ( strcmp( "", ValueForKey( e, "_frame" ) ) ) {
				frame = IntForKey( e, "_frame" );
			}
			else if ( strcmp( "", ValueForKey( e, "frame" ) ) ) {
				frame = IntForKey( e, "frame" );
			}
			model = LoadModel( value, frame );
			if ( model == NULL ) {
				continue;
			}
			PopulateWithPicoModel( castShadows, model, transform );
			continue;
		}

		/* get model2 */
		value = ValueForKey( e, "model2" );

		/* switch on model type */
		switch ( value[ 0 ] )
		{
		/* no model */
		case '\0':
			break;

		/* bsp model */
		case '*':
			m = atoi( &value[ 1 ] );
			if ( m <= 0 || m >= numBSPModels ) {
				continue;
			}
			PopulateWithBSPModel( &bspModels[ m ], transform );
			break;

		/* external model */
		default:
			frame = IntForKey( e, "_frame2" );
			model = LoadModel( value, frame );
			if ( model == NULL ) {
				continue;
			}
			PopulateWithPicoModel( castShadows, model, transform );
			continue;
		}
	}
}