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); }
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); }
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 ); }
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); }
/** * 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); }
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(); }
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); }
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); }
/** * 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); }
/** * 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 ); }
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); }
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); }
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); }
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; } }
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; } } }