Example #1
0
        /// <summary>
        /// Use a value in the range 0 to 1.0 to interpolate between min and max rotation, translation and/or scale,
        /// then apply this transformation to the given frame's transformation matrix to animate the frame.
        /// Record the amount of the change for calculating reaction forces
        /// NOTE: Rotation range must be less than 180 degrees, or the slerp will interpolate through the shortest distance,
        /// which is the opposite way to the one intended.
        /// </summary>
        /// <param name="frame">The frame to animate</param>
        /// <param name="amount">A value from 0 (min) to 1.0 (max)</param>
        public void Transform(JointFrame frame, float amount)
        {
            Quaternion Rotation = Quaternion.Identity;
            Vector3 Translation = Vector3.Empty;
            Vector3 Scale = Vector3.Empty;

            // Cap the value into range
            if (amount>1.0f)
                amount = 1.0f;
            else if (amount < 0)
                amount = 0;

            // Record the translation and rotation values before the change, for calculating relative mvt later
            Vector3 oldTrans = Translation;
            Quaternion oldRot = Rotation;

            // Interpolate Translation & store
            Translation = (TranslationMax - TranslationMin) * amount + TranslationMin;

            // Interpolate scale & store
            //Scale = (ScaleMax - ScaleMin) * amount + new Vector3(1,1,1);
            Scale = (ScaleMax - ScaleMin) * amount + ScaleMin;

            // Interpolate rotation & store
            Rotation = Quaternion.Slerp(RotationMin,RotationMax,amount);
            Rotation.Invert();

            // Do the transform
            frame.TransformationMatrix = Matrix.Scaling(Scale)
                * Matrix.RotationQuaternion(Rotation)
                * Matrix.Translation(Translation);
        }
Example #2
0
 /// <summary>
 /// Find the frame in this hierarchy with this BASE name
 /// E.g. if name = "JointHead", the first frame called "JointHead*" will be returned.
 /// This copes with the fact that TrueSpace and presumably other packages add a number to
 /// the end of frame names. So if I call a mesh "Eric", Eric's frame will be called "Eric-0"
 /// or some other number, depending on when it was created.
 /// In a skinned mesh the bones are called Bone-# by default. MUST rename them to prevent them all having
 /// a base name of "Bone"!
 /// This method is to allow a frame to be found (e.g. a joint) using a standardised name, e.g. from
 /// a Cell's X file.
 /// </summary>
 /// <param name="root">the root to start searching from</param>
 /// <param name="basename">the ROOT name of the frame</param>
 /// <returns>the frame of that name, or null if not found</returns>
 public static JointFrame FindBaseName(JointFrame root, string basename)
 {
     // convert string to a valid base name if necessary, then recurse through the hierarchy
     return RecursiveFindBaseName(root, BaseName(basename));
 }
Example #3
0
 /// <summary>
 /// Read a transformation matrix and attach to the current frame
 /// </summary>
 /// <param name="node"></param>
 /// <param name="depth"></param>
 /// <param name="thisFrame"></param>
 private static void LoadTransformationMatrix(XFileData node, int depth, JointFrame thisFrame)
 {
     try
     {
     //				Debug.WriteLine(Depth(depth) + "Creating Matrix for "+thisFrame.Name);
         GraphicsStream stream = node.Lock();							// access the data stream
         thisFrame.TransformationMatrix = MatrixFromXFile(stream);		// read in the matrix
         node.Unlock();
     }
     catch (Exception e)
     {
         Debug.WriteLine("Error reading transformation matrix: "+e.ToString());
         throw;
     }
 }
Example #4
0
        /// <summary>
        /// Read an AnimationKey node and load its transformation into the given frame
        /// </summary>
        /// <param name="node"></param>
        /// <param name="frame"></param>
        private static void LoadKeyframes(XFileData node, JointFrame frame)
        {
            int keyType = 0, keyFrames = 0;
            int keyTime = 0, keyValues = 0;
            Quaternion q = new Quaternion();
            Vector3 v = new Vector3();

            GraphicsStream stream = node.Lock();							// Lock the node and obtain a stream
            keyType = (int)stream.Read(keyType.GetType());					// get the keyframe type (rotation, etc.)
            keyFrames = (int)stream.Read(keyFrames.GetType());				// get the number of keyframes (should be 2)
            if (keyFrames>2) throw new Exception("XFile "+filespec+" should have only two keyframes per animation");

            for (int i=0; i<keyFrames; i++)
            {
                keyTime = (int)stream.Read(keyTime.GetType());					// time of key (ignored)
                keyValues = (int)stream.Read(keyValues.GetType());				// number of values in key (ignored)

                switch (keyType)
                {
                        // Rotation
                    case 0:
                        q = ReadQuaternion(stream);								// get the transformation
                        if (rmin == false)										// store it in min or max
                        {
                            motion.RotationMin = q;								// (min first, then max if min is full)
                            motion.RotationMax = q;								// (fill max too in case no 2nd key)
                            rmin = true;
                        }
                        else
                            motion.RotationMax = q;
                        break;

                        // Translation
                    case 1:
                        v = ReadVector(stream);
                        if (smin == false)
                        {
                            motion.ScaleMin = v;
                            motion.ScaleMax = v;
                            smin = true;
                        }
                        else
                            motion.ScaleMax = v;
                        break;
                        // Scale
                    case 2:
                        v = ReadVector(stream);
                        if (tmin == false)
                        {
                            motion.TranslationMin = v;
                            motion.TranslationMax = v;
                            tmin = true;
                        }
                        else
                            motion.TranslationMax = v;
                        break;

                }
            }

            node.Unlock();														// release the node
        }
Example #5
0
 /// <summary>
 /// Overload of Attach() to attach a cell to its parent given the actual attachment socket, rather than its name
 /// </summary>
 /// <param name="parent">the Cell to which I'm connected</param>
 /// <param name="skt">the actual socket to which I'm attached</param>
 public void Attach(Cell parent, JointFrame skt)
 {
     parentSocket = skt;
     this.parent = parent;
 }
Example #6
0
 /// <summary>
 /// Set the visibility level of all meshes of a given type ("SKT", "EFF", etc.)
 /// for ALL cells in the system
 /// </summary>
 /// <param name="meshname">root part of the FRAME name used to designate a part as being an effector/socket/etc</param>
 /// <param name="vis">true to make parts of this type visible</param>
 public static void SetVisibility(JointFrame.FrameType type, bool vis)
 {
     for (int i=0; i<Cell.library.Count; i++)							// apply to every cell in the library
     {
         Cell c = (Cell)library.Values[i];
         c.RecursiveSetVisibility(c.rootFrame, type, vis);
     }
 }
Example #7
0
        /// <summary>
        /// Recursively draw the local chemical concentration (in channels with the right affinity)
        /// For the Core cell, show the global chemical concs in the func0 to func5 organelles
        /// </summary>
        /// <param name="frame">frame to draw</param>
        /// <param name="lod">level of detail</param>
        private void RecursiveDrawScannerMode(JointFrame frame, float lod)
        {
            int chem = 0;
            float brightness = 0;
            Color col = Color.White;

            try
            {

                // Render this frame's mesh
                Cytoplasm cytoplasm = (Cytoplasm)frame.MeshContainer;							// get first Cytoplasm mesh in this frame
                while (cytoplasm != null)														// for each mesh...
                {
                    switch (frame.Type)
                    {
                        // If this is a channel, render it in a colour determined by its chemical preference
                        // and concentration
                        case JointFrame.FrameType.Channel:
                            chem = channel[frame.Index].chemical;		    				// the chemical number for this channel
                            col = Chemistry.Colour[chem];		    						// the base colour of that chemical
                            brightness = GetChannel(frame.Index);	        				// modulate by signal in that channel
                            if (brightness == 0) brightness = 0.01f;						// can't use black, or we'll render using texture
                            Debug.Assert(brightness >= 0f, "Chemical conc in cell " + fullname + " channel " + frame.Index + " is < 0");
                            Debug.Assert(brightness <= 1.0f, "Chemical conc in cell " + fullname + " channel " + frame.Index + " is > 1");
                            col = Color.FromArgb((int)(col.R * brightness),
                                              (int)(col.G * brightness),
                                              (int)(col.B * brightness));		    		// adjust intensity
                            cytoplasm.Render(frame, lod, col, col);
                            break;

                        // If this is a functional block, render it in yellow
                        // UNLESS this is the Core cell, in which case we should colour its six func# meshes
                        // to show the levels of the global chemicals
                        case JointFrame.FrameType.Function:
                            if (name == "Core")
                            {
                                chem = frame.Index + Chemistry.NUMSIGNALS;		    			// the global chemical number for this func block
                                col = Chemistry.Colour[chem];	    							// the base colour of that chemical
                                brightness = owner.chemistry.Read(chem);	        		    // modulate by signal in that channel
                                if (brightness == 0) brightness = 0.01f;						// can't use black, or we'll render using texture
                                col = Color.FromArgb((int)(col.R * brightness),
                                                  (int)(col.G * brightness),
                                                  (int)(col.B * brightness));					// adjust intensity
                                cytoplasm.Render(frame, lod, col, col);
                            }
                            // For non-Core cells, render the functional blocks in yellow
                            else
                            {
                                cytoplasm.Render(frame, lod, Color.Yellow, Color.Yellow);
                            }
                            break;

                        // Cell membrane is rendered in wireframe, so that we can see organelles
                        case JointFrame.FrameType.General:
                        case JointFrame.FrameType.Animating:
                            Engine.Device.RenderState.FillMode = FillMode.WireFrame;
                            cytoplasm.Render(frame, lod, Color.Gray, Color.Gray);
                            Engine.Device.RenderState.FillMode = FillMode.Solid;
                            break;
                    }

                    // and repeat for any other meshes in frame
                    cytoplasm = (Cytoplasm)cytoplasm.NextContainer;
                }
            }
            catch (Exception e)
            {
                throw new SDKException("Error: Unable to render chemical concentrations for celltype " + fullname + " chemical# " + chem + " concentration " + brightness,e);
            }

            // Render any siblings
            if (frame.Sibling != null)
            {
                RecursiveDrawScannerMode(frame.Sibling, lod);
            }

            // Render children and their siblings
            if (frame.FirstChild != null)
            {
                RecursiveDrawScannerMode(frame.FirstChild, lod);
            }
        }
Example #8
0
        /// <summary>
        /// Recursively draw in channel-edit mode
        /// </summary>
        /// <param name="frame"></param>
        /// <param name="lod"></param>
        /// <param name="style"></param>
        private void RecursiveDrawChannelMode(JointFrame frame, float lod, Cytoplasm.DesignStyle style)
        {
            try
            {
                // Render this frame's mesh
                Cytoplasm cytoplasm = (Cytoplasm)frame.MeshContainer;							// get first Cytoplasm mesh in this frame
                while (cytoplasm != null)														// for each mesh...
                {
                    switch (frame.Type)
                    {
                        // If this is a socket, render it in a colour determined by whether it is selected or not
                        case JointFrame.FrameType.Socket:
                            if (frame == Lab.SelectedSocket)
                                cytoplasm.Render(frame, lod, Color.Red, Color.Red);				// selected socket
                            else if (style != Cytoplasm.DesignStyle.Other)
                                cytoplasm.Render(frame, lod, Color.White, Color.White);			// unselected sockets on selected organism
                            break;

                        // If this is a channel, render it in a colour determined by its chemical preference
                        // And flash it if it is being edited
                        case JointFrame.FrameType.Channel:

                            int chem = channel[frame.Index].chemical;							// the chemical number for this channel
                            Color c = Chemistry.Colour[chem];									// the colour of that chemical
                            if ((this == Lab.SelectedCell) && (Lab.SelectedChannel == frame.Index))	// if we are the channel selected for editing
                            {
                                float time = Scene.TotalElapsedTime % 0.3f;						// get current fraction of a second
                                if (time > 0.15f)												// flash 1:1
                                {
                                    //c = Color.DarkGray;
                                    c = Color.FromArgb(c.R / 3, c.G / 3, c.B / 3);				// flash between bright and dark versions
                                }
                            }
                            cytoplasm.Render(frame, lod, Color.FromArgb(1,1,1), c);             // Use only emissive for clarity. Diffuse is dark (mustn't be black - means ignore)
                            break;

                        // If this is a functional block, render it in yellow
                        case JointFrame.FrameType.Function:
                            cytoplasm.Render(frame, lod, Color.Yellow, Color.Yellow);
                            break;

                        // Cell membrane is rendered in wireframe on a selected creature, so that we can see organelles
                        case JointFrame.FrameType.General:
                        case JointFrame.FrameType.Animating:
                            Engine.Device.RenderState.FillMode = FillMode.WireFrame;
                            if (style == Cytoplasm.DesignStyle.Selected)
                                cytoplasm.Render(frame, lod, Color.DarkRed, Color.DarkRed);
                            else
                                cytoplasm.Render(frame, lod, Color.DarkGreen, Color.DarkGreen);
                            Engine.Device.RenderState.FillMode = FillMode.Solid;
                            break;
                    }

                    // and repeat for any other meshes in frame
                    cytoplasm = (Cytoplasm)cytoplasm.NextContainer;
                }
            }
            catch (Exception e)
            {
                throw new SDKException("ERROR: Unable to draw organelle " + frame.Name + " in cell " + name, e);
            }

            // Render any siblings
            if (frame.Sibling != null)
            {
                RecursiveDrawChannelMode(frame.Sibling, lod, style);
            }

            // Render children and their siblings
            if (frame.FirstChild != null)
            {
                RecursiveDrawChannelMode(frame.FirstChild, lod, style);
            }
        }
Example #9
0
        /// <summary>
        /// Render the contents of this object's mesh in DESIGN mode
        /// in which the material depends on the status of the cell (selected, part of selected org, etc.).
        /// Hotspots are also rendered differently depending on whether they are selected, part of the selected cell, etc.
        /// </summary>
        /// <param name="frame">the frame of reference</param>
        /// <param name="lod">level of detail (as dist from camera), for progressive meshes</param>
        /// <param name="diffuse">Overridden colour for mesh, or Color.Black to use the mesh's own colour</param>
        /// <param name="emissive">Overridden emissive colour for mesh</param>
        public void Render(JointFrame frame, float lod, Color diffuse, Color emissive)
        {
            // If the natural mesh colour is being overridden, set up a material of the given colour
            if (diffuse != Color.Black)
            {
                Material mat = new Material();
                mat.Ambient = Color.Black;
                mat.Diffuse = diffuse;
                mat.Emissive = emissive;
                mat.Specular = Color.Black;
                Fx.SetMaterial(mat);
            }

            // set the LOD for the progressive mesh using the dist from camera to obj
            // (calculated in Map.RenderQuad())
            const float MAXDIST = 180.0f;				// use min LOD beyond this dist
            const float MINDIST = 40.0f;				// use max LOD nearer than this
            if (lod > MAXDIST)							// TODO: USE LARGE ENOUGH DIST TO ENSURE LAB IS FULLY RENDERED!!!!
                MeshData.ProgressiveMesh.NumberFaces = MeshData.ProgressiveMesh.MinFaces;
            else
            {
                int faces = (int)((float)MeshData.ProgressiveMesh.MaxFaces *
                            (1 - ((lod - MINDIST) / (MAXDIST - MINDIST))));
                MeshData.ProgressiveMesh.NumberFaces = faces;
                /////Engine.DebugHUD.WriteLine(faces.ToString());
            }

            // Set up the world matrix
            Fx.SetWorldMatrix(frame.CombinedMatrix);

            // Render the subsets
            for (int i = 0; i < materials.Length; i++)
            {
                // If this is a selected cell or an unselected cell on the selected org, we already
                // have a special material set up. Otherwise, we should use the mesh subset's own material
                // so the object is rendered normally
                if (diffuse == Color.Black)
                {
                    Fx.SetMaterial(materials[i]);
                }

                // Use mesh's texture
                Fx.SetTexture(textures[i]);

                Fx.DrawMeshSubset(MeshData.ProgressiveMesh, i);
            }
        }
Example #10
0
        /// <summary>
        /// Render the contents of this object's mesh in NORMAL textured mode
        /// </summary>
        /// <param name="frame">the frame of reference</param>
        /// <param name="lod">level of detail (as dist from camera), for progressive meshes</param>
        public void Render(JointFrame frame, float lod)
        {
            // This class of mesh may not currently be visible
            if (Visible == false)
                return;

            // set the LOD for the progressive mesh using the dist from camera to obj
            // (calculated in Map.RenderQuad())
            const float MAXDIST = 180.0f;				// use min LOD beyond this dist
            const float MINDIST = 15.0f;					// use max LOD nearer than this
            if (lod > MAXDIST)
                MeshData.ProgressiveMesh.NumberFaces = MeshData.ProgressiveMesh.MinFaces;
            else
            {
                int faces = (int)((float)MeshData.ProgressiveMesh.MaxFaces *
                            (1 - ((lod - MINDIST) / (MAXDIST - MINDIST))));
                MeshData.ProgressiveMesh.NumberFaces = faces;
                /////Engine.DebugHUD.WriteLine(faces.ToString());
            }

            // Set up the world matrix
            Fx.SetWorldMatrix(frame.CombinedMatrix);

            // Render the subsets
            for (int i = 0; i < materials.Length; i++)
            {
                Fx.SetMaterial(materials[i]);
                Fx.SetTexture(textures[i], bumps[i]);
                Fx.DrawMeshSubset(MeshData.ProgressiveMesh, i);
            }
        }
Example #11
0
        /// <summary>
        /// Helper for Cell.HitTest(). Test to see whether these two meshes currently intersect.
        /// Method: If all points on one OBB lie in front of any of the planes marking the faces of the other,
        /// then the two boxes don't overlap.
        /// </summary>
        /// <param name="ourFrame">The frame containing one mesh</param>
        /// <param name="hisFrame">Same data for other mesh</param>
        /// <returns>True if there will be a collision</returns>
        public static bool CollisionTest(JointFrame ourFrame, JointFrame hisFrame)
        {
            // Get the transformed corners for each mesh
            Vector3[] ourCorners = ((Cytoplasm)ourFrame.MeshContainer).GetTransformedOBB(ourFrame.CombinedMatrix);
            Vector3[] hisCorners = ((Cytoplasm)hisFrame.MeshContainer).GetTransformedOBB(hisFrame.CombinedMatrix);

            // Test our points against his planes. If we definitely don't intersect, return false
            if (CollisionTest2(ourCorners, hisCorners) == false)
                return false;
            // If we're still here, the boxes still might intersect, so test his points against our planes
            return CollisionTest2(hisCorners, ourCorners);
        }
Example #12
0
        /// <summary>
        /// Helper for mouse selection of 3D objects. Given a "finger" pointing into the screen,
        /// return the Cell that the finger points to (or null if no such cell).
        /// Called by Camera.MousePick()
        /// </summary>
        /// <param name="rayPosition">position of ray on screen</param>
        /// <param name="rayDirection">vector pointing into screen</param>
        /// <param name="socket">If a SOCKET on the cell was selected, its frame is returned here</param>
        /// <returns>the Cell that the finger points to (or null)</returns>
        public static Cell MousePick(Vector3 rayPosition, Vector3 rayDirection, out JointFrame socket)
        {
            float bestDist = float.MaxValue;
            Cell bestCell = null;
            socket = null;

            // For every organism on the map
            foreach (Organism org in root.organismList)
            {
                // Skip if this is the camera ship - we're inside that so we'd be certain to click on it!
                if (org == (Organism)CameraShip.CurrentShip)
                    continue;

                // if finger points somewhere within bounds of this organism
                if (Geometry.SphereBoundProbe(org.AbsSphere.Centre, org.AbsSphere.Radius, rayPosition, rayDirection))
                {
                    // Ask the organism to check its cells
                    Cell cell = org.MousePick(rayPosition, rayDirection, out socket);
                    // if the ray intersects this cell and it is closer than any previous cell, store it
                    if (cell != null)
                    {
                        float dist = Vector3.Length(cell.AbsSphere.Centre - Camera.Position);
                        if (dist < bestDist)
                            bestCell = cell;
                    }
                }
            }
            // return best candidate cell or null if none found
            return bestCell;
        }
Example #13
0
 /// <summary>
 /// Recursive part of FindBaseName()
 /// </summary>
 /// <param name="root"></param>
 /// <param name="basename"></param>
 /// <returns></returns>
 private static JointFrame RecursiveFindBaseName(JointFrame root, string basename)
 {
     // get the current frame's base name. If we match then return
     if (root.Name!=null)
     {
         string rootbase = BaseName(root.Name);
         if (rootbase == basename)
             return root;
     }
     // else continue with rest of hierarchy
     if (root.Sibling!=null)
     {
         JointFrame result = RecursiveFindBaseName(root.Sibling,basename);
         if (result!=null)
             return result;
     }
     if (root.FirstChild!=null)
     {
         JointFrame result = RecursiveFindBaseName(root.FirstChild,basename);
         if (result!=null)
             return result;
     }
     return null;
 }
Example #14
0
 private static void RecurseFrameType(FrameType type, JointFrame[] array, JointFrame frame)
 {
     if (frame.type==type)												// if frame is correct type
     {
         array[frame.index] = frame;										// store a ref to it in correct index
     }
     if (frame.FirstChild!=null)											// then recurse through children/siblings
         RecurseFrameType(type, array, frame.FirstChild);
     if (frame.Sibling!=null)
         RecurseFrameType(type, array, frame.Sibling);
 }
Example #15
0
        /// <summary>
        /// Search the given frame hierarchy for all frames of a given type (sockets, effectors, etc.).
        /// Return an array containing references to these frames, sorted in order, so that
        /// "skt0" is in array[0], etc. Used to give cells rapid access to their joints and effectors 
        /// for physics & animation. 
        /// Note: array will be no larger than is needed to contain all the named frames. Array may be of zero size but will never be null.
        /// If any indices are missing (e.g. anim0 and anim2 exist but not anim1) then the unused array entries will be null
        /// and a trace warning will be emitted.
        /// </summary>
        /// <param name="root">The root frame for the hierarchy</param>
        /// <param name="type">The type of frame to return</param>
        /// <returns>The array of JointFrames</returns>
        public static JointFrame[] IndexFrameType(JointFrame root, FrameType type)
        {
            int num = 0;
            JointFrame[] array = new JointFrame[50];							// A big enough array
            RecurseFrameType(type, array, root);								// fill the elements

            for (num=array.Length; (num>0)&&(array[num-1]==null); num--);		// find out how many entries were filled
            JointFrame[] array2 = new JointFrame[num];							// copy elements into a correctly-sized array
            Array.Copy(array,0,array2,0,num);									// (Possibly zero-length)
            for (int i=0; i<num; i++)											// scan the array for any missing elements and
            {																	// emit a trace warning - cell designer might have
                if (array2[i]==null)											// made a mistake!
                {
                    Trace.WriteLine("WARNING: Unable to find a frame of type "+type.ToString()+" with index "+i);
                }
            }
            return array2;														// any unused entries will be null
        }
Example #16
0
        /// <summary>
        /// Draw a frame and all its child and sibling frames in NORMAL display mode
        /// </summary>
        /// <param name="frame">Frame to draw</param>
        /// <param name="lod"> dist from camera </param>
        private void RecursiveDraw(JointFrame frame, float lod)
        {
            // Render this frame's mesh
            Cytoplasm cytoplasm = (Cytoplasm)frame.MeshContainer;							// get first Cytoplasm mesh in this frame
            while(cytoplasm != null)
            {
                // if this frame has colour animation, copy the instanced material from the frame to the cytoplasm
                if (frame.animColour != null)
                    cytoplasm.materials = frame.animColour;

                cytoplasm.Render(frame, lod);												// draw it (textured)
                cytoplasm = (Cytoplasm)cytoplasm.NextContainer;								// and repeat for any other meshes in frame
            }

            // Render any siblings
            if (frame.Sibling != null)
            {
                RecursiveDraw(frame.Sibling,lod);
            }

            // Render children and their siblings
            if (frame.FirstChild != null)
            {
                RecursiveDraw(frame.FirstChild,lod);
            }
        }
Example #17
0
        /// <summary>
        /// Recursively draw in cell edit mode
        /// </summary>
        /// <param name="frame"></param>
        /// <param name="lod"></param>
        /// <param name="style"></param>
        private void RecursiveDrawCellMode(JointFrame frame, float lod, Cytoplasm.DesignStyle style)
        {
            // Render this frame's mesh
            Cytoplasm cytoplasm = (Cytoplasm)frame.MeshContainer;							// get first Cytoplasm mesh in this frame
            while (cytoplasm != null)														// for each mesh...
            {
                switch (frame.Type)
                {
                    // If this is the cell membrane, render it in a colour determined by whether it is selected or not
                    case JointFrame.FrameType.General:
                    case JointFrame.FrameType.Animating:
                        if (style == Cytoplasm.DesignStyle.Selected)
                            cytoplasm.Render(frame, lod, Color.Blue, Color.Black);
                        else
                            cytoplasm.Render(frame, lod, Color.White, Color.Black);
                        break;

                    // If this is a socket, render it in a colour determined by whether it is selected or not
                    case JointFrame.FrameType.Socket:
                        if (frame == Lab.SelectedSocket)
                            cytoplasm.Render(frame, lod, Color.Red, Color.Red);
                        else
                            cytoplasm.Render(frame, lod, Color.White, Color.White);
                        break;

                    // All other parts are unrendered
                }

                // and repeat for any other meshes in frame
                cytoplasm = (Cytoplasm)cytoplasm.NextContainer;
            }

            // Render any siblings
            if (frame.Sibling != null)
            {
                RecursiveDrawCellMode(frame.Sibling, lod, style);
            }

            // Render children and their siblings
            if (frame.FirstChild != null)
            {
                RecursiveDrawCellMode(frame.FirstChild, lod, style);
            }
        }
Example #18
0
        /// <summary>
        /// Given a mouse click, find the cell that has been clicked on
        /// </summary>
        /// <param name="screenX">the mouse cursor position when the click occurred</param>
        /// <param name="screenY"></param>
        /// <param name="socket">If a SOCKET on the cell was selected, its frame is returned here</param>
        /// <returns>The picked cell, or null if no cell at that point</returns>
        public static Cell MousePick(float screenX, float screenY, out JointFrame socket)
        {
            // Step 1: Convert the mouse position into an eyepoint in 3D
            Vector3 v = new Vector3();
            screenX -= Camera.SceneViewport.X;                                                                          // remove offset of viewport
            screenY -= Camera.SceneViewport.Y;
            v.X = (((2.0f * screenX) / Camera.SceneViewport.Width) - 1) / projMatrix.M11;
            v.Y = -(((2.0f * screenY) / Camera.SceneViewport.Height) - 1) / projMatrix.M22;
            v.Z = 1.0f;

            // Step 2: Create a ray emanating from the mouse cursor in the direction of the camera
            Matrix m = viewMatrix;
            m.Invert();
            Vector3 rayDirection = new Vector3(
                                v.X * m.M11 + v.Y * m.M21 + v.Z * m.M31,
                                v.X * m.M12 + v.Y * m.M22 + v.Z * m.M32,
                                v.X * m.M13 + v.Y * m.M23 + v.Z * m.M33);

            Vector3 rayPosition = new Vector3(m.M41, m.M42, m.M43);

            // Step 3: Iterate through the orgs and cells to find the nearest one to the camera that our ray intersects
            return Map.MousePick(rayPosition, rayDirection, out socket);
        }
Example #19
0
        /// <summary>
        /// Construct a new Cell FOR USE IN THE LIBRARY as an archetype
        /// - Use Get() to get instances for actual animation and rendering
        /// </summary>
        /// <param name="name">name of Cell type, in the form "DLLname:celltype.variant" (where .variant is optional)</param>
        private Cell(string fullname)
        {
            // Store the full name so that we can identify our archetype in the library (to remove it when all instances have been disposed)
            this.fullname = fullname;

            // Parse the group:name.variant into group, name & variant
            int colon = fullname.IndexOf(":");							            // if the celltype has no : it is in the default DLL
            if (colon >= 0)
            {
                group = fullname.Substring(0, colon);				  			    // the first part is the DLL assembly name
                name = fullname.Substring(colon + 1);	        	    		    // the second is the class name, plus possible variant
            }
            else
            {
                group = "CellTypes";
                name = fullname;
            }
            int dot = name.IndexOf(".");                                            // find start of any variant
            if (dot >= 0)                                                           // If the name ends in a variant
            {
                variantName = name;
                name = name.Substring(0, dot);                                      // remove it from name
                variantName = variantName.Substring(dot+1);                         // and store it in variant
            }
            else
            {
                variantName = "default";                                            // if no variant specified, use "default.x"
            }

            // Load the frame hierarchy from disk
            rootFrame = CellLoader.Load(group, name, variantName);

            // Compute the overall bounding sphere for the cell, now that the frame hierarchy and meshes exist
            ComputeBoundingSphere();

            // Compute an approximate colour for this cell, for use in optical sensors
            ComputeColour();

            // Add this Cell to the library (key is complete dll.type name)
            library.Add(fullname, this);
        }
Example #20
0
        /// <summary>
        /// Helper for mouse selection of 3D objects. Given a "finger" pointing into the screen,
        /// return the Cell that the finger points to (or null if no such cell).
        /// Also, if the finger is pointing specifically to a SOCKET on that cell, return the socket's frame in the
        /// socket variable
        /// Called by Map.MousePick()
        /// </summary>
        /// <param name="rayPosition">position of ray on screen</param>
        /// <param name="rayDirection">vector pointing into screen</param>
        /// <param name="socket">If a SOCKET on the cell was selected, its frame is returned here</param>
        /// <returns>the nearest selected cell or null</returns>
        public Cell MousePick(Vector3 rayPosition, Vector3 rayDirection, out JointFrame socket)
        {
            float bestDist = float.MaxValue;
            Cell bestCell = null;
            JointFrame bestFrame = null;

            foreach (Cell cell in partList)
            {
                // Unproject the ray and test against every triangle of every mesh
                // in the cell. The cost of this is that I have to retain the original Mesh for each Cytoplasm object, since
                // its ProgressiveMesh doesn't have an .Intersect() method.
                // Return the one (if any) closest to the camera
                JointFrame result = cell.MousePick(rayPosition, rayDirection);
                if (result != null)
                {
                    float dist = Vector3.Length(cell.AbsSphere.Centre - Camera.Position);
                    if (dist < bestDist)
                    {
                        bestCell = cell;
                        bestFrame = result;
                    }
                }
            }
            // If the mesh that was clicked on is a socket, pass the socket frame back to the caller
            // If it was a cell but not a socket, pass back a null, because when the cell changes
            // we must find a new socket to select
            socket = null;
            if (bestCell != null)
            {
                if (bestFrame.Type == JointFrame.FrameType.Socket)
                    socket = bestFrame;
            }

            // Return the nearest selected cell or null
            return bestCell;
        }
Example #21
0
        private void RecursiveSetVisibility(JointFrame frame, JointFrame.FrameType type, bool vis)
        {
            if (frame.Type==type)												// if we're the right type of frame
                if (frame.MeshContainer!=null)									// and there's a mesh
                    ((Cytoplasm)frame.MeshContainer).Visible = vis;				// set its visibility

            if (frame.Sibling != null)											// recurse through siblings
                RecursiveSetVisibility(frame.Sibling, type, vis);
            if (frame.FirstChild != null)										// recurse through children
                RecursiveSetVisibility(frame.FirstChild, type, vis);
        }
Example #22
0
        private void ComputeBoundingSphere(JointFrame frame, Matrix parentMatrix)
        {
            // Give the meshes their proper relative positions within the cell
            Matrix combinedMatrix = frame.TransformationMatrix * parentMatrix;

            // If this frame contains a mesh, transform its bounding sphere and
            // combine it with the overall bounds for the cell
            if (frame.MeshContainer!=null)
            {
                Cytoplasm cyt = (Cytoplasm)frame.MeshContainer;
                float radius = cyt.BoundRadius;
                Vector3 centre = cyt.BoundCentre;
                // transform the sphere's centre
                centre.TransformCoordinate(combinedMatrix);
                // Transform the sphere's radius (to scale it - the original vertices are probably not at their final scale
                Vector3 radiusVector = new Vector3(radius, 0, 0);               // create a vector of size radius
                radiusVector.TransformCoordinate(combinedMatrix);               // transform it to rescale it
                radius = radiusVector.Length();                                 // scaled radius is the length of the transformed vector
                // Combine this sphere with the others in the cell
                RelSphere.CombineBounds(centre, radius);
            }

            // Now propagate the new combined matrix through to my siblings and children
            if (frame.Sibling != null)											// recurse through siblings
            {
                ComputeBoundingSphere(frame.Sibling, parentMatrix);
            }
            if (frame.FirstChild != null)										// recurse through children
            {
                ComputeBoundingSphere(frame.FirstChild, combinedMatrix);
            }
        }
Example #23
0
 /// <summary>
 /// The absolute location/orientation of this Cell is determined by its SOCKET on the parent Cell.
 /// This method locates the frame in the parent with the given (genetically defined) name
 /// and stores a reference to it in .socket
 /// Also stores a reference to the parent cell, to make it easier to walk up the tree
 /// </summary>
 /// <param name="parent">the Cell to which I'm connected</param>
 /// <param name="skt">the name of the socket to which I'm attached</param>
 public void Attach(Cell parent, string sktname)
 {
     try
     {
         parentSocket = JointFrame.FindBaseName(parent.RootFrame, sktname);
         this.parent = parent;
     }
     catch { }
     if (parentSocket == null)
     {
         throw new SDKException("Cell.FindSocket() was unable to connect cell [" + this.name + "] to parent socket [" + parent.name + "-" + sktname + "]");
     }
     //			Debug.WriteLine("	Connected cell ["+this.name+"] to parent socket ["+parent.name+"-"+sktname+"]");
 }
Example #24
0
 /// <summary>
 /// Recursively convert the frame hierarchy into a flat list of frames for 
 /// easier or more powerful searching, e.g. during 3D picking.
 /// </summary>
 /// <param name="list"></param>
 /// <returns></returns>
 private List<JointFrame> FlattenFrames(JointFrame frame, List<JointFrame> list)
 {
     list.Add(frame);
     if (frame.Sibling!=null)
         FlattenFrames(frame.Sibling, list);
     if (frame.FirstChild!=null)
         FlattenFrames(frame.FirstChild, list);
     return list;
 }
Example #25
0
        /// <summary>
        /// Recursively process frame node(s) and their subnodes from an XFileData object
        /// </summary>
        /// <param name="node"></param>
        /// <param name="depth"></param>
        /// <param name="parentFrame"></param>
        private static void LoadFrame(XFileData node, int depth, JointFrame parentFrame)
        {
            JointFrame newFrame = new JointFrame(node.Name);				// Create a new frame
            //			Debug.Write(Depth(depth) + "Creating frame "+newFrame.Name+" ("+newFrame.Type.ToString()+":"+newFrame.Index+") ");
            if (parentFrame==null)											// if there's no parent frame
            {																// the new frame is the root
            //				Debug.WriteLine("as root");
                rootFrame = newFrame;
            }
            else if (parentFrame.FirstChild==null)							// or, if we're the first child
            {
            //				Debug.WriteLine("as child of "+parentFrame.Name);
                parentFrame.FirstChild = newFrame;							// attach as first child of parent
            }
            else															// else we're a sibling
            {
                JointFrame bigSister = parentFrame.FirstChild;
                while (bigSister.Sibling!=null)								// so scan to the end of this row
                    bigSister = bigSister.Sibling;
            //				Debug.WriteLine("as sibling of "+bigSister.Name);
                bigSister.Sibling = newFrame;								// attach as a sibling
            }

            // --------- Recurse through this node's children to construct frame's contents ----------
            depth++;
            for (int i=0; i<node.NumberChildren; i++)
            {
                using (XFileData child = node.GetChild(i))
                {
                    // **** Frame nested inside this frame
                    if (child.Type==XFileGuid.Frame)
                    {
                        LoadFrame(child, depth, newFrame);
                    }

                    // **** FrameTransformationMatrix
                    else if (child.Type==XFileGuid.FrameTransformMatrix)
                    {
                        LoadTransformationMatrix(child, depth, newFrame);
                    }

                    // **** Mesh
                    else if (child.Type==XFileGuid.Mesh)
                    {
                        string name = child.Name;                                       // use mesh named in xfile if available
                        if (name == "") name = node.Name;                               // or name it after the frame

                        LoadMesh(child, name, depth, newFrame);
                    }

                }
            }
        }
Example #26
0
 /// <summary>
 /// Recursively create a list of frames that contain meshes. 
 /// Useful for e.g. collision detection.
 /// </summary>
 /// <param name="frame">Current frame in the recursion</param>
 /// <param name="list">Where to store the results</param>
 /// <param name="includeSpots">False if we only want major meshes, not hotspots, sockets or channels</param>
 /// <returns></returns>
 private List<JointFrame> GetMeshFrames(JointFrame frame, List<JointFrame> list, bool includeSpots)
 {
     if (frame.MeshContainer != null)											// if we have a mesh
     {
         if ((includeSpots==true)
             ||(frame.Type==JointFrame.FrameType.General)
             ||(frame.Type==JointFrame.FrameType.Animating))						// optionally exclude hotspots & sockets
         {
             list.Add(frame);
         }
     }
     if (frame.Sibling != null)
         GetMeshFrames(frame.Sibling, list, includeSpots);
     if (frame.FirstChild != null)
         GetMeshFrames(frame.FirstChild, list, includeSpots);
     return list;
 }
Example #27
0
        /// <summary>
        /// Read a mesh and create a Cytoplasm object from it, then attach this to the current frame
        /// </summary>
        /// <param name="node"></param>
        /// <param name="depth"></param>
        /// <param name="thisFrame"></param>
        private static void LoadMesh(XFileData node, string name, int depth, JointFrame thisFrame)
        {
            //			Debug.WriteLine(Depth(depth) + "Creating Mesh "+name+" for "+thisFrame.Name);

            Mesh mesh = null;
            ExtendedMaterial[] materials = null;
            GraphicsStream adjacency = null;
            EffectInstance[] effects = null;

            try
            {
                mesh = Mesh.FromX(node,MeshFlags.Managed,Engine.Device,out adjacency, out materials, out effects);
                //Debug.WriteLine(Depth(depth) + "Mesh "+node.Name+" has "+mesh.NumberVertices+" verts and "+materials.Length+" materials");
            }
            catch (Direct3DXException e)
            {
                Debug.WriteLine("Error reading mesh: "+e.ToString());
                throw;
            }

            // Create a Cytoplasm (meshcontainer) object from mesh, materials, etc.
            // Give it the right name (node.Name)
            // Link it into the tree of Cytoplasm objects
            // Link it to this mesh
            Cytoplasm cyt = new Cytoplasm(folder,name,mesh,materials,effects,adjacency,null);
            thisFrame.MeshContainer = cyt;
        }
Example #28
0
        // Helper for above
        private bool MousePick(JointFrame frame, Vector3 rayPosition, Vector3 rayDirection)
        {
            // Skip frames that don't have meshes
            if (frame.MeshContainer == null)
                return false;

            // Unproject the ray and its normal into model space
            Matrix unproject = Matrix.Invert(frame.CombinedMatrix);
            Vector3 localPosn = Vector3.TransformCoordinate(rayPosition, unproject);
            Vector3 localDirn = Vector3.TransformNormal(rayDirection, unproject);
            localDirn.Normalize();

            // Do the intersection test
            return ((Cytoplasm)frame.MeshContainer).OriginalMesh.Intersect(localPosn, localDirn);
        }
Example #29
0
        /// <summary>
        /// Called by UpdateFrames() to recursively calculate all combined matrices.
        /// </summary>
        /// <param name="frame"></param>
        /// <param name="parentMatrix"></param>
        private void RecurseFrameMatrices(JointFrame frame, Matrix parentMatrix)
        {
            // My combined transformation matrix is computed by combining my frame orientation
            // with my parent's combined matrix
            frame.CombinedMatrix = frame.TransformationMatrix * parentMatrix;	// combine my matrix with total so far

            // Now propagate the new combined matrix through to my siblings and children
            if (frame.Sibling != null)											// recurse through siblings
            {
                RecurseFrameMatrices(frame.Sibling, parentMatrix);
            }
            if (frame.FirstChild != null)										// recurse through children
            {
                RecurseFrameMatrices(frame.FirstChild, frame.CombinedMatrix);
            }
        }
Example #30
0
 /// <summary>
 /// Find the frame in this hierarchy with this EXACT name
 /// </summary>
 /// <param name="root">the root to start searching from</param>
 /// <param name="name">the EXACT name of the frame</param>
 /// <returns>the frame of that name, or null if not found</returns>
 public static JointFrame Find(JointFrame root, string name)
 {
     // get the current frame's name. If we match then return
     if (root.Name == name)
     {
             return root;
     }
     // else continue with rest of hierarchy
     if (root.Sibling!=null)
     {
         JointFrame result = Find(root.Sibling,name);
         if (result!=null)
             return result;
     }
     if (root.FirstChild!=null)
     {
         JointFrame result = Find(root.FirstChild,name);
         if (result!=null)
             return result;
     }
     return null;
 }