Example #1
0
        /// <summary>
        /// Clone this cell
        /// </summary>
        /// <param name="gene">The gene specifying this cell instance's orientation, wiring, etc.</param>
        /// <param name="owner">The organism that owns me</param>
        private Cell Clone(Gene gene, Organism owner)
        {
            // Make a shallow copy of all members
            Cell newCell = (Cell)this.MemberwiseClone();

            // Replace members that are CLONED copies of objects in the master...
            newCell.rootFrame = JointFrame.CloneHierarchy(rootFrame);	// my unique copy of the frame hierarchy
            // TODO: Clone any other members here

            // Replace or create members that are UNIQUE to this instance...
            newCell.instance = instance++;													// my instance number (tally in master)
            newCell.PlugOrientation = gene.Orientation;										// my orientation in the parent socket
            newCell.owner = owner;															// my owning organism

            newCell.joint = JointFrame.IndexFrameType(
                            newCell.rootFrame,JointFrame.FrameType.Animating);				// lists of my animation, hotspot & skt frames
            newCell.hotspot = JointFrame.IndexFrameType(
                            newCell.rootFrame, JointFrame.FrameType.Hotspot);
            newCell.socket = JointFrame.IndexFrameType(
                            newCell.rootFrame, JointFrame.FrameType.Socket);

            newCell.physiology = Physiology.LoadPhysiology(newCell.group, newCell.name, newCell.variantName,		// my Physiology class containing functionality
                                                            newCell,
                                                            newCell.joint.Length,
                                                            newCell.socket.Length);

            newCell.GetMyVariantIndex();                                                    // Convert variant name into an index before trying to access channel data

            newCell.channel = newCell.LoadChannels(gene);									// lists of channel info from gene AND mesh frames

            newCell.collisionFrames = new List<JointFrame>();
            newCell.GetMeshFrames(newCell.rootFrame, newCell.collisionFrames, false);		// a list of mesh-containing frames for collision tests

            // Set all the internal (organelle) frames to invisible, because they aren't normally rendered
            newCell.HideOrganelles();

            // TODO: Initialise other instance-specific members here

            // Now that everything is set up, call the Physiology subclass's Init() method to allow the physiology to initialise itself
            newCell.physiology.Init();

            // Add a device reset handler to rebuild this cell's resources
            Engine.Device.DeviceReset += new System.EventHandler(newCell.OnReset);

            return newCell;
        }
Example #2
0
        /// <summary>
        /// Get a clone of this Cell from the library, loading it first if necessary
        /// </summary>
        /// <returns>A modifiable clone of the named Cell</returns>
        /// <param name="gene">The gene containing the cell's properties, orientation and wiring</param>
        /// <param name="owner">The organism that owns me</param>
        public static Cell Get(Gene gene, Organism owner)
        {
            Cell cell = null;

            // Get name of the cell from the gene
            string fullname = gene.XFile();

            // if the library already contains a Cell of that name, that's what we'll clone from
            if (library.ContainsKey(fullname))
            {
                cell = (Cell)library[fullname];
            //				Debug.WriteLine("	Cell: Created new Cell instance: "+name+":"+cell.instance);
            }
            // otherwise, create a new entry in the library by loading a whole X file
            else
            {
                cell = new Cell(fullname);
            //				Debug.WriteLine("	Cell: Created new Cell archetype: "+name+":"+cell.instance);
            }

            // Return a cloned instance of this Cell
            Cell newCell = cell.Clone(gene, owner);

            newCell.CreateBoundMarker();								// temp: create marker to show bounding sphere

            return newCell;
        }
Example #3
0
        /// <summary>
        /// Update (called whether this is the current cameraship or not)
        /// </summary>
        public override void Update()
        {
            /// HACK: FOR TESTING ONLY - ROTATE THE SHIP
            ///RotateBy(0.03f, 0.05f, 0.02f);

            // Steer the spotlight to follow the camera
            if (CurrentShip==this)
                Fx.SetSpotlightPosition(Matrix.Invert(rootCell.GetHotspotNormalMatrix(0)) * Camera.ProjMatrix);

            // If there is a creature on the clamp, position/orient it so that it sticks to the clamp (hotspot 1)
            if (SelectedOrg != null)
            {
                // Set the selected organism's position and orientation according to the clamp's hotspot
                // (Organisms store their location/orientation in a vector/quaternion, so I need to convert
                // the hotspot matrix into this form. Luckily there's a function!)
                Matrix clampMatrix = rootCell.GetHotspotMatrix(1);
                Vector3 clampPosition = new Vector3(clampMatrix.M41, clampMatrix.M42, clampMatrix.M43);
                clampMatrix.M41 = clampMatrix.M42 = clampMatrix.M43 = 0;
                Quaternion rot = Quaternion.RotationMatrix(clampMatrix);            // NOTE: Assumes there's no scaling factor to mess up the rotation matrix
                rot.Normalize();                                                    // Normalization improves (but doesn't cure) an error in the rotation using SoftImage
                SelectedOrg.RotateTo(rot);
                SelectedOrg.MoveTo(clampPosition);
            }

            // If a socket is selected, make sure the socket marker is pointing at it
            if (SelectedSocket != null)
            {
                if (socketMarker == null)
                {
                    Color c = Color.FromArgb(16, 255, 0, 255);
                    socketMarker = Marker.CreateCone(c, new Vector3(0, 0, 0), new Orientation(), 0.1f, 32.0f);
                }
                else
                {
                    socketMarker.Goto(SelectedSocket.CombinedMatrix);
                }
            }
            else if (socketMarker != null)
            {
                socketMarker.Delete();
                socketMarker = null;
            }

            // If a link socket is selected, make sure the link marker is pointing at it
            if (LinkSocket != null)
            {
                if (linkMarker == null)
                {
                    Color c = Color.FromArgb(64, 255, 255, 0);
                    linkMarker = Marker.CreateCone(c, new Vector3(0, 0, 0), new Orientation(), 0.3f, 3.5f);
                }
                else
                {
                    linkMarker.Goto(LinkSocket.CombinedMatrix);
                }
            }
            else if (linkMarker != null)
            {
                linkMarker.Delete();
                linkMarker = null;
            }

            // If there's a creature being tractor beamed back to the clamp, update it
            if (TractorBeam != null)
            {
                // Magnetically attract org towards clamp position. If it is now close by, attach it ready for editing
                Matrix clampMatrix = rootCell.GetHotspotMatrix(1);
                if (TractorBeam.Tractor(new Vector3(clampMatrix.M41, clampMatrix.M42, clampMatrix.M43), Quaternion.RotationMatrix(clampMatrix)) == true)
                {
                    Attach(TractorBeam);
                    TractorBeam = null;
                }
            }

            // Pass control to the base method
            base.Update();
        }
Example #4
0
 /// <summary>
 /// Attach a creature to the clamp (discarding any previous occupant)
 /// </summary>
 /// <param name="org"></param>
 public void Attach(Organism org)
 {
     // detach any previous occupant
     if (SelectedOrg != null)
         Detach();
     // suspend physical properties, reset CG, etc. and set the selected org, cell & socket
     org.EditOn();
     // Remember this organism so that it can be tractor beamed back to the clamp after release
     TrackedOrg = org;
 }
Example #5
0
        /// <summary>
        /// TEMP: Create one or more creatures for testing
        /// </summary>
        private static void CreateSomeCreatures()
        {
            const int NUMCREATURES = 50;

            Creature = new Organism[NUMCREATURES];

            string[] genotype = {
                "testTail",
                "testJawRed",
            };

            // Creature 0 is guaranteed to be in front of the camera - use this alone when testing
            Creature[0] = new Organism(genotype[0], new Vector3(512.0f, 25.0f, 475.0f), new Orientation(0, 0, 0));
            Creature[1] = new Organism(genotype[1], new Vector3(512.0f, 25.0f, 480.0f), new Orientation(0, 0, 0));

            for (int c = 2; c < NUMCREATURES; c++)
            {
                float x, z;
                do
                {
                    x = Rnd.Float(400,600);
                    z = Rnd.Float(400,600);
                } while (Terrain.AltitudeAt(x, z) > Water.WATERLEVEL - 10);

                Vector3 loc = new Vector3(
                    x,
                    Rnd.Float(Terrain.AltitudeAt(x, z) + 5, Water.WATERLEVEL - 5),
                    z
                    );
                Orientation or = new Orientation(Rnd.Float(3.14f), Rnd.Float(3.14f), Rnd.Float(3.14f));
                int genome = Rnd.Int(genotype.Length - 1);
                Creature[c] = new Organism(genotype[genome], loc, or);
            }
        }
Example #6
0
        // Helper for GetObjectsWithinRange()
        // Run through each object in the given quad, keeping only those that are within the radius
        // and are of the right type(s). Optionally also filter those not in direct line of sight.
        private static void GetObjectsFromQuad(Map map, List<IDetectable> result, Vector3 loc, float radius, 
            bool includeOrganisms, bool includeTerrain,
            bool lineOfSightOnly, Organism ignoreMe)
        {
            // Organisms...
            if (includeOrganisms==true)
            {
                foreach (Renderable obj in map.OrganismList)
                {
                    if (obj != ignoreMe)														// don't include the owner of the sensor!
                    {
                        float radii = obj.AbsSphere.Radius + radius;
                        if (Vector3.LengthSq(loc - obj.AbsSphere.Centre) <= (radii * radii))	// include it if spheres intersect
                        {
                            if (lineOfSightOnly == true)										// and optionally if unobstructed by terrain etc.
                            {
                                if ((Terrain.InLineOfSight(loc, obj.AbsSphere.Centre))
                                    && (!result.Contains((IDetectable)obj)))                    // Object may be in several quads, so only add if unique
                                        result.Add((IDetectable)obj);
                            }
                            else
                            {
                                if (!result.Contains((IDetectable)obj))                         // Object may be in several quads, so only add if unique
                                    result.Add((IDetectable)obj);
                            }
                        }
                    }
                }
            }

            // Tiles...
            if (includeTerrain==true)
            {
                foreach (Renderable obj in map.TerrainList)
                {
                    float radii = obj.AbsSphere.Radius + radius;
                    if (Vector3.LengthSq(loc - obj.AbsSphere.Centre) <= (radii * radii))	// include it if obj sphere intersects tile SPHERE
                    {
                        if (lineOfSightOnly==true)
                        {
                            if (Terrain.InLineOfSight(loc, obj.AbsSphere.Centre))
                                result.Add((IDetectable)obj);
                        }
                        else
                        {
                            if (!result.Contains((IDetectable)obj))                         // Object may be in several quads, so only add if unique
                                result.Add((IDetectable)obj);
                        }
                    }
                }
            }
        }
Example #7
0
        /// <summary>
        /// Return a list of all the IDetectable objects within a given radius of a point
        /// (for sensors). IDetectable objects include Organisms and tiles but not scenery.
        /// Only return objects of the specified class(es). Optionally perform a line-of-sight
        /// test on the candidates too.
        /// </summary>
        /// <param name="loc">location of sensor</param>
        /// <param name="radius">range of sensor</param>
        /// <param name="includeOrganisms">Set true to include organisms in the list</param>
        /// <param name="includeTerrain">Set true to include tiles in the list</param>
        /// <param name="lineOfSightOnly">Set true to exclude objects obscured by terrain.</param>
        /// <param name="ignoreMe">The Organism object issuing the call (or null) - obviously we don't want to detect ourselves!</param>
        /// <returns>A list of IDetectable objects</returns>
        public static List<IDetectable> GetObjectsWithinRange(Vector3 loc, float radius, 
            bool includeOrganisms, bool includeTerrain,
            bool lineOfSightOnly, Organism ignoreMe)
        {
            // Create a list to store the winners in
            List<IDetectable> result = new List<IDetectable>();

            // Run down the cell hierarchy, following only the thread that contains the given location,
            // Until we reach a depth at which the given range exceeds the boundary of the quad.
            // Back up one level. We now have the smallest quad that completely encloses the circle under consideration...

            // First, clip the circle to the edges of the map, otherwise no quad will be fully within circle
            float minx = loc.X-radius;
            if (minx<0) minx=0;
            float maxx = loc.X+radius;
            if (maxx>MapWidth) maxx=MapWidth;
            float minz = loc.Z-radius;
            if (minz<0) minz=0;
            float maxz = loc.Z+radius;
            if (maxz>MapHeight) maxz=MapHeight;
            // then walk the hierarchy
            Map map = root.RecursiveFindSmallestContainer(minx, maxx, minz, maxz);

            // normally we can just search the one quad
            if (map.level!=0)
            {
                GetObjectsFromQuad(map, result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
            }
            // BUT, for a sensor close to the mid-point of the map, the quad to search will be the WHOLE map!!!
            // This is sufficiently wasteful that it's worth treating as a special case (reduces workload by factor of 4)...
            else
            {
                if ((map.child[0].child[2].bounds.Right >= maxx)
                    &&(map.child[1].child[3].bounds.Y <= minz)
                    &&(map.child[2].child[0].bounds.X <= minx)
                    &&(map.child[3].child[1].bounds.Bottom >= maxz))
                {
                    // only scan the grandchildren that surround the mid-point
                    GetObjectsFromQuad(map.child[0].child[2], result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
                    GetObjectsFromQuad(map.child[1].child[3], result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
                    GetObjectsFromQuad(map.child[2].child[0], result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
                    GetObjectsFromQuad(map.child[3].child[1], result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
                }
                else
                {
                    // here if there was some other reason for having to scan the whole map - e.g. very large range effectors
                    GetObjectsFromQuad(map.child[0].child[2], result, loc, radius, includeOrganisms, includeTerrain, lineOfSightOnly, ignoreMe);
                }
            }
            return result;
        }