/// <summary> /// Create an Agent. /// All Agents are collidable and have a single instance Object3D named agentObject. /// Set StepSize, create first, follow and above cameras. /// Set first as agentCamera /// <param name="stage"></param> /// <param name="label"></param> /// <param name="position"></param> /// <param name="orientAxis"></param> /// <param name="radians"></param> /// <param name="meshFile"></param> /// </summary> public Agent(Stage stage, string label, Vector3 position, Vector3 orientAxis, float radians, string meshFile) : base(stage, label, meshFile) { // create an Object3D for this agent agentObject = addObject(position, orientAxis, radians); first = new Camera(stage, agentObject, Camera.CameraEnum.FirstCamera); follow = new Camera(stage, agentObject, Camera.CameraEnum.FollowCamera); above = new Camera(stage, agentObject, Camera.CameraEnum.AboveCamera); stage.addCamera(first); stage.addCamera(follow); stage.addCamera(above); agentCamera = first; }
/// <summary> /// Construct a pack with an Object3D leader /// </summary> /// <param name="theStage"> the scene </param> /// <param name="label"> name of pack</param> /// <param name="meshFile"> model of a pack instance</param> /// <param name="xPos, zPos"> approximate position of the pack </param> /// <param name="aLeader"> alpha dog can be used for flock center and alignment </param> public Pack(Stage theStage, string label, string meshFile, int nDogs, int xPos, int zPos, Object3D theLeader) : base(theStage, label, meshFile) { isCollidable = true; random = new Random(); leader = theLeader; int spacing = stage.Spacing; // initial vertex offset of dogs around (xPos, zPos) int [,] position = { {0, 0}, {7, -4}, {-5, -2}, {-7, 4}, {5, 2} , {3,9}, {12, 0}, {5, -10}}; for( int i = 0; i < position.GetLength(0); i++) { int x = xPos + position[i, 0]; int z = zPos + position[i, 1]; float scale = (float)(0.5 + random.NextDouble()); addObject( new Vector3(x * spacing, stage.surfaceHeight(x, z), z * spacing), new Vector3(0, 1, 0), 0.0f, new Vector3(scale, scale, scale)); } }
/// <summary> /// Create a new Object3D, place it on the stage, add to Model3D's instance collection, /// and if collidable add to collision collection. /// </summary> /// <param name="position"> location of new Object3D</param> /// <param name="orientAxis"> axis of rotation</param> /// <param name="radians"> rotation on orientAxis</param> /// <returns> the new Object3D</returns> public Object3D addObject(Vector3 position, Vector3 orientAxis, float radians) { Object3D obj3d = new Object3D(stage, this, String.Format("{0}.{1}", name, instance.Count), position, orientAxis, radians, Vector3.One); obj3d.updateBoundingSphere(); // need to do only once for Model3D instance.Add(obj3d); if (IsCollidable) stage.Collidable.Add(obj3d); return obj3d; }
/// <summary> /// Sets the Object3D's height value to the corresponding surface position's height /// </summary> /// <param name="anObject3D"> has Translation.X and Translation.Y values</param> public void setSurfaceHeight(Object3D anObject3D) { float terrainHeight = terrain.surfaceHeight( (int) (anObject3D.Translation.X / spacing), (int) (anObject3D.Translation.Z / spacing) ); anObject3D.Translation = new Vector3( anObject3D.Translation.X, terrainHeight, anObject3D.Translation.Z); }
// Methods public bool isCollidable(Object3D obj3d) { if (collidable.Contains(obj3d)) return true; else return false; }
public void rotateToTarget(Object3D dog, Vector3 toTarget, float angle) { Vector3 axis, toObj; double radian, aCosDot; // put both vector on the XZ plane of Y == 0 toObj = new Vector3(dog.Translation.X, 0, dog.Translation.Z); toTarget.Normalize(); // Dot not defined for co-linear vectors: test toTarget and Forward // if vectors are identical (w/in epsilon 0.05) return, no need to turnToFace if (Vector3.Distance(toTarget, dog.Forward) <= 0.05) return; // if vectors are reversed (w/in epsilon 0.05) nudgle alittle if (Vector3.Distance(Vector3.Negate(toTarget), dog.Forward) <= 0.05) { toTarget.X += 0.05f; toTarget.Z += 0.05f; toTarget.Normalize(); } // determine axis for rotation axis = Vector3.Cross(toTarget, dog.Forward); // order of arguments maters axis.Normalize(); // get cosine of rotation aCosDot = Math.Acos(Vector3.Dot(toTarget, dog.Forward)); // test and adjust direction of rotation into radians if (aCosDot == 0) radian = Math.PI * 2; else if (aCosDot == Math.PI) radian = Math.PI; else if (axis.X + axis.Y + axis.Z < 0) radian = (float)(2 * Math.PI - aCosDot); else radian = -aCosDot; // stage.setInfo(19, string.Format("radian to rotate = {0,5:f2}, axis for rotation ({1,5:f2}, {2,5:f2}, {3,5:f2})", // radian, axis.X, axis.Y, axis.Z)); if (Double.IsNaN(radian)) { // validity check, this should not happen stage.setInfo(19, "error: Object3D.turnToFace() radian is NaN"); return; } else { // valid radian perform transformation // save location, translate to origin, rotate, translate back to location //radian = radian / alignmentWeight; Vector3 objectLocation = dog.Translation; dog.Orientation *= Matrix.CreateTranslation(-1 * objectLocation); // all terrain rotations are really on Y dog.Orientation *= Matrix.CreateFromAxisAngle(axis, (float)radian/60); dog.Up = Vector3.Up; // correct for flipped from negative axis of rotation dog.Orientation *= Matrix.CreateTranslation(objectLocation); return; } }
public Camera(Stage aScene, Object3D anAgentObject, CameraEnum cameraType) { scene = aScene; agent = anAgentObject; cameraCase = cameraType; }
private int findTreasure(Object3D agentObject, List<Treasure> treasure) { float minDistance = 100000000; int targetTreasure = 0; for (int i = 0; i < treasure.Count; i++) { if (!treasure[i].tagged) //don't check distance for tagged treasures { float distance = Vector3.Distance( treasure[i].translation, new Vector3(agentObject.Translation.X, 0, agentObject.Translation.Z)); if (distance < minDistance) { minDistance = distance; targetTreasure = i; } } } if (minDistance == 100000000) allTagged = true; return targetTreasure; }
/// <summary> /// Sets the Object3D's height value to the corresponding surface position's height /// </summary> /// <param name="anObject3D"> has Translation.X and Translation.Y values</param> public void setSurfaceHeight(Object3D anObject3D) { //Vecs 3s needed for each corner Vector3 cornerA, cornerB, cornerC, cornerD; Vector3 aPos = anObject3D.Translation; //height values for the corners float heightA, heightB, heightC, heightD; heightB = terrain.surfaceHeight((int)(aPos.X / spacing) + 1, (int)(aPos.Z / spacing)); heightC = terrain.surfaceHeight((int)(aPos.X / spacing), (int)(aPos.Z / spacing) + 1); heightD = terrain.surfaceHeight((int)(aPos.X / spacing) + 1, (int)(aPos.Z / spacing) + 1); heightA = terrain.surfaceHeight((int)(aPos.X / spacing), (int)(aPos.Z / spacing)); //Make Vector3 Objects andd add heights as y value cornerA = new Vector3((int)(aPos.X / spacing), heightA, (int)(aPos.Z / spacing)); cornerB = new Vector3((int)(aPos.X / spacing) * spacing + spacing, heightB, (int)(aPos.Z / spacing) * spacing); cornerC = new Vector3((int)(aPos.X / spacing) * spacing, heightC, (int)(aPos.Z / spacing) * spacing + spacing); cornerD = new Vector3((int)(aPos.X / spacing) * spacing + spacing, heightD, (int)(aPos.Z / spacing) * spacing + spacing); //difference on X and on Z float xy; float zy; float terrainHeight; //Differentiate between bottom and top surface //If player is closer to top left corner use lerp //else use lerp on bottom //top surface if (Vector3.Distance(cornerA, aPos) < Vector3.Distance(cornerD, aPos)) { xy = Vector3.Lerp(cornerA, cornerB, ((float)(aPos.X - cornerA.X)) / spacing).Y - cornerA.Y; zy = Vector3.Lerp(cornerA, cornerC, ((float)(aPos.Z - cornerA.Z)) / spacing).Y - cornerA.Y; aPos.Y = cornerA.Y + xy + zy; } //bottom surface else { xy = Vector3.Lerp(cornerD, cornerC, ((float)(cornerD.X - aPos.X)) / spacing).Y - cornerD.Y; zy = Vector3.Lerp(cornerD, cornerB, ((float)(cornerD.Z - aPos.Z)) / spacing).Y - cornerD.Y; aPos.Y = cornerD.Y + xy + zy; } if (lerping == false) { terrainHeight = terrain.surfaceHeight( (int)(anObject3D.Translation.X / spacing), (int)(anObject3D.Translation.Z / spacing)); anObject3D.Translation = new Vector3(aPos.X, terrainHeight, aPos.Z); } else { anObject3D.Translation = new Vector3(aPos.X, aPos.Y, aPos.Z); } }