static int test_angle (const vec3_t angles) { int i; quat_t rotation, r; vec3_t scale, shear; mat3_t mat; AngleQuat (angles, rotation); QuatToMatrix (rotation, mat, 0, 1); Mat3Decompose (mat, r, shear, scale); for (i = 0; i < 4; i++) if (!compare (rotation[i], r[i])) goto negate; return 1; negate: // Mat3Decompose always sets the rotation quaternion's scalar to +ve // but AngleQuat might produce a -ve scalar. QuatNegate (r, r); for (i = 0; i < 4; i++) if (!compare (rotation[i], r[i])) goto fail; return 1; fail: printf ("\n\n(%g %g %g)\n", VectorExpand (angles)); printf (" [%g %g %g %g]\n", QuatExpand (rotation)); printf (" [%g %g %g %g] [%g %g %g] [%g %g %g]\n", QuatExpand (r), VectorExpand (scale), VectorExpand (shear)); return 0; }
void Orientation_Widget::setQuat( QQuaternion q ) { quat = q; QMatrix3x3 m = QuatToMatrix( quat ); mat = QMatrix4x4(m); update(); }
void Orientation_Widget::setQuat2( QQuaternion q ) { quat2 = q; QMatrix3x3 m = QuatToMatrix( quat2 ); mat2 = QMatrix4x4(m); bQuat2Valid = true; update(); }
bool BOTAI_WillHomingMissileHit(VECTOR * MyPos) { float Cos; float Angle; VECTOR DirVector; VECTOR TmpVec; QUATLERP qlerp; SECONDARYWEAPONBULLET MissCopy = SecBulls[ HomingMissile ]; // direction vector from missile to me DirVector.x = MyPos->x - MissCopy.Pos.x; DirVector.y = MyPos->y - MissCopy.Pos.y; DirVector.z = MyPos->z - MissCopy.Pos.z; NormaliseVector( &DirVector ); // angle difference between the missile's current vector and wanted vector Cos = DotProduct( &DirVector, &MissCopy.DirVector ); // set the parameters to perform a linear interpolation on two quaternions QuatFrom2Vectors( &qlerp.end, &Forward, &DirVector ); qlerp.start = MissCopy.DirQuat; qlerp.crnt = &MissCopy.DirQuat; qlerp.dir = QuatDotProduct( &qlerp.start, &qlerp.end ); // bound angle difference if( Cos < -1.0F ) Cos = -1.0F; else if ( Cos > 1.0F ) Cos = 1.0F; // get angle difference in radians Angle = (float) acos( Cos ); // calculate the amount of angle to turn if( Angle ) qlerp.time = ( ( D2R( MissCopy.TurnSpeed ) * framelag ) / Angle ); else qlerp.time = 1.0F; if( qlerp.time > 1.0F ) qlerp.time = 1.0F; // perform quat interpolation QuatInterpolate( &qlerp ); QuatToMatrix( &MissCopy.DirQuat, &MissCopy.Mat ); ApplyMatrix( &MissCopy.Mat, &Forward, &MissCopy.DirVector ); ApplyMatrix( &MissCopy.Mat, &SlideUp, &MissCopy.UpVector ); // will missile hit? if(RaytoSphere2(MyPos, SHIP_RADIUS, &MissCopy.Pos, &MissCopy.DirVector, &TmpVec, &TmpVec )) { DebugPrintf("homing missile will hit\n"); return true; } else { DebugPrintf("safe from homing missile\n"); return false; } }
/*------------------------------------------------------------------- Procedure : Create Quat from dir vector and up vector Input : VECTOR * Direction Vector : VECTOR * Up Vector : QUAT * Destin Quaternion Output : Nothing -------------------------------------------------------------------*/ void QuatFromDirAndUp( VECTOR * Dir, VECTOR * Up, QUAT * Quat ) { MATRIX TempMat; VECTOR TempUp; QUAT RotQuat; QuatFrom2Vectors( Quat, &Forward, Dir ); QuatToMatrix( Quat, &TempMat ); ApplyMatrix( &TempMat, &SlideUp, &TempUp ); QuatFrom2Vectors( &RotQuat, &TempUp, Up ); QuatMultiply( &RotQuat, Quat, Quat ); }
void _GetMatrix(Animation* animation, double time, double m[4][4]) { Animation* a = (Animation*) animation; /* m = translation * rotation * scale */ /* Rotation. */ if(a->rotations) { double drot[4]; _GetRotation(a, time, drot); Rotation3 RR; RR.x = drot[0]; RR.y = drot[1]; RR.z = drot[2]; RR.angle = drot[3]; Quaternion q; FromAngleAxis(&q, RR.angle, RR.x, RR.y, RR.z); QuatToMatrix(&q, m); /* Also sets bottom row to 0 0 0 1 */ } else { m[0][0] = 1; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0; m[1][0] = 0; m[1][1] = 1; m[1][2] = 0; m[1][3] = 0; m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; m[2][3] = 0; m[3][0] = 0; m[3][1] = 0; m[3][2] = 0; m[3][3] = 1; } /* Concatenate with scaling. */ if(a->scales) { double S[3]; _GetScale(a, time, S); m[0][0] *= S[0]; m[0][1] *= S[1]; m[0][2] *= S[2]; m[1][0] *= S[0]; m[1][1] *= S[1]; m[1][2] *= S[2]; m[2][0] *= S[0]; m[2][1] *= S[1]; m[2][2] *= S[2]; } /* Translation. */ if(a->translations) { double P[3]; _GetTranslation(a, time, P); m[0][3] = P[0]; m[1][3] = P[1]; m[2][3] = P[2]; } }
/*=================================================================== Procedure : Check if im in an Active Teleport.... Input : void Output : true/false ===================================================================*/ bool TeleportsAreaCheck( VECTOR * NewPos , VECTOR * OldPos ,u_int16_t Group, OBJECT *obj ) { TELEPORT * TPpnt; TELEPORT * newTPpnt; TPpnt = TeleportsGroupLink[Group]; while( TPpnt ) { if( TPpnt->Status == TELEPORTACTIVE ) { TeleportsZoneCheck( OldPos , NewPos , TPpnt ); if( Entry ) { PlaySfx( SFX_Teleport, 1.0F ); // StartShipScreenShake( 10.0F ); // Were in the Zone.... newTPpnt = Teleports; newTPpnt += TPpnt->Links[Random_Range(TPpnt->num_links)]; obj->Group = newTPpnt->Group; obj->Pos = newTPpnt->Pos; #if TELEPORTS_VERSION_NUMBER >= 2 QuatFromDirAndUp( &newTPpnt->Dir, &newTPpnt->Up, &obj->Quat); QuatToMatrix( &obj->Quat, &obj->Mat ); #endif return true; } } TPpnt = TPpnt->NextInGroup; } return false; }
int SearObject::init(const std::string &file_name) { assert(m_initialised == false); std::string object; if (m_config.readFromFile(file_name)) { if (m_config.findItem(SECTION_model, KEY_filename)) { object = (std::string)m_config.getItem(SECTION_model, KEY_filename); } else { fprintf(stderr, "[SearObject] Error: No SearObject filename specified.\n"); return 1; } } else { fprintf(stderr, "[SearObject] Error reading %s as varconf file. Trying as SearObject file.\n", file_name.c_str()); object = file_name; } System::instance()->getFileHandler()->getFilePath(object); // Load SearObject file if (load(object)) { // Error loading object fprintf(stderr, "[SearObject] Error loading SearObject %s\n", object.c_str()); m_static_objects.clear(); return 1; } // Initialise transform matrix float matrix[4][4]; for (int j = 0; j < 4; ++j) { for (int i = 0; i < 4; ++i) { if (i == j) matrix[j][i] = 1.0f; else matrix[j][i] = 0.0f; } } bool do_transform = false; if (m_config.findItem(SECTION_model, KEY_rotation)) { const std::string &str=(std::string)m_config.getItem(SECTION_model, KEY_rotation); float w,x,y,z; sscanf(str.c_str(), "%f;%f;%f;%f", &w, &x, &y, &z); WFMath::Quaternion q(w,x,y,z); QuatToMatrix(q, matrix); do_transform = true; } if (m_config.findItem(SECTION_model, KEY_scale)) { double s = (double)m_config.getItem(SECTION_model, KEY_scale); for (int i = 0; i < 4; ++i) matrix[i][i] *= s; do_transform = true; } if (do_transform) { transform_object(m_static_objects, matrix); } bool ignore_minus_z = false; Scaling scale = SCALE_NONE; Alignment align = ALIGN_NONE; bool process_model = false; if (m_config.findItem(SECTION_model, KEY_ignore_minus_z)) { if ((bool)m_config.getItem(SECTION_model, KEY_ignore_minus_z)) { process_model = true; ignore_minus_z = true; } } if (m_config.findItem(SECTION_model, KEY_z_align)) { if ((bool)m_config.getItem(SECTION_model, KEY_z_align)) { process_model = true; align = ALIGN_Z; } } if (m_config.findItem(SECTION_model, KEY_align_mass)) { if ((bool)m_config.getItem(SECTION_model, KEY_align_mass)) { process_model = true; align = ALIGN_CENTRE_MASS; } } if (m_config.findItem(SECTION_model, KEY_align_bbox_hc)) { if ((bool)m_config.getItem(SECTION_model, KEY_align_bbox_hc)) { process_model = true; align = ALIGN_BBOX_HC; } } if (m_config.findItem(SECTION_model, KEY_align_bbox_lc)) { if ((bool)m_config.getItem(SECTION_model, KEY_align_bbox_lc)) { process_model = true; align = ALIGN_BBOX_LC; } } if (m_config.findItem(SECTION_model, KEY_align_extent)) { if ((bool)m_config.getItem(SECTION_model, KEY_align_extent)) { process_model = true; align = ALIGN_CENTRE_EXTENT; } } if (m_config.findItem(SECTION_model, KEY_scale_isotropic)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic)) { process_model = true; scale = SCALE_ISOTROPIC; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_x)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_x)) { process_model = true; scale = SCALE_ISOTROPIC_Z; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_y)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_y)) { process_model = true; scale = SCALE_ISOTROPIC_Y; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_z)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_z)) { process_model = true; scale = SCALE_ISOTROPIC_Z; } } if (m_config.findItem(SECTION_model, KEY_scale_anisotropic)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_anisotropic)) { process_model = true; scale = SCALE_ANISOTROPIC; } } if (process_model == true) { scale_object(m_static_objects, scale, align, ignore_minus_z); } contextCreated(); m_initialised = true; return 0; }
int LibModelFile::init(const std::string &filename) { assert(m_initialised == false); std::string object; if (m_config.readFromFile(filename)) { if (m_config.findItem(SECTION_model, KEY_filename)) { object = (std::string)m_config.getItem(SECTION_model, KEY_filename); } else { fprintf(stderr, "[LibModelFile] Error: No md3 filename specified.\n"); return 1; } } else { fprintf(stderr, "[LibModelFile] Error reading %s as varconf file. Trying as .md3 file.\n", filename.c_str()); object = filename; } // Initialise transform matrix float matrix[4][4]; for (int j = 0; j < 4; ++j) { for (int i = 0; i < 4; ++i) { if (i == j) matrix[j][i] = 1.0f; else matrix[j][i] = 0.0f; } } if (m_config.findItem(SECTION_model, KEY_rotation)) { const std::string &str=(std::string)m_config.getItem(SECTION_model, KEY_rotation); float w,x,y,z; sscanf(str.c_str(), "%f;%f;%f;%f", &w, &x, &y, &z); WFMath::Quaternion q(w,x,y,z); QuatToMatrix(q, matrix); } if (m_config.findItem(SECTION_model, KEY_scale)) { double s = (double)m_config.getItem(SECTION_model, KEY_scale); for (int i = 0; i < 4; ++i) matrix[i][i] *= s; } System::instance()->getFileHandler()->getFilePath(object); // Load md3 file // if (debug) printf("[LibModelFile] Loading: %s\n", object.c_str()); libmd3_file *modelFile = libmd3_file_load(object.c_str()); if (!modelFile) { fprintf(stderr, "[LibModelFile] Error loading %s file\n", object.c_str()); return 1; } for (int i = 0; i < modelFile->header->mesh_count; ++i) { libmd3_unpack_normals(&modelFile->meshes[i]); } // Get mesh data libmd3_mesh *meshp = modelFile->meshes; for (int i = 0; i < modelFile->header->mesh_count; ++i, ++meshp) { StaticObject* so = new StaticObject(); so->init(); // Get Texture data from Mesh int texture_id = NO_TEXTURE_ID; int texture_mask_id = NO_TEXTURE_ID; if (meshp->mesh_header->skin_count != 0) { std::string name = (const char*)(meshp->skins[0].name); m_config.clean(name); // Check for texture name overrides in vconf file // Backwards compatibility. if (m_config.findItem(name, KEY_filename)) { name = (std::string)m_config.getItem(name, KEY_filename); } // Check for texture name overrides in vconf file // New method if (m_config.findItem(name, KEY_texture_map_0)) { name = (std::string)m_config.getItem(name, KEY_texture_map_0); } // Request Texture ID texture_id = RenderSystem::getInstance().requestTexture(name); texture_mask_id = RenderSystem::getInstance().requestTexture(name, true); float m[4]; if (m_config.findItem(name, KEY_ambient)) { const std::string &str = (std::string)m_config.getItem(name, KEY_ambient); sscanf(str.c_str(), "%f;%f;%f;%f", &m[0], &m[1], &m[2], &m[3]); so->setAmbient(m); } if (m_config.findItem(name, KEY_diffuse)) { const std::string &str = (std::string)m_config.getItem(name, KEY_diffuse); sscanf(str.c_str(), "%f;%f;%f;%f", &m[0], &m[1], &m[2], &m[3]); so->setDiffuse(m); } if (m_config.findItem(name, KEY_specular)) { const std::string &str = (std::string)m_config.getItem(name, KEY_specular); sscanf(str.c_str(), "%f;%f;%f;%f", &m[0], &m[1], &m[2], &m[3]); so->setSpecular(m); } if (m_config.findItem(name, KEY_emission)) { const std::string &str = (std::string)m_config.getItem(name, KEY_emission); sscanf(str.c_str(), "%f;%f;%f;%f", &m[0], &m[1], &m[2], &m[3]); so->setEmission(m); } if (m_config.findItem(name, KEY_shininess)) { so->setShininess((double)m_config.getItem(name, KEY_shininess)); } } // Set the transform so->getMatrix().setMatrix(matrix); // Set the textures so->setTexture(0, texture_id, texture_mask_id); so->setNumPoints(meshp->mesh_header->vertex_count); so->setNumFaces(meshp->mesh_header->triangle_count); // Copy data into array. so->createVertexData(meshp->mesh_header->vertex_count * 3); float *ptr = so->getVertexDataPtr(); for (int i = 0; i < meshp->mesh_header->vertex_count * 3; ++i) { ptr[i] = default_scale * (float)meshp->vertices[i]; } so->copyTextureData(meshp->texcoords, meshp->mesh_header->vertex_count * 2); so->copyNormalData(meshp->normals, meshp->mesh_header->vertex_count * 3); so->copyIndices(meshp->triangles, meshp->mesh_header->triangle_count * 3); m_static_objects.push_back(so); } libmd3_file_free(modelFile); bool ignore_minus_z = false; Scaling scale = SCALE_NONE; Alignment align = ALIGN_NONE; bool process_model = false; if (m_config.findItem(SECTION_model, KEY_ignore_minus_z)) { if ((bool)m_config.getItem(SECTION_model, KEY_ignore_minus_z)) { process_model = true; ignore_minus_z = true; } } if (m_config.findItem(SECTION_model, KEY_z_align)) { if ((bool)m_config.getItem(SECTION_model, KEY_z_align)) { process_model = true; align = ALIGN_Z; } } if (m_config.findItem(SECTION_model, KEY_scale_isotropic)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic)) { process_model = true; scale = SCALE_ISOTROPIC; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_x)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_x)) { process_model = true; scale = SCALE_ISOTROPIC_Z; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_y)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_y)) { process_model = true; scale = SCALE_ISOTROPIC_Y; } } else if (m_config.findItem(SECTION_model, KEY_scale_isotropic_z)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_isotropic_z)) { process_model = true; scale = SCALE_ISOTROPIC_Z; } } if (m_config.findItem(SECTION_model, KEY_scale_anisotropic)) { if ((bool)m_config.getItem(SECTION_model, KEY_scale_anisotropic)) { process_model = true; scale = SCALE_ANISOTROPIC; } } if (process_model == true) { scale_object(m_static_objects, scale, align, ignore_minus_z); } contextCreated(); m_initialised = true; return 0; }