|
|
11/14/2008 <描述>载入3D模型,用上下左右方向键操作一个摄像机,已3D模型的中心为圆点的一个球面为运行轨迹,全方位的观察该3D物体。同时在屏幕上显示X,Y,Z三条坐标轴 /* INFR 1350U Photographic and Image Processing Techniques * Assignment Two * Submit by: Jian Sun * Student ID Number: 100285100 */ using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Net; using Microsoft.Xna.Framework.Storage; namespace Sun_as2 { /// <summary> /// This is the main type for your game /// </summary> public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Model helicopter; Vector3 helicopterPosition = Vector3.Zero;//set the helicopter at the origin of the coordinate system Vector3 cameraPosition = new Vector3(0.0f, 0.0f, 45.0f); Vector3 cameraLookAt = new Vector3(0.0f, 0.0f, 0.0f); //set the camera's orientation Vector3 tempPostition; //this will be stored the camera position after rotate Matrix cameraProjectionMatrix; //a projection matrix Matrix cameraViewMatrix; //a view matrix static float currentVerAng = 0; //set the current vertical angle equals 0 static float currentHorAng = 0; //set the current horizontal angle equals 0 //an array to store all points that will be used to draw three lines VertexPositionColor[] vertices; BasicEffect basicEffect; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } /// <summary> /// Allows the game to perform any initialization it needs to before starting to run. /// This is where it can query for any required services and load any non-graphic /// related content. Calling base.Initialize will enumerate through any components /// and initialize them as well. /// </summary> protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } /// <summary> /// LoadContent will be called once per game and is the place to load /// all of your content. /// </summary> protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here helicopter = Content.Load<Model>("Models\\bell47");//load the model into XNA //initialize the camera view matrix cameraViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up); //initialize the camera projection matrix cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(45.0f), //set the field of view to 45 degree graphics.GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f); //load the vertices, there are total 6 points vertices = new VertexPositionColor[6]; vertices[0] = new VertexPositionColor(Vector3.Zero, Color.Red); vertices[1] = new VertexPositionColor(new Vector3(400,0,0), Color.Red); //x-axis is red vertices[2] = new VertexPositionColor(Vector3.Zero, Color.Green); vertices[3] = new VertexPositionColor(new Vector3(0,400,0), Color.Green); //y-axis is green vertices[4] = new VertexPositionColor(Vector3.Zero, Color.Blue); vertices[5] = new VertexPositionColor(new Vector3(0,0,400), Color.Blue); //z-axis is blue //initalize the basicEffect basicEffect = new BasicEffect(graphics.GraphicsDevice, null); //enable the color basicEffect.VertexColorEnabled = true; } /// <summary> /// UnloadContent will be called once per game and is the place to unload /// all content. /// </summary> protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } /// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here // Allows the game to exit by pressing 'Q' and 'q' on keyborad KeyboardState keys; keys = Keyboard.GetState(); if (keys.IsKeyDown(Keys.Q)) this.Exit(); //use a key 'Q' to exit if (keys.IsKeyDown(Keys.Up)) { //if the current vertical angle is large than -80 degree if (currentVerAng >= -80) { currentVerAng -= 5; //update the current vertical angle updateCameraPosition(); } } if (keys.IsKeyDown(Keys.Left)) { currentHorAng -= 5; //decrease the current horizontal angle means turn left if (currentHorAng < 0 || currentHorAng > 360) //the current horizontal angle must in the range[0,360] { if (currentHorAng < 0) currentHorAng += 360; //if current horizontal angle is negative, plus 360 degree else currentHorAng -= 360; //if current horizontal angle is positive, minus 360 degree } updateCameraPosition(); } if (keys.IsKeyDown(Keys.Right)) { currentHorAng += 5; //increase the current horizontal angle means turn right if (currentHorAng < 0 || currentHorAng > 360) //the current horizontal angle must in the range[0,360] { if (currentHorAng < 0) currentHorAng += 360; //if current horizontal angle is negative, plus 360 degree else currentHorAng -= 360; //if current horizontal angle is positive, minus 360 degree } updateCameraPosition(); } if (keys.IsKeyDown(Keys.Down)) { //if the current vertial angle is small than 80 if (currentVerAng <= 80) { currentVerAng += 5; updateCameraPosition(); } } base.Update(gameTime); } //update the position of camera void updateCameraPosition() { tempPostition = Vector3.Transform(cameraPosition, Matrix.CreateRotationX(MathHelper.ToRadians(currentVerAng))); tempPostition = Vector3.Transform(tempPostition, Matrix.CreateRotationY(MathHelper.ToRadians(currentHorAng))); cameraViewMatrix = Matrix.CreateLookAt(tempPostition, helicopterPosition, Vector3.Up); } /// <summary> /// This is called when the game should draw itself. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.WhiteSmoke); // TODO: Add your drawing code here //set up the cameraViewMatrix DrawLine(); DrawModel(helicopter, helicopterPosition);//draw the model base.Draw(gameTime); } //this function is used to draw a 3D cooridnate system void DrawLine() { basicEffect.Begin();//start to draw the 3D coordinate foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Begin(); basicEffect.World = Matrix.CreateTranslation(Vector3.Zero); basicEffect.View = cameraViewMatrix; basicEffect.Projection = cameraProjectionMatrix; graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionColor.VertexElements); graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 3); pass.End(); } basicEffect.End(); } //this funtion is used to draw the model and the model's effects //it's from the XNA creators online club, 3D game tutorial //website link:http://creators.xna.com/en-us/education/gettingstarted/bg3d/chapter4 void DrawModel(Model model, Vector3 modelPosition) { foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.PreferPerPixelLighting = true; //becasue the origin model is too big, therefore I make it smaller,the rate is 0.05 effect.World = Matrix.CreateScale(0.05f) * Matrix.CreateTranslation(modelPosition); effect.Projection = cameraProjectionMatrix; effect.View = cameraViewMatrix; } mesh.Draw(); } } } } #include "Keyframe.h" #include <iostream> #include <math.h> using namespace std; Keyframe_t *Keyframe_new(vector3_t *position) { Keyframe_t *key = new Keyframe_t; vector3_copy(position, &key->info.position); return key; } /*copy the Keyframe_t k to Keyframe_t result*/ void Keyframe_copy(Keyframe_t *k, Keyframe_t *result) { result->info = k->info; result->durationMS = k->durationMS; result->startMS = k->startMS; } void Keyframe_interpolateLinear(Keyframe_t *k1, Keyframe_t *k2, float t, Keyframe_t *result) { vector3_lerp(&k1->info.position,&k2->info.position,t,&result->info.position); //call a vector3_lerp function to do interpolate linear } void Keyframe_interpolateCatmullRom(Keyframe_t *k1, Keyframe_t *k2, Keyframe_t *k3, Keyframe_t *k4, float t, Keyframe_t *result) { vector3_catmullRom(&k1->info.position,&k2->info.position,&k3->info.position,&k4->info.position,t,&result->info.position); //call a vector3_catmullRom to do catmull rom splines interpolation } KeyframeAnimationSystem_t *KAS_new() { KeyframeAnimationSystem_t *kas = new KeyframeAnimationSystem_t; /* other initialization here */ kas->currentKeyframe = 0; //initialize the currentKeyframe is 0 kas->loopFlag = true; kas->interpolationMode = INTERPOLATION_CATMULL_ROM; kas->isAnimating = false; return kas; } void KAS_toggleInterpolationMode(KeyframeAnimationSystem_t *kas) { //change the interpolation mode if (kas->interpolationMode == INTERPOLATION_LINEAR) kas->interpolationMode = INTERPOLATION_CATMULL_ROM; else kas->interpolationMode = INTERPOLATION_LINEAR; } void KAS_addKeyframe(KeyframeAnimationSystem_t *kas, Keyframe_t *key) { kas->keys.push_back(key); //add a keyframe_t key into the vector in keyframeAnimationSystem_t } void KAS_update(KeyframeAnimationSystem_t *kas, float timeMS) { kas->currentTimeMS = timeMS; //determine the current time is between in which two keys if (kas->keys[kas->currentKeyframe]->startMS <= timeMS && timeMS < kas->keys[kas->currentKeyframe]->startMS+kas->keys[kas->currentKeyframe]->durationMS) { KAS_interpolate(kas,timeMS,&kas->currentValues); } else { //while the current time is out of the range, it means the current key is finished, so switch to next keyframe if (kas->currentKeyframe < kas->keys.size()-1) //make sure the currentKeyframe is not over the size of vector list { KAS_switchToNextKeyframe(kas); } else { kas->isAnimating = false;//when the time is finish,the sprite is in the end position, therefore, the isAnimating is false } } } void KAS_interpolate(KeyframeAnimationSystem_t *kas, float timeMS, Keyframe_t *result) { float t; t = (timeMS - kas->keys[kas->currentKeyframe]->startMS)/kas->keys[kas->currentKeyframe]->durationMS; //transfer the current time into [0,1]] //if the interpolation mode is linear if (kas->interpolationMode == INTERPOLATION_LINEAR) Keyframe_interpolateLinear(KAS_getCurrentKeyframe(kas),KAS_getNextKeyframe(kas),t,result); else { //recaluate the index value of four points in order to get catmull rom value int p0,p1,p2,p3; p1 = kas->currentKeyframe; p0 = kas->currentKeyframe-1; if (p0<0) p0 = p1; p2 = kas->currentKeyframe+1; if (p2 == kas->keys.size()) p2 = p1; p3 = kas->currentKeyframe+2; if (p3>=kas->keys.size()) p3 = p2; Keyframe_interpolateCatmullRom(KAS_getKeyframeAtIndex(kas,p0), //the four points in the curve KAS_getKeyframeAtIndex(kas,p1), KAS_getKeyframeAtIndex(kas,p2), KAS_getKeyframeAtIndex(kas,p3), t, result); } } void KAS_switchToNextKeyframe(KeyframeAnimationSystem_t *kas) { kas->currentKeyframe++; //switch to next keyframe } Keyframe_t *KAS_getNextKeyframe(KeyframeAnimationSystem_t *kas) { return kas->keys[kas->currentKeyframe+1];//return the pointer of next keyframe } Keyframe_t *KAS_getCurrentKeyframe(KeyframeAnimationSystem_t *kas) { return kas->keys[kas->currentKeyframe];//reture the pointer of current keyframe } Keyframe_t *KAS_getKeyframeAtIndex(KeyframeAnimationSystem_t *kas, int ind) { return kas->keys[ind];//return the pointer of keyframe at index ind } void KAS_setInterpolationMode(KeyframeAnimationSystem_t *kas, int interpolationMode) { kas->interpolationMode = interpolationMode; //set the interpolation mode equals int interpolationMode } void KAS_startAnimation(KeyframeAnimationSystem_t *kas, float timeMS) { kas->startTimeMS = timeMS; //set the start time in the keyframeAnimationSystem_t } void KAS_stopAnimation(KeyframeAnimationSystem_t *kas) { kas->isAnimating = false; //stop the animation } void KAS_toggleAnimation(KeyframeAnimationSystem_t *kas, float timeMS) { kas->currentTimeMS = timeMS;//set the current time = timeMS if (kas->isAnimating) kas->isAnimating = false; else kas->isAnimating = true;//toggle animation } void KAS_clearAllKeyframes(KeyframeAnimationSystem_t *kas) { kas->keys.clear(); //clear all elements in the vector keys } #ifndef _KEYFRAME_H #define _KEYFRAME_H #include <vector> #include <algorithm> #include "VectorMath.h" using namespace std; /* this file contains the declarations for functions in a keyframe animation system */ enum {INTERPOLATION_LINEAR=0, INTERPOLATION_CATMULL_ROM}; /* the KeyframeInfo struct contains information that is to be used in a single keyframe - i.e. note it may contain many types of things */ typedef struct _KeyframeInfo_t { vector3_t position; }KeyframeInfo_t; /* the keyframe contains the information plus other variables you would need to define a keyframe animation system */ typedef struct _Keyframe_t { KeyframeInfo_t info; float durationMS; float startMS; // set when changing the keyframe to this one }Keyframe_t; /* The Keyframe Animation System contains a list of keyframes * and any other information that is necessary * You may add anything else you need to this structure. */ typedef struct _KeyframeAnimationSystem_t { vector<Keyframe_t*> keys; bool loopFlag; // does the system loop back to the beginning or not int currentKeyframe; int interpolationMode; bool isAnimating; float deltaTimeMS; // delta since previous update float startTimeMS; float currentTimeMS; float previousTimeMS; // the previous time update Keyframe_t currentValues; // the current interpolated values to be used for drawing purposes }KeyframeAnimationSystem_t; /* functions needed to implement a keyframe animation system or KAS */ /* this returns a new keyframe with given position */ Keyframe_t *Keyframe_new(vector3_t *position); /* this returns a new initialized KeyframeAnimationSystem */ KeyframeAnimationSystem_t *KAS_new(); /****************************/ /* Keyframe functions */ /****************************/ /*copy keyframe_t k to the keyframe_t result*/ void Keyframe_copy(Keyframe_t *k, Keyframe_t *result); /* interpolation routines for keyframes */ void Keyframe_interpolateLinear(Keyframe_t *k1, Keyframe_t *k2, float timeMS, Keyframe_t *result); void Keyframe_interpolateCatmullRom(Keyframe_t *k1, Keyframe_t *k2, Keyframe_t *k3, Keyframe_t *k4, float timeMS, Keyframe_t *result); /***************************/ /* Keyframe animation system functions */ /***************************/ /*switch the current interpolation mode from Linear to Catmull-rom or from Catmull-rom to Linear interpolation*/ void KAS_toggleInterpolationMode(KeyframeAnimationSystem_t *kas); /* add a keyframe to the system */ void KAS_addKeyframe(KeyframeAnimationSystem_t *kas, Keyframe_t *key); /* this updates the keyframe animation given the current time in milliseconds */ void KAS_update(KeyframeAnimationSystem_t *kas, float timeMS); /* this calls the appropriate interpolation routines and returns the interpolated values in result */ void KAS_interpolate(KeyframeAnimationSystem_t *kas, float timeMS, Keyframe_t *result); /* returns the next keyframe in the sequence */ Keyframe_t *KAS_getNextKeyframe(KeyframeAnimationSystem_t *kas); /* this returns the current keyframe */ Keyframe_t *KAS_getCurrentKeyframe(KeyframeAnimationSystem_t *kas); /* this returns a particular keyframe given an index into the array/list */ Keyframe_t *KAS_getKeyframeAtIndex(KeyframeAnimationSystem_t *kas, int ind); /* this just switches the animation to the next keyframe */ void KAS_switchToNextKeyframe(KeyframeAnimationSystem_t *kas); /* easy functions to round out the functionality */ /* this sets the interpolation mode to be either linear or catmull rom */ void KAS_setInterpolationMode(KeyframeAnimationSystem_t *kas, int interpolationMode); /* this tells the system to start animating and passes in the current time in milliseconds */ void KAS_startAnimation(KeyframeAnimationSystem_t *kas, float timeMS); /* this stops the animation */ void KAS_stopAnimation(KeyframeAnimationSystem_t *kas); /* this toggles the animation, if it was animating, it is now stopped */ void KAS_toggleAnimation(KeyframeAnimationSystem_t *kas, float timeMS); /* this clears all keyframes from the KAS */ void KAS_clearAllKeyframes(KeyframeAnimationSystem_t *kas); #endif #include "VectorMath.h" #include <string> #include <iostream> using namespace std; vector3_t *vector3_new(float x, float y, float z) { vector3_t *v = new vector3_t; vector3_set(v,x,y,z); return v; } /* set up a new vector with appropriate values */ void vector3_set(vector3_t *v, float x, float y, float z) { v->x = x; //set the float x equals the x value of vector v v->y = y; //set the float y equals the y value of vector v v->z = z; //set the float z equals the z value of vector v } /* vector copy, result = v1 */ void vector3_copy(vector3_t *v1, vector3_t *result) { result->x = v1->x; //set the x value in vector result equals the x value of vector v1 result->y = v1->y; //set the y value in vector result equals the y value of vector v1 result->z = v1->z; //set the z value in vector result equals the z value of vector v1 } /* returns v1 dot v2 */ float vector3_dot(vector3_t *v1, vector3_t *v2) { return v1->x*v2->x+v1->y*v2->y+v1->z*v2->z;//the formula of dot product is x1x2+y1y2+z1z2 } /* result = v1 x v2 */ void vector3_cross(vector3_t *v1, vector3_t *v2, vector3_t *result) { //the formula for corss product is v1 x v2 = <v1y*v2z - v1z*v2y, v1z*v2x - v1x*v2z, v1x*v2y - v1y*v2x> result->x = v1->y*v2->z - v1->z*v2->y; result->y = v1->z*v2->x - v1->x*v2->z; result->z = v1->x*v2->y - v1->y*v2->x; } /* result = v1+v2 */ void vector3_add(vector3_t *v1, vector3_t *v2, vector3_t *result) { //the formula is result = <v1x+v2x, v1y+v2y, v1z+v2z> result->x = v1->x+v2->x; result->y = v1->y+v2->y; result->z = v1->z+v2->z; } /* result = v1-v2 */ void vector3_subtract(vector3_t *v1, vector3_t *v2, vector3_t *result) { //the formula is result = <v1x-v2x, v1y-v2y, v1z-v2z> result->x = v1->x-v2->x; result->y = v1->y-v2->y; result->z = v1->z-v2->z; } /* INTERPOLATION ROUTINES */ void vector3_lerp(vector3_t *v1, vector3_t *v2, float t, vector3_t *result) { //the formula is result = (1-t)v1 + t*v2 float t2 = 1 - t; result->x = v1->x*t2 + v2->x*t; result->y = v1->y*t2 + v2->y*t; result->z = v1->z*t2 + v2->z*t; } void vector3_catmullRom(vector3_t *v1, vector3_t *v2, vector3_t *v3, vector3_t *v4, float t, vector3_t *result) { //the formula is p(t) = [t~3,t~2,t,1]*0.5*M*[v1,v2,v3,v4]~t result->x = catmullRom1D(-1,2,-1,0,t)*v1->x + catmullRom1D(3,-5,0,2,t)*v2->x + catmullRom1D(-3,4,1,0,t)*v3->x + catmullRom1D(1,-1,0,0,t)*v4->x; result->y = catmullRom1D(-1,2,-1,0,t)*v1->y + catmullRom1D(3,-5,0,2,t)*v2->y + catmullRom1D(-3,4,1,0,t)*v3->y + catmullRom1D(1,-1,0,0,t)*v4->y; result->z = catmullRom1D(-1,2,-1,0,t)*v1->z + catmullRom1D(3,-5,0,2,t)*v2->z + catmullRom1D(-3,4,1,0,t)*v3->z + catmullRom1D(1,-1,0,0,t)*v4->z; } float catmullRom1D(float p0, float p1, float p2, float p3, float t) { //this formula is [t~3, t~2, t, 1] dot product [p0, p1, p2, p3]~t return (t*t*t*p0+t*t*p1+t*p2+p3)*0.5f; } void vector3_print(vector3_t *v, char *s) { cout << s<< "["<<v->x<<","<<v->y<<","<<v->z<<"]"<<endl; } #ifndef _VECTOR_MATH_H #define _VECTOR_MATH_H /* this file contains the function declarations for 3D vector math routines */ /* a vector contains an x,y,z */ typedef struct _vector3_t { float x,y,z; }vector3_t; /* create a new vector with values (x,y,z) */ vector3_t *vector3_new(float x, float y, float z); /* print a vector to the console */ void vector3_print(vector3_t *v, char *s); /* set values in a vector with (x,y,z) */ void vector3_set(vector3_t *v, float x, float y, float z); /* vector copy, result = v1 */ void vector3_copy(vector3_t *v1, vector3_t *result); /* the scalar/inner/dot product returns v1 dot v2 */ float vector3_dot(vector3_t *v1, vector3_t *v2); /* the cross product, result = v1 x v2 */ void vector3_cross(vector3_t *v1, vector3_t *v2, vector3_t *result); /* vector addition, result = v1+v2 */ void vector3_add(vector3_t *v1, vector3_t *v2, vector3_t *result); /* vector subtraction, result = v1-v2 */ void vector3_subtract(vector3_t *v1, vector3_t *v2, vector3_t *result); /* INTERPOLATION ROUTINES */ /* lerp is linear interpolation given 2 vectors and a value t betwen 0..1 result is the linearly interpolated vector */ void vector3_lerp(vector3_t *v1, vector3_t *v2, float t, vector3_t *result); /* catmull rom spline interpolation. Given 4 vectors, and a t-value (between 0..1) result is the interpolated result */ void vector3_catmullRom(vector3_t *v1, vector3_t *v2, vector3_t *v3, vector3_t *v4, float t, vector3_t *result); /* this is a helper function that might be useful for you and would compute a single value for a single catmull rom spline */ float catmullRom1D(float p1, float p2, float p3, float p4, float t); #endif
|