private void ProcessObjectQueueUpdateToNode(VObject _obj) { // Little known fact. Dead avatar in LibOMV have the word 'dead' in their UUID // Skip over this one and move on to the next one if it's dead. if (((Avatar)_obj.Prim).ID.ToString().Contains("dead")) { return; } if (_obj.Node == null) { return; } //If we don't have an avatar representation yet for this avatar or it's a full update if (_obj.Requesting == false) { if ((_obj._3DiIrrfileUUID != _obj.RequestIrrfileUUID) && (_obj.RequestIrrfileUUID != UUID.Zero)) { if (Reference.Viewer.IrrManager.Contains(_obj.RequestIrrfileUUID) == false) { _obj.requestTexturesDirectlyFromAssetServerWithoutJ2KConversion = true; Reference.Viewer.IrrManager.RequestObject(_obj); Reference.Log.Debug("Request object: UUID:" + _obj.RequestIrrfileUUID.ToString()); } else { _obj._3DiIrrfileUUID = _obj.RequestIrrfileUUID; IrrDatas datas = Reference.Viewer.IrrManager.GetObject(_obj._3DiIrrfileUUID, true); if (datas != null) { // Set avatar mesh. lock (entities) { Reference.Viewer.EffectManager.RemoveGhostNode(_obj.Node); _obj.IsGhost = false; AnimatedMeshSceneNode animeNode = Reference.Viewer.IrrManager.IrrFileLoad(datas, Reference.SceneManager, _obj, "tmpmesh_" + _obj.Prim.LocalID.ToString() + "_"); if (animeNode != null) { animeNode.AnimationEnd += animeNode_AnimationEnd; animeNode.SetTransitionTime(0.1f); _obj.Mesh = animeNode.AnimatedMesh.GetMesh(0); SetAnimation(_obj, _obj.Prim.ParentID != 0 ? "sitstart" : "standing"); } } } Reference.Log.Debug("Loaded object: UUID:" + _obj.RequestIrrfileUUID.ToString()); } } } AnimationFrame(_obj, _obj.Prim.ParentID != 0); _obj.TargetPosition = new Vector3D(_obj.Prim.Position.X, _obj.Prim.Position.Z - 0.83f, _obj.Prim.Position.Y); _obj.Velocity = new Vector3D(_obj.Prim.Velocity.X, _obj.Prim.Velocity.Z, _obj.Prim.Velocity.Y); if (_obj.Prim.ID != userUUID) { // REVIEW NEEDED: a more general calculation //float roll, pitch, yaw; //_obj.Prim.Rotation.GetEulerAngles(out roll, out pitch, out yaw); //_obj.Node.Rotation = new Vector3D(Utils.ToDegrees(roll), Utils.ToDegrees(pi2 - pitch), Utils.ToDegrees(yaw)); Vector3 axis; float angle; _obj.Prim.Rotation.GetAxisAngle(out axis, out angle); _obj.Node.Rotation = new Vector3D(0, Utils.ToDegrees((axis.Z > 0 ? 1 : -1) * (pi2 - angle)), 0); } // If exsit parent prim, set parent. uint parentID = _obj.Prim.ParentID; if (parentID == 0) { _obj.ParentPosition = new Vector3(); if (_obj.IsChildAgent) { _obj.IsChildAgent = false; _obj.SmoothingReset = true; } } else { ulong regionID = Reference.Viewer.ProtocolManager.AvatarConnection.m_user.Network.CurrentSim.Handle; if (Reference.Viewer.EntityManager.Entities.ContainsKey(regionID.ToString() + parentID.ToString())) { VObject parentObj = Reference.Viewer.EntityManager.Entities[regionID.ToString() + parentID.ToString()]; if (parentObj != null) { _obj.ParentPosition = parentObj.Prim.Position; IrrlichtNETCP.Quaternion iquParent = new IrrlichtNETCP.Quaternion (parentObj.Prim.Rotation.X, parentObj.Prim.Rotation.Z, parentObj.Prim.Rotation.Y, parentObj.Prim.Rotation.W); iquParent.makeInverse(); IrrlichtNETCP.Quaternion iquAvatar = new IrrlichtNETCP.Quaternion (_obj.Prim.Rotation.X, _obj.Prim.Rotation.Z, _obj.Prim.Rotation.Y, _obj.Prim.Rotation.W); iquAvatar.makeInverse(); IrrlichtNETCP.Quaternion finalRotation = iquAvatar * iquParent; _obj.Node.Rotation = finalRotation.Matrix.RotationDegrees; _obj.TargetPosition = parentObj.Node.Position + _obj.TargetPosition * iquParent; } _obj.SmoothingReset = true; _obj.IsChildAgent = true; } else { UpdateObjectToPiplineEnqueue(_obj); } } _obj.SyncToChilds(); // If avatar's height position is minus, teleport to current sim center. if (_obj.Prim.ID == Reference.Viewer.ProtocolManager.AvatarConnection.GetSelfUUID && _obj.Prim.Position.Z < 0) Reference.Viewer.ProtocolManager.Teleport(Reference.Viewer.ProtocolManager.GetCurrentSimName(), 128, 128, 128); }