Пример #1
0
 public AttachmentPoint(AttachmentPoint other)
 {
     this.name = other.name;
     this.parentBone = other.parentBone;
     this.orientation = other.orientation;
     this.position = other.position;
 }
Пример #2
0
 public AttachmentPoint(string name, string parentBone, Quaternion orientation, Vector3 position)
 {
     this.name = name;
     this.parentBone = parentBone;
     this.orientation = orientation;
     this.position = position;
 }
 /// <summary>
 ///		Constructor.
 /// </summary>
 /// <param name="name">Name of this plane.</param>
 public MovablePlane(string name)
 {
     this.name = name;
     lastTranslate = Vector3.Zero;
     lastRotate = Quaternion.Identity;
     isDirty = true;
 }
 public AddMarkerAtCameraCommand(WorldEditor app, IWorldContainer parent, string name)
 {
     this.app = app;
     this.parent = parent;
     this.name = name;
     this.pos = app.CameraPosition;
     this.orient = new Quaternion(app.CameraOrientation.w, app.CameraOrientation.x, app.CameraOrientation.y, app.CameraOrientation.z);
 }
 public AddWaypointParticleEffectCommand(Waypoint parent, WorldEditor app, string particleEffectName, float positionScale, float velocityScale, Quaternion orientation)
 {
     this.app = app;
     this.parent = parent;
     this.particleEffectName = particleEffectName;
     this.positionScale = positionScale;
     this.velocityScale = velocityScale;
     this.orientation = parent.Orientation;
 }
 public AddObjectParticleEffectCommand(StaticObject parent, WorldEditor app, string particleEffectName, float positionScale, float velocityScale, string attachmentPointName, Quaternion orientation)
 {
     this.app = app;
     this.parent = parent;
     this.particleEffectName = particleEffectName;
     this.positionScale = positionScale;
     this.velocityScale = velocityScale;
     this.attachmentPointName = attachmentPointName;
     this.orientation = orientation;
 }
Пример #7
0
 /// <summary>
 /// Creates a new Entity (should not occur on it's own)
 /// </summary>
 public Entity()
 {
     uuid = new libsecondlife.LLUUID();
     localid = 0;
     m_pos = new LLVector3();
     velocity = new LLVector3();
     rotation = new Quaternion();
     m_name = "(basic entity)";
     children = new List<Entity>();
 }
        public ParticleEffect(IWorldObject parent, WorldEditor app, string particleEffectName, float particleScale, float velocityScale, Quaternion orientation)
        {
            this.parent = parent;
            this.app = app;
            this.orientation = orientation;

            this.particleEffectName = particleEffectName;
            this.particleScale = particleScale;
            this.velocityScale = velocityScale;
        }
 public AddParticleEffectMessage()
 {
     this.MessageType = WorldMessageType.AddParticleEffect;
     orientation = Quaternion.Identity;
     velocityMultiplier = 1.0f;
     particleSizeMultiplier = 1.0f;
     particleBooleans = 0;
     color = null;
 }
 protected override void ParseMessage(IncomingMessage inMessage)
 {
     orientation = inMessage.ReadQuaternion();
 }
 protected override void ParseMessage(IncomingMessage inMessage)
 {
     base.ParseMessage(inMessage);
     name = inMessage.ReadString();
     location = inMessage.ReadIntVector();
     orientation = inMessage.ReadQuaternion();
     scale = inMessage.ReadVector();
     objectType = (ObjectNodeType)inMessage.ReadInt32();
     followTerrain = inMessage.ReadBool();
     try {
         direction = inMessage.ReadVector();
         lastInterp = inMessage.ReadTimestamp();
     } catch (System.IO.EndOfStreamException) {
         // ignore this - it means we got an old style response
     }
 }
 protected override void ParseMessage(IncomingMessage inMessage)
 {
     base.ParseMessage(inMessage);
     lightType = (LightNodeType)inMessage.ReadInt32();
     name = inMessage.ReadString();
     diffuse = inMessage.ReadColor();
     specular = inMessage.ReadColor();
     attenuationRange = inMessage.ReadSingle();
     attenuationConstant = inMessage.ReadSingle();
     attenuationLinear = inMessage.ReadSingle();
     attenuationQuadratic = inMessage.ReadSingle();
     switch (lightType) {
         case LightNodeType.Point:
             location = inMessage.ReadIntVector();
             break;
         case LightNodeType.Directional:
             orientation = inMessage.ReadQuaternion();
             break;
         case LightNodeType.Spotlight:
             location = inMessage.ReadIntVector();
             orientation = inMessage.ReadQuaternion();
             spotlightInnerAngle = inMessage.ReadSingle();
             spotlightOuterAngle = inMessage.ReadSingle();
             spotlightFalloff = inMessage.ReadSingle();
             break;
         default:
             throw new Exception("Invalid light node type: " + lightType);
     }
 }
        protected void GetCompositeTransform(ref Quaternion orientation,
											 ref Vector3 translation,
											 Bone bone, Animation anim, int keyFrameIndex)
        {
            if (bone == null)
                return;
            Quaternion tmpOrient = Quaternion.Identity;
            Vector3 tmpTranslate = Vector3.Zero;
            GetCompositeTransform(ref tmpOrient, ref tmpTranslate, (Bone)bone.Parent, anim, keyFrameIndex);
            AnimationTrack track = GetBoneTrack(anim, bone.Handle);
            KeyFrame keyFrame = track.KeyFrames[keyFrameIndex];
            orientation = tmpOrient * bone.Orientation * keyFrame.Rotation;
            translation = tmpTranslate + bone.Position + keyFrame.Translate;
        }
        /// <summary>
        ///		Creates this shader as an OGRE material.
        /// </summary>
        /// <remarks>
        ///		Creates a new material based on this shaders settings and registers it with the
        ///		SceneManager passed in. 
        ///		Material name is in the format of: shader#lightmap.
        /// </remarks>
        /// <param name="sm">SceneManager to register the material with.</param>
        /// <param name="lightmapNumber">Lightmap number</param>
        public Material CreateAsMaterial(SceneManager sm, int lightmapNumber)
        {
            string materialName = String.Format("{0}#{1}", name, lightmapNumber);
            Material material = sm.CreateMaterial(materialName);

            LogManager.Instance.Write("Using Q3 shader {0}", name);

            for(int p = 0; p < pass.Count; ++p)
            {
                TextureUnitState t;

                // Create basic texture
                t = LoadMaterialTextures(p, lightmapNumber, material);

                // Blending
                if(p == 0)
                {
                    // scene blend
                    material.SetSceneBlending(pass[p].blendSrc, pass[p].blendDest);

                    if(material.IsTransparent && (pass[p].blendSrc != SceneBlendFactor.SourceAlpha))
                        material.DepthWrite = false;

                    t.SetColorOperation(LayerBlendOperation.Replace);
                }
                else
                {
                    if(pass[p].customBlend)
                    {
                        // Fallback for now
                        t.SetColorOperation(LayerBlendOperation.Modulate);
                    }
                    else
                    {
                        t.SetColorOperation(pass[p].blend);
                    }
                }

                // Tex coords
                if(pass[p].texGen == ShaderTextureGen.Base)
                    t.TextureCoordSet = 0;
                else if(pass[p].texGen == ShaderTextureGen.Lightmap)
                    t.TextureCoordSet = 1;
                else if(pass[p].texGen == ShaderTextureGen.Environment)
                    t.SetEnvironmentMap(true, EnvironmentMap.Planar);

                // Tex mod
                // Scale
                t.SetTextureScaleU(pass[p].tcModScale[0]);
                t.SetTextureScaleV(pass[p].tcModScale[1]);

                CreateProceduralTextureMods(p, t);
                // Address mode
                t.TextureAddressing = pass[p].addressMode;
                // Alpha mode
                t.SetAlphaRejectSettings(pass[p].alphaFunc, pass[p].alphaVal);
            }

            // Do farbox (create new material)

            // Do skydome (use this material)
            if(skyDome)
            {
                float halfAngle = 0.5f * (0.5f * (4.0f * (float) Math.Atan(1.0f)));
                float sin = (float) Math.Sin(halfAngle);

                // Quake3 is always aligned with Z upwards
                Quaternion q = new Quaternion(
                    (float) Math.Cos(halfAngle),
                    sin * Vector3.UnitX.x,
                    sin * Vector3.UnitY.y,
                    sin * Vector3.UnitX.z
                    );

                // Also draw last, and make close to camera (far clip plane is shorter)
                sm.SetSkyDome(true, materialName, 20 - (cloudHeight / 256 * 18), 12, 2000, false, q);
            }

            material.CullingMode = Axiom.Graphics.CullingMode.None;
            material.ManualCullMode = cullMode;
            material.Lighting = false;
            material.Load();

            return material;
        }
Пример #15
0
        /// <summary>
        ///		Gets the shortest arc quaternion to rotate this vector to the destination vector. 
        /// </summary>
        /// <remarks>
        ///		Don't call this if you think the dest vector can be close to the inverse
        ///		of this vector, since then ANY axis of rotation is ok.
        ///	</remarks>
        public Quaternion GetRotationTo(Vector3 destination)
        {
            // Based on Stan Melax's article in Game Programming Gems
            Quaternion q = new Quaternion();

            Vector3 v0 = new Vector3(this.x, this.y, this.z);
            Vector3 v1 = destination;

            // normalize both vectors
            v0.Normalize();
            v1.Normalize();

            // get the cross product of the vectors
            Vector3 c = v0.Cross(v1);

            // If the cross product approaches zero, we get unstable because ANY axis will do
            // when v0 == -v1
            float d = v0.Dot(v1);

            // If dot == 1, vectors are the same
            if (d >= 1.0f)
            {
                return Quaternion.Identity;
            }

            float s = MathUtil.Sqrt( (1+d) * 2 );
            float inverse = 1 / s;

            q.x = c.x * inverse;
            q.y = c.y * inverse;
            q.z = c.z * inverse;
            q.w = s * 0.5f;

            return q;
        }
 public QuaternionValue(Quaternion val):
     base((object)val)
 {
 }
Пример #17
0
        /// <summary>
        ///    Reads and returns a Quaternion.
        /// </summary>
        /// <returns></returns>
        protected Quaternion ReadQuat(BinaryMemoryReader reader)
        {
            Quaternion quat = new Quaternion();

            quat.x = reader.ReadSingle();
            quat.y = reader.ReadSingle();
            quat.z = reader.ReadSingle();
            quat.w = reader.ReadSingle();

            return quat;
        }
        private SceneNode NewSceneObject(string meshName, Vector3 position, 
										 Vector3 scale, Quaternion orientation)
        {
            SceneNode node = UnscaledSceneObject(meshName, position);
            node.ScaleFactor = scale;
            node.Orientation = orientation;
            return node;
        }
        protected void UpdateOrientation()
        {
            Quaternion azimuthRotation = Quaternion.FromAngleAxis(MathUtil.DegreesToRadians(azimuth), Vector3.UnitY);
            Quaternion zenithRotation = Quaternion.FromAngleAxis(MathUtil.DegreesToRadians(-zenith), Vector3.UnitX);
            Matrix3 lightMatrix = (azimuthRotation * zenithRotation).ToRotationMatrix(); // Compute "position" of light (actually just reverse direction)
            Vector3 relativeLightPos = lightMatrix * Vector3.UnitZ;

            relativeLightPos.Normalize();

            this.lightDirection = -relativeLightPos;
            Quaternion displayZenithRotation = Quaternion.FromAngleAxis(MathUtil.DegreesToRadians(-Zenith + 90), Vector3.UnitX);
            this.orientation = (azimuthRotation * displayZenithRotation);

            if (inScene)
            {
                this.displayObject.SetOrientation(orientation);
            }
        }
        /// <summary>
        ///		Generates billboard corners.
        /// </summary>
        /// <param name="camera"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="billboard"></param>
        /// <remarks>Billboard param only required for type OrientedSelf</remarks>
        protected virtual void GenerateBillboardAxes(ref Vector3 x, ref Vector3 y, Billboard bb) {
            // If we're using accurate facing, recalculate camera direction per BB
            if (accurateFacing && 
                (billboardType == BillboardType.Point || 
                 billboardType == BillboardType.OrientedCommon ||
	    	     billboardType == BillboardType.OrientedSelf))
            {
                // cam -> bb direction
                camDir = bb.Position - camPos;
                camDir.Normalize();
            }


            switch (billboardType)
            {
                case BillboardType.Point:
                    if (accurateFacing) {
                        // Point billboards will have 'up' based on but not equal to cameras
                        y = camQ * Vector3.UnitY;
                        x = camDir.Cross(y);
                        x.Normalize();
                        y = x.Cross(camDir); // both normalised already
                    } else {
                        // Get camera axes for X and Y (depth is irrelevant)
                        x = camQ * Vector3.UnitX;
                        y = camQ * Vector3.UnitY;
                    }
                    break;

                case BillboardType.OrientedCommon:
                    // Y-axis is common direction
                    // X-axis is cross with camera direction
                    y = commonDirection;
                    x = camDir.Cross(y);
                    x.Normalize();
                    break;

                case BillboardType.OrientedSelf:
                    // Y-axis is direction
                    // X-axis is cross with camera direction
                    // Scale direction first
                    y = bb.Direction;
                    x = camDir.Cross(y);
                    x.Normalize();
                    break;

                case BillboardType.PerpendicularCommon:
                    // X-axis is up-vector cross common direction
                    // Y-axis is common direction cross X-axis
                    x = commonUpVector.Cross(commonDirection);
                    y = commonDirection.Cross(x);
                    break;

                case BillboardType.PerpendicularSelf:
                    // X-axis is up-vector cross own direction
                    // Y-axis is own direction cross X-axis
                    x = commonUpVector.Cross(bb.Direction);
                    x.Normalize();
                    y = bb.Direction.Cross(x); // both should be normalised
                    break;
            }


#if NOT
            // Default behavior is that billboards are in local node space
            // so orientation of camera (in world space) must be reverse-transformed 
            // into node space to generate the axes
            Quaternion invTransform = parentNode.DerivedOrientation.Inverse();
            Quaternion camQ = Quaternion.Zero;

            switch (billboardType) {
                case BillboardType.Point:
                    // Get camera world axes for X and Y (depth is irrelevant)
                    camQ = camera.DerivedOrientation;
                    // Convert into billboard local space
                    camQ = invTransform * camQ;
                    x = camQ * Vector3.UnitX;
                    y = camQ * Vector3.UnitY;
                    break;
                case BillboardType.OrientedCommon:
                    // Y-axis is common direction
                    // X-axis is cross with camera direction 
                    y = commonDirection;
                    y.Normalize();
                    // Convert into billboard local space
                    camQ = invTransform * camQ;
                    x = camQ * camera.DerivedDirection.Cross(y);
                    x.Normalize();
                    break;
                case BillboardType.OrientedSelf:
                    // Y-axis is direction
                    // X-axis is cross with camera direction 
                    y = billboard.Direction;
                    // Convert into billboard local space
                    camQ = invTransform * camQ;
                    x = camQ * camera.DerivedDirection.Cross(y);
                    x.Normalize();
                    break;
                case BillboardType.PerpendicularCommon:
                    // X-axis is common direction cross common up vector
                    // Y-axis is coplanar with common direction and common up vector
                    x = commonDirection.Cross(commonUpVector);
                    x.Normalize();
                    y = x.Cross(commonDirection);
                    y.Normalize();
                    break;
                case BillboardType.PerpendicularSelf:
                    // X-axis is direction cross common up vector
                    // Y-axis is coplanar with direction and common up vector
                    x = billboard.Direction.Cross(commonUpVector);
                    x.Normalize();
                    y = x.Cross(billboard.Direction);
                    y.Normalize();
                    break;
            }
#endif
        }
 public ParticleEffect(IWorldObject parent, WorldEditor app, string particleEffectName, float particleScale, float velocityScale, string attachmentPointName, Quaternion orientation)
     : this(parent, app, particleEffectName, particleScale, velocityScale, orientation)
 {
     this.attachmentPointName = attachmentPointName;
 }
 protected override void ParseMessage(IncomingMessage inMessage)
 {
     base.ParseMessage(inMessage);
     slotName = inMessage.ReadString();
     effectName = inMessage.ReadString();
     orientation = inMessage.ReadQuaternion();
     velocityMultiplier = inMessage.ReadSingle();
     particleSizeMultiplier = inMessage.ReadSingle();
     particleBooleans = inMessage.ReadByte();
     if (GetFlag(Flags.HasColor))
         color = inMessage.ReadColor();
 }
 protected XmlElement WriteQuaternion(string elementName, Quaternion rot)
 {
     Vector3 axis = new Vector3();
     float angle = 0;
     rot.ToAngleAxis(ref angle, ref axis);
     XmlElement node = document.CreateElement(elementName);
     XmlAttribute attr;
     attr = document.CreateAttribute("angle");
     if (angle >= Math.PI &&
         2 * (float)Math.PI - angle < (float)Math.PI)
     {
         angle = 2 * (float)Math.PI - angle;
         axis = -1 * axis;
         Debug.Assert(angle < Math.PI);
     }
     Debug.Assert(angle < Math.PI + .0001);
     attr.Value = angle.ToString();
     node.Attributes.Append(attr);
     XmlElement childNode = WriteAxis(axis);
     node.AppendChild(childNode);
     return node;
 }
Пример #24
0
        public void HandleUpdate(AgentUpdatePacket pack)
        {
            if (((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.ControlFlags.AGENT_CONTROL_FLY) != 0)
            {
                if (this._physActor.Flying == false)
                {
                    this.current_anim = Animations.AnimsLLUUID["ANIM_AGENT_FLY"];
                    this.anim_seq     = 1;
                    this.SendAnimPack();
                }
                this._physActor.Flying = true;
            }
            else
            {
                if (this._physActor.Flying == true)
                {
                    this.current_anim = Animations.AnimsLLUUID["ANIM_AGENT_STAND"];
                    this.anim_seq     = 1;
                    this.SendAnimPack();
                }
                this._physActor.Flying = false;
            }
            if (((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.ControlFlags.AGENT_CONTROL_AT_POS) != 0)
            {
                Axiom.MathLib.Quaternion q = new Axiom.MathLib.Quaternion(pack.AgentData.BodyRotation.W, pack.AgentData.BodyRotation.X, pack.AgentData.BodyRotation.Y, pack.AgentData.BodyRotation.Z);
                if (((movementflag & 1) == 0) || (q != this.bodyRot))
                {
                    if (((movementflag & 1) == 0) && (!this._physActor.Flying))
                    {
                        this.current_anim = Animations.AnimsLLUUID["ANIM_AGENT_WALK"];
                        this.anim_seq     = 1;
                        this.SendAnimPack();
                    }


                    //we should add a new force to the list
                    // but for now we will deal with velocities
                    NewForce newVelocity        = new NewForce();
                    Axiom.MathLib.Vector3 v3    = new Axiom.MathLib.Vector3(1, 0, 0);
                    Axiom.MathLib.Vector3 direc = q * v3;
                    direc.Normalize();

                    //work out velocity for sim physics system
                    direc = direc * ((0.03f) * 128f);
                    if (this._physActor.Flying)
                    {
                        direc *= 2;
                    }

                    newVelocity.X = direc.x;
                    newVelocity.Y = direc.y;
                    newVelocity.Z = direc.z;
                    this.forcesList.Add(newVelocity);
                    movementflag = 1;
                    this.bodyRot = q;
                }
            }
            else if ((((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.ControlFlags.AGENT_CONTROL_UP_POS) != 0) && (PhysicsEngineFlying))
            {
                if (((movementflag & 2) == 0) && this._physActor.Flying)
                {
                    //we should add a new force to the list
                    // but for now we will deal with velocities
                    NewForce newVelocity        = new NewForce();
                    Axiom.MathLib.Vector3 v3    = new Axiom.MathLib.Vector3(0, 0, 1);
                    Axiom.MathLib.Vector3 direc = v3;
                    direc.Normalize();

                    //work out velocity for sim physics system
                    direc         = direc * ((0.03f) * 128f * 2);
                    newVelocity.X = direc.x;
                    newVelocity.Y = direc.y;
                    newVelocity.Z = direc.z;
                    this.forcesList.Add(newVelocity);
                    movementflag = 2;
                }
            }
            else if ((((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) && (PhysicsEngineFlying))
            {
                if (((movementflag & 4) == 0) && this._physActor.Flying)
                {
                    //we should add a new force to the list
                    // but for now we will deal with velocities
                    NewForce newVelocity     = new NewForce();
                    Axiom.MathLib.Vector3 v3 = new Axiom.MathLib.Vector3(0, 0, -1);
                    //Axiom.MathLib.Quaternion q = new Axiom.MathLib.Quaternion(pack.AgentData.BodyRotation.W, pack.AgentData.BodyRotation.X, pack.AgentData.BodyRotation.Y, pack.AgentData.BodyRotation.Z);
                    Axiom.MathLib.Vector3 direc = v3;
                    direc.Normalize();

                    //work out velocity for sim physics system
                    direc         = direc * ((0.03f) * 128f * 2);
                    newVelocity.X = direc.x;
                    newVelocity.Y = direc.y;
                    newVelocity.Z = direc.z;
                    this.forcesList.Add(newVelocity);
                    movementflag = 4;
                }
            }
            else if (((uint)pack.AgentData.ControlFlags & (uint)MainAvatar.ControlFlags.AGENT_CONTROL_AT_NEG) != 0)
            {
                Axiom.MathLib.Quaternion q = new Axiom.MathLib.Quaternion(pack.AgentData.BodyRotation.W, pack.AgentData.BodyRotation.X, pack.AgentData.BodyRotation.Y, pack.AgentData.BodyRotation.Z);
                if (((movementflag & 8) == 0) || (q != this.bodyRot))
                {
                    //we should add a new force to the list
                    // but for now we will deal with velocities
                    NewForce newVelocity        = new NewForce();
                    Axiom.MathLib.Vector3 v3    = new Axiom.MathLib.Vector3(-1, 0, 0);
                    Axiom.MathLib.Vector3 direc = q * v3;
                    direc.Normalize();

                    //work out velocity for sim physics system
                    direc = direc * ((0.03f) * 128f);
                    if (this._physActor.Flying)
                    {
                        direc *= 2;
                    }

                    newVelocity.X = direc.x;
                    newVelocity.Y = direc.y;
                    newVelocity.Z = direc.z;
                    this.forcesList.Add(newVelocity);
                    movementflag = 8;
                    this.bodyRot = q;
                }
            }
            else
            {
                if (movementflag == 16)
                {
                    movementflag = 0;
                }
                if ((movementflag) != 0)
                {
                    NewForce newVelocity = new NewForce();
                    newVelocity.X = 0;
                    newVelocity.Y = 0;
                    newVelocity.Z = 0;
                    this.forcesList.Add(newVelocity);
                    movementflag = 0;
                    // We're standing still, so make it show!
                    if (this._physActor.Flying == false)
                    {
                        this.current_anim = Animations.AnimsLLUUID["ANIM_AGENT_STAND"];
                        this.anim_seq     = 1;
                        this.SendAnimPack();
                    }
                    this.movementflag = 16;
                }
            }
        }
 protected XmlElement WriteRotation(Quaternion rot)
 {
     return WriteQuaternion("rotation", rot);
 }
Пример #26
0
        /// <summary>
        ///		Updates this lights position.
        /// </summary>
        public virtual void Update()
        {
            if(parentNode != null) {
                if(!localTransformDirty
                    && parentNode.DerivedOrientation == lastParentOrientation
                    && parentNode.DerivedPosition == lastParentPosition) {
                }
                else {
                    // we are out of date with the scene node we are attached to
                    lastParentOrientation = parentNode.DerivedOrientation;
                    lastParentPosition = parentNode.DerivedPosition;
                    derivedDirection = lastParentOrientation * direction;
                    derivedPosition = (lastParentOrientation * position) + lastParentPosition;
                }
            }
            else {
                derivedPosition = position;
                derivedDirection = direction;
            }

            localTransformDirty = false;
        }
Пример #27
0
        /// <summary>
        ///     Gets the shortest arc quaternion to rotate this vector
        ///     to the destination vector.
        /// </summary>   
        /// <remarks>
        ///     If you call this with a dest vector that is close to the inverse
        ///     of this vector, we will rotate 180 degrees around the 'fallbackAxis'
        ///     (if specified, or a generated axis if not) since in this case
        ///     ANY axis of rotation is valid.
        /// </remarks>
        public Quaternion GetRotationTo(Vector3 destination, Vector3 fallbackAxis)
        {
            // Based on Stan Melax's article in Game Programming Gems
            Quaternion q = new Quaternion();

            Vector3 v0 = new Vector3(this.x, this.y, this.z);
            Vector3 v1 = destination;

            // normalize both vectors
            v0.Normalize();
            v1.Normalize();

            // get the cross product of the vectors
            Vector3 c = v0.Cross(v1);

            // If the cross product approaches zero, we get unstable because ANY axis will do
            // when v0 == -v1
            float d = v0.Dot(v1);

            // If dot == 1, vectors are the same
            if (d >= 1.0f)
            {
                return Quaternion.Identity;
            }

            if (d < (1e-6f - 1.0f))
            {
                if (fallbackAxis != Vector3.Zero)
                    // rotate 180 degrees about the fallback axis
                    q = Quaternion.FromAngleAxis((float)Math.PI, fallbackAxis);
                else
                {
                    // Generate an axis
                    Vector3 axis = Vector3.UnitX.Cross(this);
                    if (axis.IsZero) // pick another if colinear
                        axis = Vector3.UnitY.Cross(this);
                    axis.Normalize();
                    q = Quaternion.FromAngleAxis((float)Math.PI, axis);
                }
            }
            else
            {
                float s = MathUtil.Sqrt( (1+d) * 2 );
                float inverse = 1 / s;

                q.x = c.x * inverse;
                q.y = c.y * inverse;
                q.z = c.z * inverse;
                q.w = s * 0.5f;
                q.Normalize();
            }
            return q;
        }
Пример #28
0
        protected void FromXml(XmlReader r, bool loadCollections)
        {
            string filename = "";
            string baseName = worldFilePath.Substring(0, worldFilePath.LastIndexOf('\\'));
            bool loadColl = loadCollections;

            for (int i = 0; i < r.AttributeCount; i++)
            {
                r.MoveToAttribute(i);
                switch (r.Name)
                {
                    case "Name":
                        name = r.Value;
                        break;
                }
            }
            r.MoveToElement();

            while (r.Read())
            {
                // look for the start of an element
                if (r.NodeType == XmlNodeType.Whitespace)
                {
                    continue;
                }
                if (r.NodeType == XmlNodeType.EndElement)
                {
                    break;
                }
                if (r.NodeType == XmlNodeType.Element)
                {
                    switch (r.Name)
                    {
                        case "CameraPosition":
                            cameraPosition = XmlHelperClass.ParseVectorAttributes(r);
                            break;
                        case "CameraOrientation":
                            cameraOrientation = XmlHelperClass.ParseQuaternion(r);
                            break;
                        case "Terrain":
                            worldTerrain = new WorldTerrain(app, r);
                            break;
                        case "TerrainDisplay":
                            worldTerrain.DisplayParamsFromXml(r);
                            break;
                        case "Ocean":
                            ocean = new Ocean(this, app, r);
                            break;
                        case "Skybox":
                            skybox = new Skybox(this, app, r);
                            break;
                        case "GlobalFog":
                            fog = new GlobalFog(this, app, r);
                            break;
                        case "GlobalAmbientLight":
                            ambientLight = new GlobalAmbientLight(this, app, app.Scene, r);
                            break;
                        case "GlobalDirectionalLight":
                            directionalLight = new GlobalDirectionalLight(this, app, r);
                            break;
                        case "PathObjectTypes":
                            pathObjectTypes = new PathObjectTypeContainer(app, this, r);
                            break;
                        case "WorldCollection":
                            string collectionName = null;
                            filename = "";
                            for (int i = 0; i < r.AttributeCount; i++)
                            {
                                r.MoveToAttribute(i);
                                switch (r.Name)
                                {
                                    case "Name":
                                        collectionName = r.Value;
                                        break;
                                    case "Filename":
                                        filename = r.Value;
                                        break;
                                }
                            }
                            string filepath = String.Format("{0}\\{1}", baseName, filename);
                            if (filename != "")
                            {
                                if (filename.EndsWith("~.mwc"))
                                {
                                    string autofilepath = String.Format("{0}\\{1}", baseName, filename);
                                    string normalfilepath = String.Format("{0}\\{1}", baseName, filename.Remove(filename.LastIndexOf("~"), 1));
                                    if ((File.Exists(autofilepath) && File.Exists(normalfilepath) &&
                                        (new FileInfo(autofilepath)).LastWriteTime < (new FileInfo(normalfilepath).LastWriteTime))
                                        || (!File.Exists(autofilepath) && File.Exists(normalfilepath)))
                                    {
                                        filename = filename.Remove(filename.LastIndexOf("~"), 1);
                                        filepath = normalfilepath;
                                    }
                                    else
                                    {
                                        filepath = autofilepath;
                                    }
                                }
                                XmlReader childReader = XmlReader.Create(filepath, app.XMLReaderSettings);
                                WorldObjectCollection collection = new WorldObjectCollection(childReader, collectionName, this, app, baseName, loadColl);
                                collection.Filename = filename;
                                while (collection.Filename.Contains("~"))
                                {
                                    collection.Filename = collection.Filename.Remove(collection.Filename.LastIndexOf("~"), 1);
                                }
                                Add(collection);
                                childReader.Close();

                            }
                            else
                            {
                                XmlReader childReader = XmlReader.Create(String.Format("{0}\\{1}.mwc", baseName, collectionName), app.XMLReaderSettings);
                                WorldObjectCollection collection = new WorldObjectCollection(childReader, collectionName, this, app, baseName, loadColl);
                                collection.Filename = filename;
                                Add(collection);
                                while (collection.Filename.Contains("~"))
                                {
                                    collection.Filename = collection.Filename.Remove(collection.Filename.LastIndexOf("~"), 1);
                                }
                                childReader.Close();
                            }

                            r.MoveToElement();

                            break;
                    }
                }
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="plane"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="curvature"></param>
        /// <param name="xSegments"></param>
        /// <param name="ySegments"></param>
        /// <param name="normals"></param>
        /// <param name="numberOfTexCoordSets"></param>
        /// <param name="uTiles"></param>
        /// <param name="vTiles"></param>
        /// <param name="upVector"></param>
        /// <param name="orientation"></param>
        /// <param name="vertexBufferUsage"></param>
        /// <param name="indexBufferUsage"></param>
        /// <param name="vertexShadowBuffer"></param>
        /// <param name="indexShadowBuffer"></param>
        /// <returns></returns>
        public Mesh CreateCurvedIllusionPlane(string name, Plane plane, float width, float height, float curvature, int xSegments, int ySegments, bool normals, int numberOfTexCoordSets, float uTiles, float vTiles, Vector3 upVector, Quaternion orientation, BufferUsage vertexBufferUsage, BufferUsage indexBufferUsage, bool vertexShadowBuffer, bool indexShadowBuffer)
        {
            Mesh mesh = CreateManual(name);
            SubMesh subMesh = mesh.CreateSubMesh(name + "SubMesh");

            // set up vertex data, use a single shared buffer
            mesh.SharedVertexData = new VertexData();
            VertexData vertexData = mesh.SharedVertexData;

            // set up vertex declaration
            VertexDeclaration vertexDeclaration = vertexData.vertexDeclaration;
            int currentOffset = 0;

            // always need positions
            vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Position);
            currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3);

            // optional normals
            if(normals) {
                vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Normal);
                currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3);
            }

            for(ushort i = 0; i < numberOfTexCoordSets; i++) {
                // assumes 2d texture coordinates
                vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i);
                currentOffset += VertexElement.GetTypeSize(VertexElementType.Float2);
            }

            vertexData.vertexCount = (xSegments + 1) * (ySegments + 1);

            // allocate vertex buffer
            HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, vertexBufferUsage, vertexShadowBuffer);

            // set up the binding, one source only
            VertexBufferBinding binding = vertexData.vertexBufferBinding;
            binding.SetBinding(0, vertexBuffer);

            // work out the transform required, default orientation of plane is normal along +z, distance 0
            Matrix4 xlate, xform, rot;
            Matrix3 rot3 = Matrix3.Identity;
            xlate = rot = Matrix4.Identity;

            // determine axes
            Vector3 zAxis, yAxis, xAxis;
            zAxis = plane.Normal;
            zAxis.Normalize();
            yAxis = upVector;
            yAxis.Normalize();
            xAxis = yAxis.Cross(zAxis);
            if(xAxis.Length == 0) {
                throw new AxiomException("The up vector for a plane cannot be parallel to the planes normal.");
            }

            rot3.FromAxes(xAxis, yAxis, zAxis);
            rot = rot3;

            // set up standard xform from origin
            xlate.Translation = plane.Normal * -plane.D;

            // concatenate
            xform = xlate * rot;

            // generate vertex data, imagine a large sphere with the camera located near the top,
            // the lower the curvature, the larger the sphere.  use the angle from the viewer to the
            // points on the plane
            float cameraPosition;      // camera position relative to the sphere center

            // derive sphere radius (unused)
            //float sphereDistance;      // distance from the camera to the sphere along box vertex vector
            float sphereRadius;

            // actual values irrelevant, it's the relation between the sphere's radius and the camera's position which is important
            float SPHERE_RADIUS = 100;
            float CAMERA_DISTANCE = 5;
            sphereRadius = SPHERE_RADIUS - curvature;
            cameraPosition = sphereRadius - CAMERA_DISTANCE;

            // lock the whole buffer
            float xSpace = width / xSegments;
            float ySpace = height / ySegments;
            float halfWidth = width / 2;
            float halfHeight = height / 2;
            Vector3 vec = Vector3.Zero;
            Vector3 norm = Vector3.Zero;
            Vector3 min = Vector3.Zero;
            Vector3 max = Vector3.Zero;
            float maxSquaredLength = 0;
            bool firstTime = true;

            // generate vertex data
            GenerateCurvedIllusionPlaneVertexData(vertexBuffer, ySegments, xSegments, xSpace, halfWidth, ySpace, halfHeight, xform, firstTime, normals, orientation, cameraPosition, sphereRadius, uTiles, vTiles, numberOfTexCoordSets, ref min, ref max, ref maxSquaredLength);

            // generate face list
            subMesh.useSharedVertices = true;
            Tesselate2DMesh(subMesh, xSegments + 1, ySegments + 1, false, indexBufferUsage, indexShadowBuffer);

            // generate bounds for the mesh
            mesh.BoundingBox = new AxisAlignedBox(min, max);
            mesh.BoundingSphereRadius = MathUtil.Sqrt(maxSquaredLength);

            mesh.Load();
            mesh.Touch();

            return mesh;
        }
Пример #30
0
 /// <summary>
 ///    Reads and returns a Quaternion.
 /// </summary>
 protected void WriteQuat(BinaryWriter writer, Quaternion quat)
 {
     writer.Write(quat.x);
     writer.Write(quat.y);
     writer.Write(quat.z);
     writer.Write(quat.w);
 }
        private static void GenerateCurvedIllusionPlaneVertexData(HardwareVertexBuffer vertexBuffer, int ySegments, int xSegments, float xSpace, float halfWidth, float ySpace, float halfHeight, Matrix4 xform, bool firstTime, bool normals, Quaternion orientation, float cameraPosition, float sphereRadius, float uTiles, float vTiles, int numberOfTexCoordSets, ref Vector3 min, ref Vector3 max, ref float maxSquaredLength)
        {
            Vector3 vec;
            Vector3 norm;
            float sphereDistance;
            unsafe {
                // lock the vertex buffer
                IntPtr data = vertexBuffer.Lock(BufferLocking.Discard);

                float* pData = (float*)data.ToPointer();

                for (int y = 0; y < ySegments + 1; ++y) {
                    for (int x = 0; x < xSegments + 1; ++x) {
                        // centered on origin
                        vec.x = (x * xSpace) - halfWidth;
                        vec.y = (y * ySpace) - halfHeight;
                        vec.z = 0.0f;

                        // transform by orientation and distance
                        vec = xform * vec;

                        // assign to geometry
                        *pData++ = vec.x;
                        *pData++ = vec.y;
                        *pData++ = vec.z;

                        // build bounds as we go
                        if (firstTime) {
                            min = vec;
                            max = vec;
                            maxSquaredLength = vec.LengthSquared;
                            firstTime = false;
                        } else {
                            min.Floor(vec);
                            max.Ceil(vec);
                            maxSquaredLength = MathUtil.Max(maxSquaredLength, vec.LengthSquared);
                        }

                        if (normals) {
                            norm = Vector3.UnitZ;
                            norm = orientation * norm;

                            *pData++ = vec.x;
                            *pData++ = vec.y;
                            *pData++ = vec.z;
                        }

                        // generate texture coordinates, normalize position, modify by orientation to return +y up
                        vec = orientation.Inverse() * vec;
                        vec.Normalize();

                        // find distance to sphere
                        sphereDistance = MathUtil.Sqrt(cameraPosition * cameraPosition * (vec.y * vec.y - 1.0f) + sphereRadius * sphereRadius) - cameraPosition * vec.y;

                        vec.x *= sphereDistance;
                        vec.z *= sphereDistance;

                        // use x and y on sphere as texture coordinates, tiled
                        float s = vec.x * (0.01f * uTiles);
                        float t = vec.z * (0.01f * vTiles);
                        for (int i = 0; i < numberOfTexCoordSets; i++) {
                            *pData++ = s;
                            *pData++ = (1 - t);
                        }
                    } // x
                } // y

                // unlock the buffer
                vertexBuffer.Unlock();
            } // unsafe
        }