/// <summary> /// Deserialize a message from the network. /// </summary> /// <remarks> /// Only receives what it needs and decompresses floats if you chose to. /// </remarks> /// <param name="writer">The Networkreader to read from.</param> public void Deserialize(BinaryReader reader, SmoothSyncPUN2 smoothSync) { // The first received byte tells us what we need to be syncing. byte syncInfoByte = reader.ReadByte(); bool syncPosition = shouldSyncPosition(syncInfoByte); bool syncRotation = shouldSyncRotation(syncInfoByte); bool syncScale = shouldSyncScale(syncInfoByte); bool syncVelocity = shouldSyncVelocity(syncInfoByte); bool syncAngularVelocity = shouldSyncAngularVelocity(syncInfoByte); state.atPositionalRest = shouldBeAtPositionalRest(syncInfoByte); state.atRotationalRest = shouldBeAtRotationalRest(syncInfoByte); int syncIndex = (int)reader.ReadUInt32(); state.ownerTimestamp = reader.ReadSingle(); if (!smoothSync) { Debug.LogWarning("Could not find target for network state message."); return; } // If we want the server to relay non-owned object information out to other clients, set these variables so we know what we need to send. if (PhotonNetwork.IsMasterClient && !smoothSync.photonView.IsMine) { state.serverShouldRelayPosition = syncPosition; state.serverShouldRelayRotation = syncRotation; state.serverShouldRelayScale = syncScale; state.serverShouldRelayVelocity = syncVelocity; state.serverShouldRelayAngularVelocity = syncAngularVelocity; } // Find the correct object to sync according to the syncIndex. for (int i = 0; i < smoothSync.childObjectSmoothSyncs.Length; i++) { if (smoothSync.childObjectSmoothSyncs[i].syncIndex == syncIndex) { smoothSync = smoothSync.childObjectSmoothSyncs[i]; } } state.receivedTimestamp = smoothSync.localTime; if (smoothSync.receivedStatesCounter < PhotonNetwork.SerializationRate) { smoothSync.receivedStatesCounter++; } // Read position. if (syncPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { state.position.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYPosition) { state.position.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZPosition) { state.position.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXPosition) { state.position.x = reader.ReadSingle(); } if (smoothSync.isSyncingYPosition) { state.position.y = reader.ReadSingle(); } if (smoothSync.isSyncingZPosition) { state.position.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.position = smoothSync.stateBuffer[0].position; } else { state.position = smoothSync.getPosition(); } } // Read rotation. if (syncRotation) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.rotation = Quaternion.Euler(state.reusableRotationVector); } else { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = reader.ReadSingle(); } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = reader.ReadSingle(); } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = reader.ReadSingle(); } state.rotation = Quaternion.Euler(state.reusableRotationVector); } } else { if (smoothSync.stateCount > 0) { state.rotation = smoothSync.stateBuffer[0].rotation; } else { state.rotation = smoothSync.getRotation(); } } // Read scale. if (syncScale) { if (smoothSync.isScaleCompressed) { if (smoothSync.isSyncingXScale) { state.scale.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYScale) { state.scale.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZScale) { state.scale.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXScale) { state.scale.x = reader.ReadSingle(); } if (smoothSync.isSyncingYScale) { state.scale.y = reader.ReadSingle(); } if (smoothSync.isSyncingZScale) { state.scale.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.scale = smoothSync.stateBuffer[0].scale; } else { state.scale = smoothSync.getScale(); } } // Read velocity. if (syncVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { state.velocity.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXVelocity) { state.velocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedVelocity = state.velocity; } else { // If we didn't receive an updated velocity, use the latest received velocity. state.velocity = smoothSync.latestReceivedVelocity; } // Read anguluar velocity. if (syncAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isSyncingXAngularVelocity) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYAngularVelocity) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZAngularVelocity) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.angularVelocity = state.reusableRotationVector; } else { if (smoothSync.isSyncingXAngularVelocity) { state.angularVelocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYAngularVelocity) { state.angularVelocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZAngularVelocity) { state.angularVelocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedAngularVelocity = state.angularVelocity; } else { // If we didn't receive an updated angular velocity, use the latest received angular velocity. state.angularVelocity = smoothSync.latestReceivedAngularVelocity; } //// Update new owner information sent from the Server. //if (smoothSync.isSmoothingAuthorityChanges && !NetworkServer.active) //{ // smoothSync.ownerChangeIndicator = (int)reader.ReadByte(); //} if (smoothSync.automaticallyResetTime) { state.localTimeResetIndicator = (int)reader.ReadByte(); } }
/// <summary> /// Deserialize a message from the network. /// </summary> /// <remarks> /// Only receives what it needs and decompresses floats if you chose to. /// </remarks> /// <param name="writer">The Networkreader to read from.</param> override public void Deserialize(NetworkReader reader) { // The first received byte tells us what we need to be syncing. byte syncInfoByte = reader.ReadByte(); bool syncPosition = shouldSyncPosition(syncInfoByte); bool syncRotation = shouldSyncRotation(syncInfoByte); bool syncScale = shouldSyncScale(syncInfoByte); bool syncVelocity = shouldSyncVelocity(syncInfoByte); bool syncAngularVelocity = shouldSyncAngularVelocity(syncInfoByte); state.teleport = shouldTeleport(syncInfoByte); state.atPositionalRest = shouldBeAtPositionalRest(syncInfoByte); state.atRotationalRest = shouldBeAtRotationalRest(syncInfoByte); NetworkInstanceId netID = reader.ReadNetworkId(); int syncIndex = (int)reader.ReadPackedUInt32(); state.ownerTimestamp = reader.ReadSingle(); // Find the GameObject GameObject ob = null; if (NetworkServer.active) { ob = NetworkServer.FindLocalObject(netID); } else { ob = ClientScene.FindLocalObject(netID); } if (!ob) { Debug.LogWarning("Could not find target for network state message."); return; } // It doesn't matter which SmoothSync is returned since they all have the same list. smoothSync = ob.GetComponent <SmoothSync>(); // If we want the server to relay non-owned object information out to other clients, set these variables so we know what we need to send. if (NetworkServer.active && !smoothSync.hasAuthority) { state.serverShouldRelayPosition = syncPosition; state.serverShouldRelayRotation = syncRotation; state.serverShouldRelayScale = syncScale; state.serverShouldRelayVelocity = syncVelocity; state.serverShouldRelayAngularVelocity = syncAngularVelocity; } // Find the correct object to sync according to the syncIndex. for (int i = 0; i < smoothSync.childObjectSmoothSyncs.Length; i++) { if (smoothSync.childObjectSmoothSyncs[i].syncIndex == syncIndex) { smoothSync = smoothSync.childObjectSmoothSyncs[i]; } } if (!smoothSync) { Debug.LogWarning("Could not find target for network state message."); return; } // Read position. if (syncPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { state.position.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYPosition) { state.position.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZPosition) { state.position.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXPosition) { state.position.x = reader.ReadSingle(); } if (smoothSync.isSyncingYPosition) { state.position.y = reader.ReadSingle(); } if (smoothSync.isSyncingZPosition) { state.position.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.position = smoothSync.stateBuffer[0].position; } else { state.position = smoothSync.getPosition(); } } // Read rotation. if (syncRotation) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.rotation = Quaternion.Euler(state.reusableRotationVector); } else { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = reader.ReadSingle(); } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = reader.ReadSingle(); } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = reader.ReadSingle(); } state.rotation = Quaternion.Euler(state.reusableRotationVector); } } else { if (smoothSync.stateCount > 0) { state.rotation = smoothSync.stateBuffer[0].rotation; } else { state.rotation = smoothSync.getRotation(); } } // Read scale. if (syncScale) { if (smoothSync.isScaleCompressed) { if (smoothSync.isSyncingXScale) { state.scale.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYScale) { state.scale.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZScale) { state.scale.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXScale) { state.scale.x = reader.ReadSingle(); } if (smoothSync.isSyncingYScale) { state.scale.y = reader.ReadSingle(); } if (smoothSync.isSyncingZScale) { state.scale.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.scale = smoothSync.stateBuffer[0].scale; } else { state.scale = smoothSync.getScale(); } } // Read velocity. if (syncVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { state.velocity.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXVelocity) { state.velocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedVelocity = state.velocity; } else { // If we didn't receive an updated velocity, use the latest received velocity. state.velocity = smoothSync.latestReceivedVelocity; } // Read anguluar velocity. if (syncAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isSyncingXAngularVelocity) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYAngularVelocity) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZAngularVelocity) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.angularVelocity = state.reusableRotationVector; } else { if (smoothSync.isSyncingXAngularVelocity) { state.angularVelocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYAngularVelocity) { state.angularVelocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZAngularVelocity) { state.angularVelocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedAngularVelocity = state.angularVelocity; } else { // If we didn't receive an updated angular velocity, use the latest received angular velocity. state.angularVelocity = smoothSync.latestReceivedAngularVelocity; } }
/// <summary> /// Serialize the message over the network. /// </summary> /// <remarks> /// Only sends what it needs and compresses floats if you chose to. /// </remarks> /// <param name="writer">The NetworkWriter to write to.</param> public void Serialize(BinaryWriter writer) { bool sendPosition, sendRotation, sendScale, sendVelocity, sendAngularVelocity, sendAtPositionalRestTag, sendAtRotationalRestTag; //// If is a server trying to relay client information back out to other clients. //if (NetworkServer.active && !smoothSync.photonView.IsMine)//!smoothSync.hasAuthority) //{ // sendPosition = state.serverShouldRelayPosition; // sendRotation = state.serverShouldRelayRotation; // sendScale = state.serverShouldRelayScale; // sendVelocity = state.serverShouldRelayVelocity; // sendAngularVelocity = state.serverShouldRelayAngularVelocity; // sendTeleportTag = state.teleport; // sendAtPositionalRestTag = state.atPositionalRest; // sendAtRotationalRestTag = state.atRotationalRest; //} //else // If is a server or client trying to send owned object information across the network. { sendPosition = smoothSync.sendPosition; sendRotation = smoothSync.sendRotation; sendScale = smoothSync.sendScale; sendVelocity = smoothSync.sendVelocity; sendAngularVelocity = smoothSync.sendAngularVelocity; sendAtPositionalRestTag = smoothSync.sendAtPositionalRestMessage; sendAtRotationalRestTag = smoothSync.sendAtRotationalRestMessage; } //// Only set last sync States on clients here because the server needs to send multiple Serializes. //if (!NetworkServer.active) { if (sendPosition) { smoothSync.lastPositionWhenStateWasSent = state.position; } if (sendRotation) { smoothSync.lastRotationWhenStateWasSent = state.rotation; } if (sendScale) { smoothSync.lastScaleWhenStateWasSent = state.scale; } if (sendVelocity) { smoothSync.lastVelocityWhenStateWasSent = state.velocity; } if (sendAngularVelocity) { smoothSync.lastAngularVelocityWhenStateWasSent = state.angularVelocity; } } writer.Write(encodeSyncInformation(sendPosition, sendRotation, sendScale, sendVelocity, sendAngularVelocity, sendAtPositionalRestTag, sendAtRotationalRestTag)); //writer.Write(smoothSync.netID); writer.Write((uint)smoothSync.syncIndex); writer.Write(state.ownerTimestamp); // Write position. if (sendPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { writer.Write(HalfHelper.Compress(state.position.x)); } if (smoothSync.isSyncingYPosition) { writer.Write(HalfHelper.Compress(state.position.y)); } if (smoothSync.isSyncingZPosition) { writer.Write(HalfHelper.Compress(state.position.z)); } } else { if (smoothSync.isSyncingXPosition) { writer.Write(state.position.x); } if (smoothSync.isSyncingYPosition) { writer.Write(state.position.y); } if (smoothSync.isSyncingZPosition) { writer.Write(state.position.z); } } } // Write rotation. if (sendRotation) { Vector3 rot = state.rotation.eulerAngles; if (smoothSync.isRotationCompressed) { // Convert to radians for more accurate Half numbers if (smoothSync.isSyncingXRotation) { writer.Write(HalfHelper.Compress(rot.x * Mathf.Deg2Rad)); } if (smoothSync.isSyncingYRotation) { writer.Write(HalfHelper.Compress(rot.y * Mathf.Deg2Rad)); } if (smoothSync.isSyncingZRotation) { writer.Write(HalfHelper.Compress(rot.z * Mathf.Deg2Rad)); } } else { if (smoothSync.isSyncingXRotation) { writer.Write(rot.x); } if (smoothSync.isSyncingYRotation) { writer.Write(rot.y); } if (smoothSync.isSyncingZRotation) { writer.Write(rot.z); } } } // Write scale. if (sendScale) { if (smoothSync.isScaleCompressed) { if (smoothSync.isSyncingXScale) { writer.Write(HalfHelper.Compress(state.scale.x)); } if (smoothSync.isSyncingYScale) { writer.Write(HalfHelper.Compress(state.scale.y)); } if (smoothSync.isSyncingZScale) { writer.Write(HalfHelper.Compress(state.scale.z)); } } else { if (smoothSync.isSyncingXScale) { writer.Write(state.scale.x); } if (smoothSync.isSyncingYScale) { writer.Write(state.scale.y); } if (smoothSync.isSyncingZScale) { writer.Write(state.scale.z); } } } // Write velocity. if (sendVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { writer.Write(HalfHelper.Compress(state.velocity.x)); } if (smoothSync.isSyncingYVelocity) { writer.Write(HalfHelper.Compress(state.velocity.y)); } if (smoothSync.isSyncingZVelocity) { writer.Write(HalfHelper.Compress(state.velocity.z)); } } else { if (smoothSync.isSyncingXVelocity) { writer.Write(state.velocity.x); } if (smoothSync.isSyncingYVelocity) { writer.Write(state.velocity.y); } if (smoothSync.isSyncingZVelocity) { writer.Write(state.velocity.z); } } } // Write angular velocity. if (sendAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { // Convert to radians for more accurate Half numbers if (smoothSync.isSyncingXAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.x * Mathf.Deg2Rad)); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.y * Mathf.Deg2Rad)); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.z * Mathf.Deg2Rad)); } } else { if (smoothSync.isSyncingXAngularVelocity) { writer.Write(state.angularVelocity.x); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(state.angularVelocity.y); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(state.angularVelocity.z); } } } //// Only the server sends out owner information. //if (smoothSync.isSmoothingAuthorityChanges && NetworkServer.active) //{ // writer.Write((byte)smoothSync.ownerChangeIndicator); //} if (smoothSync.automaticallyResetTime) { writer.Write((byte)state.localTimeResetIndicator); } }
/// <summary> /// Parses the MDL file to obtain model information /// </summary> /// <param name="selectedItem">The currently selected item</param> /// <param name="selectedRace">The currently selected race</param> /// <param name="selectedBody">The currently selected body</param> /// <param name="selectedPart">The currently selected part</param> /// <param name="selectedCategory">The items category </param> public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart) { string itemType = Helper.GetCategoryType(selectedCategory); string MDLFolder = ""; if (itemType.Equals("weapon") || itemType.Equals("food")) { if (selectedPart.Equals("Secondary")) { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); } else { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); } } else if (itemType.Equals("accessory")) { MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID); MDLFile = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } else if (itemType.Equals("character")) { if (selectedItem.ItemName.Equals(Strings.Body)) { MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Face)) { MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Hair)) { MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Tail)) { MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } } else if (itemType.Equals("monster")) { bool isDemiHuman = false; if (selectedItem.PrimaryMTRLFolder != null) { isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman"); } if (isDemiHuman) { MDLFolder = string.Format(Strings.DemiMDLFolder, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.DemiMDLFile, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody, selectedPart); } else { MDLFolder = string.Format(Strings.MonsterMDLFolder, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.MonsterMDLFile, selectedItem.PrimaryModelID.PadLeft(4, '0'), selectedItem.PrimaryModelBody.PadLeft(4, '0')); } } else { MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID); if (selectedPart.Equals("-")) { MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } else { MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, selectedPart); } } fullPath = MDLFolder + "/" + MDLFile; int offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat); if (offset == 0) { if (itemType.Equals("weapon")) { if (selectedPart.Equals("Secondary")) { MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.SecondaryModelID); MDLFile = string.Format(Strings.EquipMDLFile, "0101", selectedItem.SecondaryModelID, Info.slotAbr[Strings.Hands]); offset = Helper.GetDataOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile), Strings.ItemsDat); } } } int datNum = ((offset / 8) & 0x000f) / 2; var MDLDatData = Helper.GetType3DecompressedData(offset, datNum, Strings.ItemsDat); using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1))) { // The size of the header + (size of the mesh information block (136 bytes) * the number of meshes) + padding br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin); var modelStringCount = br.ReadInt32(); var stringBlockSize = br.ReadInt32(); var stringBlock = br.ReadBytes(stringBlockSize); var unknown = br.ReadBytes(4); var totalMeshCount = br.ReadInt16(); var attributeStringCount = br.ReadInt16(); var meshPartsCount = br.ReadInt16(); var materialStringCount = br.ReadInt16(); var boneStringCount = br.ReadInt16(); var boneListCount = br.ReadInt16(); var unknown1 = br.ReadInt16(); var unknown2 = br.ReadInt16(); var unknown3 = br.ReadInt16(); var unknown4 = br.ReadInt16(); var unknown5 = br.ReadInt16(); var unknown6 = br.ReadInt16(); br.ReadBytes(10); var unknown7 = br.ReadInt16(); br.ReadBytes(16); using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock))) { br1.BaseStream.Seek(0, SeekOrigin.Begin); for (int i = 0; i < attributeStringCount; i++) { byte a; List <byte> atrName = new List <byte>(); while ((a = br1.ReadByte()) != 0) { atrName.Add(a); } string atr = Encoding.ASCII.GetString(atrName.ToArray()); atr = atr.Replace("\0", ""); atrStrings.Add(atr); } for (int i = 0; i < boneStringCount; i++) { byte b; List <byte> boneName = new List <byte>(); while ((b = br1.ReadByte()) != 0) { boneName.Add(b); } string bone = Encoding.ASCII.GetString(boneName.ToArray()); bone = bone.Replace("\0", ""); boneStrings.Add(bone); } for (int i = 0; i < materialStringCount; i++) { byte b; List <byte> name = new List <byte>(); while ((b = br1.ReadByte()) != 0) { name.Add(b); } string material = Encoding.ASCII.GetString(name.ToArray()); material = material.Replace("\0", ""); materialStrings.Add(material); } } br.ReadBytes(32 * unknown5); for (int i = 0; i < 3; i++) { LevelOfDetail LoD = new LevelOfDetail(); LoD.MeshOffset = br.ReadInt16(); LoD.MeshCount = br.ReadInt16(); br.ReadBytes(40); LoD.VertexDataSize = br.ReadInt32(); LoD.IndexDataSize = br.ReadInt32(); LoD.VertexOffset = br.ReadInt32(); LoD.IndexOffset = br.ReadInt32(); modelData.LoD.Add(LoD); } var savePos = br.BaseStream.Position; for (int i = 0; i < modelData.LoD.Count; i++) { List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>(); for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { modelData.LoD[i].MeshList.Add(new Mesh()); meshInfoList.Clear(); br.BaseStream.Seek((i * 136) + 68, SeekOrigin.Begin); var dataBlockNum = br.ReadByte(); while (dataBlockNum != 255) { MeshDataInfo meshInfo = new MeshDataInfo() { VertexDataBlock = dataBlockNum, Offset = br.ReadByte(), DataType = br.ReadByte(), UseType = br.ReadByte() }; meshInfoList.Add(meshInfo); br.ReadBytes(4); dataBlockNum = br.ReadByte(); } modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray(); } } br.BaseStream.Seek(savePos, SeekOrigin.Begin); for (int x = 0; x < modelData.LoD.Count; x++) { for (int i = 0; i < modelData.LoD[x].MeshCount; i++) { MeshInfo meshInfo = new MeshInfo() { VertexCount = br.ReadInt32(), IndexCount = br.ReadInt32(), MaterialNum = br.ReadInt16(), MeshPartOffset = br.ReadInt16(), MeshPartCount = br.ReadInt16(), BoneListIndex = br.ReadInt16(), IndexDataOffset = br.ReadInt32() }; var typeChar = materialStrings[meshInfo.MaterialNum][4].ToString() + materialStrings[meshInfo.MaterialNum][9].ToString(); if (typeChar.Equals("cb")) { modelData.LoD[x].MeshList[i].IsBody = true; } for (int j = 0; j < 3; j++) { meshInfo.VertexDataOffsets.Add(br.ReadInt32()); } for (int k = 0; k < 3; k++) { meshInfo.VertexSizes.Add(br.ReadByte()); } meshInfo.VertexDataBlockCount = br.ReadByte(); modelData.LoD[x].MeshList[i].MeshInfo = meshInfo; } } br.ReadBytes(attributeStringCount * 4); br.ReadBytes(unknown6 * 20); for (int i = 0; i < modelData.LoD.Count; i++) { foreach (var mesh in modelData.LoD[i].MeshList) { for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++) { MeshPart meshPart = new MeshPart() { IndexOffset = br.ReadInt32(), IndexCount = br.ReadInt32(), Attributes = br.ReadInt32(), BoneOffset = br.ReadInt16(), BoneCount = br.ReadInt16() }; mesh.MeshPartList.Add(meshPart); } } } br.ReadBytes(unknown7 * 12); br.ReadBytes(materialStringCount * 4); br.ReadBytes(boneStringCount * 4); for (int i = 0; i < boneListCount; i++) { Bones bones = new Bones(); for (int j = 0; j < 64; j++) { bones.BoneData.Add(br.ReadInt16()); } bones.BoneCount = br.ReadInt32(); modelData.BoneSet.Add(bones); } //br.ReadBytes(unknown1 * 16); Dictionary <int, int> indexMin = new Dictionary <int, int>(); Dictionary <int, List <int> > extraIndices = new Dictionary <int, List <int> >(); Dictionary <int, List <int> > extraIndices2 = new Dictionary <int, List <int> >(); List <ExtraIndex> indexCounts = new List <ExtraIndex>(); var pCount = 0; var pCount1 = 0; var pCount2 = 0; if (unknown1 > 0) { for (int i = 0; i < unknown1; i++) { //not sure br.ReadBytes(4); //LoD[0] Extra Data Index var p1 = br.ReadUInt16(); //LoD[1] Extra Data Index var p2 = br.ReadUInt16(); //LoD[2] Extra Data Index var p3 = br.ReadUInt16(); //LoD[0] Extra Data Part Count var p1n = br.ReadUInt16(); pCount += p1n; //LoD[1] Extra Data Part Count var p2n = br.ReadUInt16(); pCount1 += p2n; //LoD[2] Extra Data Part Count var p3n = br.ReadUInt16(); pCount2 += p3n; } } Dictionary <int, int> indexLoc = new Dictionary <int, int>(); if (unknown1 > 0) { for (int i = 0; i < modelData.LoD[0].MeshCount; i++) { var ido = modelData.LoD[0].MeshList[i].MeshInfo.IndexDataOffset; indexLoc.Add(ido, i); } } List <int> maskCounts = new List <int>(); Dictionary <int, int> totalExtraCounts = new Dictionary <int, int>(); if (unknown2 > 0) { for (int i = 0; i < pCount; i++) { //Index Offset Start var m1 = br.ReadInt32(); var iLoc = 0; if (indexLoc.ContainsKey(m1)) { iLoc = indexLoc[m1]; } //index count var mCount = br.ReadInt32(); //index offset in unk3 var mOffset = br.ReadInt32(); indexCounts.Add(new ExtraIndex() { IndexLocation = iLoc, IndexCount = mCount }); maskCounts.Add(mCount); } br.ReadBytes((pCount1 + pCount2) * 12); } int totalLoD0MaskCount = 0; if (unknown2 > 0) { for (int i = 0; i < pCount; i++) { totalLoD0MaskCount += maskCounts[i]; } } if (unknown3 > 0) { var unk3Remainder = (unknown3 * 4) - (totalLoD0MaskCount * 4); var c = 0; foreach (var ic in indexCounts) { HashSet <int> mIndexList = new HashSet <int>(); for (int i = 0; i < ic.IndexCount; i++) { //index its replacing? attatched to? var oIndex = br.ReadUInt16(); //extra index following last equipment index var mIndex = br.ReadUInt16(); mIndexList.Add(mIndex); if (extraIndices.ContainsKey(ic.IndexLocation)) { extraIndices[ic.IndexLocation].Add(mIndex); extraIndices2[ic.IndexLocation].Add(oIndex); } else { extraIndices.Add(ic.IndexLocation, new List <int>() { mIndex }); extraIndices2.Add(ic.IndexLocation, new List <int>() { oIndex }); } } if (totalExtraCounts.ContainsKey(ic.IndexLocation)) { totalExtraCounts[ic.IndexLocation] += mIndexList.Count; } else { totalExtraCounts.Add(ic.IndexLocation, mIndexList.Count); } c++; } //the rest of unk3 br.ReadBytes(unk3Remainder); } if (unknown3 > 0) { foreach (var ei in extraIndices) { indexMin.Add(ei.Key, ei.Value.Min()); } extraIndexData.indexCounts = indexCounts; extraIndexData.indexMin = indexMin; extraIndexData.totalExtraCounts = totalExtraCounts; extraIndexData.extraIndices = extraIndices; extraIndexData.extraIndices2 = extraIndices2; modelData.ExtraData = extraIndexData; } //br.ReadBytes(unknown3 * 4); var boneIndexSize = br.ReadInt32(); for (int i = 0; i < boneIndexSize / 2; i++) { modelData.BoneIndicies.Add(br.ReadUInt16()); } int padding = br.ReadByte(); br.ReadBytes(padding); for (int i = 0; i < 4; i++) { ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox(); for (int j = 0; j < 4; j++) { boundingBox.PointA.Add(br.ReadSingle()); } for (int k = 0; k < 4; k++) { boundingBox.PointB.Add(br.ReadSingle()); } modelData.BoundingBoxes.Add(boundingBox); } //float4x4 for (int i = 0; i < boneStringCount; i++) { boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); boneTransforms.Add(br.ReadSingle()); } for (int i = 0; i < 3; i++) { for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { Mesh mesh = modelData.LoD[i].MeshList[j]; for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++) { br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin); mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount)); } br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin); mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount); } } int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0, blendWeights = 0, blendIndices = 0; for (int i = 0; i < modelData.LoD[0].MeshCount; i++) { objBytes.Clear(); var vertexList = new Vector3Collection(); var texCoordList = new Vector2Collection(); var texCoordList2 = new Vector2Collection(); var normalList = new Vector3Collection(); var tangentList = new Vector3Collection(); var colorsList = new Color4Collection(); var indexList = new IntCollection(); var blendWeightList = new List <float>(); var blendWeightList2 = new List <float[]>(); var blendIndicesList = new List <int>(); var blendIndicesList2 = new List <int[]>(); var weightCounts = new List <int>(); var extraVerts = new HashSet <Vector3>(); Dictionary <int, Vector3> extraVertDict = new Dictionary <int, Vector3>(); Mesh mesh = modelData.LoD[0].MeshList[i]; MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList; int c = 0; foreach (var meshDataInfo in meshDataInfoList) { if (meshDataInfo.UseType == 0) { vertex = c; } else if (meshDataInfo.UseType == 1) { blendWeights = c; } else if (meshDataInfo.UseType == 2) { blendIndices = c; } else if (meshDataInfo.UseType == 3) { normals = c; } else if (meshDataInfo.UseType == 4) { coordinates = c; } else if (meshDataInfo.UseType == 6) { tangents = c; } else if (meshDataInfo.UseType == 7) { colors = c; } c++; } /* * ----------------- * Vertex * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin); Vector3 vVector = new Vector3(); if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14) { System.Half h1 = System.Half.ToHalf(br1.ReadUInt16()); System.Half h2 = System.Half.ToHalf(br1.ReadUInt16()); System.Half h3 = System.Half.ToHalf(br1.ReadUInt16()); float x = HalfHelper.HalfToSingle(h1); float y = HalfHelper.HalfToSingle(h2); float z = HalfHelper.HalfToSingle(h3); vVector = new Vector3(x, y, z); objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); } else if (meshDataInfoList[vertex].DataType == 2) { var x = BitConverter.ToSingle(br1.ReadBytes(4), 0); var y = BitConverter.ToSingle(br1.ReadBytes(4), 0); var z = BitConverter.ToSingle(br1.ReadBytes(4), 0); vVector = new Vector3(x, y, z); objBytes.Add("v " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); } vertexList.Add(vVector); } } /* * ----------------- * Blend Weight * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendWeights].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendWeights].VertexDataBlock] + meshDataInfoList[blendWeights].Offset, SeekOrigin.Begin); float x = br1.ReadByte() / 255.0f; float y = br1.ReadByte() / 255.0f; float z = br1.ReadByte() / 255.0f; float w = br1.ReadByte() / 255.0f; int count = 0; if (x != 0) { blendWeightList.Add(x); count++; if (y != 0) { blendWeightList.Add(y); count++; if (z != 0) { blendWeightList.Add(z); count++; if (w != 0) { blendWeightList.Add(w); count++; } } } } if (count == 1) { blendWeightList2.Add(new float[] { x }); } else if (count == 2) { blendWeightList2.Add(new float[] { x, y }); } else if (count == 3) { blendWeightList2.Add(new float[] { x, y, z }); } else if (count == 4) { blendWeightList2.Add(new float[] { x, y, z, w }); } weightCounts.Add(count); } } /* * ----------------- * Blend Index * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[blendIndices].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[blendIndices].VertexDataBlock] + meshDataInfoList[blendIndices].Offset, SeekOrigin.Begin); int x = br1.ReadByte(); int y = br1.ReadByte(); int z = br1.ReadByte(); int w = br1.ReadByte(); if (weightCounts[j] == 1) { blendIndicesList.Add(x); blendIndicesList2.Add(new int[] { x }); } else if (weightCounts[j] == 2) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList2.Add(new int[] { x, y }); } else if (weightCounts[j] == 3) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList.Add(z); blendIndicesList2.Add(new int[] { x, y, z }); } else if (weightCounts[j] == 4) { blendIndicesList.Add(x); blendIndicesList.Add(y); blendIndicesList.Add(z); blendIndicesList.Add(w); blendIndicesList2.Add(new int[] { x, y, z, w }); } } } /* * ----------------- * Texture Coordinates * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin); float x = 0; float y = 0; float z = 0; float w = 0; if (meshDataInfoList[coordinates].DataType == 13 || meshDataInfoList[coordinates].DataType == 14) { var sx = br1.ReadUInt16(); var sy = br1.ReadUInt16(); var sz = br1.ReadUInt16(); var sw = br1.ReadUInt16(); var h1 = new SharpDX.Half(sx); var h2 = new SharpDX.Half(sy); var h3 = new SharpDX.Half(sz); var h4 = new SharpDX.Half(sw); x = h1; y = h2; z = h3; w = h4; } else if (meshDataInfoList[coordinates].DataType == 1) { x = br1.ReadSingle(); y = br1.ReadSingle(); } else { x = br1.ReadSingle(); y = br1.ReadSingle(); z = br1.ReadSingle(); w = br1.ReadSingle(); } var ox = x - Math.Truncate(x); var oy = y - Math.Truncate(y); objBytes.Add("vt " + ox.ToString("N5") + " " + (1 - y).ToString("N5") + " "); texCoordList.Add(new Vector2(x, y)); texCoordList2.Add(new Vector2(z, w)); } } /* * ----------------- * Normals * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin); float x = 0; float y = 0; float z = 0; float w = 0; if (meshDataInfoList[normals].DataType == 13 || meshDataInfoList[normals].DataType == 14) { System.Half h1 = System.Half.ToHalf(br1.ReadUInt16()); System.Half h2 = System.Half.ToHalf(br1.ReadUInt16()); System.Half h3 = System.Half.ToHalf(br1.ReadUInt16()); System.Half h4 = System.Half.ToHalf(br1.ReadUInt16()); x = HalfHelper.HalfToSingle(h1); y = HalfHelper.HalfToSingle(h2); z = HalfHelper.HalfToSingle(h3); w = HalfHelper.HalfToSingle(h4); } else { x = br1.ReadSingle(); y = br1.ReadSingle(); z = br1.ReadSingle(); } var nv = new Vector3(x, y, z); objBytes.Add("vn " + x.ToString("N5") + " " + y.ToString("N5") + " " + z.ToString("N5") + " "); normalList.Add(nv); } } /* * ----------------- * Tangents * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin); int x = br1.ReadByte(); int y = br1.ReadByte(); int z = br1.ReadByte(); int w = br1.ReadByte(); var x1 = x * 2 / 255f - 1f; var y1 = y * 2 / 255f - 1f; var z1 = z * 2 / 255f - 1f; var w1 = w * 2 / 255f - 1f; var nv = new Vector3(x1, y1, z1); tangentList.Add(nv); } } /* * ----------------- * Vertex Color * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin); int a = br1.ReadByte(); int r = br1.ReadByte(); int g = br1.ReadByte(); int b = br1.ReadByte(); colorsList.Add(new Color4(r, g, b, a)); } } /* * ----------------- * Index * ----------------- */ using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData))) { for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3) { int i1 = br1.ReadUInt16(); int i2 = br1.ReadUInt16(); int i3 = br1.ReadUInt16(); objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " "); indexList.Add(i1); indexList.Add(i2); indexList.Add(i3); } } ModelMeshData modelMeshData = new ModelMeshData() { Vertices = vertexList, Normals = normalList, TextureCoordinates = texCoordList, TextureCoordinates2 = texCoordList2, BiTangents = tangentList, Indices = indexList, VertexColors = colorsList, OBJFileData = objBytes.ToArray(), BoneStrings = boneStrings, AttributeStrings = atrStrings, BoneIndices = modelData.BoneIndicies, BoneTransforms = boneTransforms, BlendWeights = blendWeightList, BlendIndices = blendIndicesList, WeightCounts = weightCounts, MeshPartList = mesh.MeshPartList, BlendIndicesArrayList = blendIndicesList2, BlendWeightsArrayList = blendWeightList2, MaterialNum = mesh.MeshInfo.MaterialNum, MeshPartCount = mesh.MeshInfo.MeshPartCount, MeshPartOffset = mesh.MeshInfo.MeshPartOffset }; if (extraIndices2.ContainsKey(i)) { foreach (var id in extraIndices2[i]) { if (!extraVertDict.ContainsKey(id)) { if (modelMeshData.Indices.Count >= id) { var v = 0; try { v = modelMeshData.Indices[id]; } catch { v = 0; } extraVertDict.Add(id, modelMeshData.Vertices[v]); } else { //new Thread(() => MessageBox.Show("There was an error reading the models extra data.\n\n" + // "Mesh " + i + " Index " + id + "\n\n" + // "This is likely caused by parts of a mesh being deleted and may cause crashes in-game.\n\n" + // "Consider using Advanced Import to Fix or Disable Hiding for the above mesh.", // "Extra Data Warning" + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Warning)).Start(); new Thread(() => MessageBox.Show(string.Format(Dialogs.MDLExtraDataWarning, i, id), Dialogs.ExtraDataWarning + Info.appVersion, MessageBoxButtons.OK, MessageBoxIcon.Warning)).Start(); break; } } } } mesh.extraVertDict = extraVertDict; meshList.Add(modelMeshData); } } }
public ONNXTensor(TensorProto onnxTensor) { // read shape var onnxShape = onnxTensor.Dims.ToArray(); var shape = ONNXLayout.ConvertShapeToBarracuda(onnxShape, onnxLayout: "?"); // read data float[] data; if ((onnxTensor.RawData != null) && (!onnxTensor.RawData.IsEmpty)) { var byteArray = new byte[onnxTensor.RawData.Length]; onnxTensor.RawData.CopyTo(byteArray, 0); // Float32 if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float) { data = new float[shape.length]; Debug.Assert((sizeof(float) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, data, 0, byteArray.Length); } // Float16 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Float16) { var typedData = new UInt16[shape.length]; Debug.Assert((sizeof(UInt16) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => HalfHelper.HalfToSingle(x)).ToArray(); } // Int32 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int32) { var typedData = new int[shape.length]; Debug.Assert((sizeof(int) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } // Int64 else if (onnxTensor.DataType == (int)TensorProto.Types.DataType.Int64) { var typedData = new long[shape.length]; Debug.Assert((sizeof(long) * shape.length) == onnxTensor.RawData.Length); Buffer.BlockCopy(byteArray, 0, typedData, 0, byteArray.Length); data = typedData.Select(x => (float)x).ToArray(); } else { throw new OnnxLayerImportException($"Tensor data type {(TensorProto.Types.DataType)onnxTensor.DataType} is not supported."); } } // Float32 else if ((onnxTensor.FloatData != null) && (onnxTensor.FloatData.Count != 0)) { Debug.Assert(shape.length == onnxTensor.FloatData.Count); data = new float[shape.length]; onnxTensor.FloatData.CopyTo(data, 0); } // Int32 else if ((onnxTensor.Int32Data != null) && (onnxTensor.Int32Data.Count != 0)) { Debug.Assert(shape.length == onnxTensor.Int32Data.Count); data = onnxTensor.Int32Data.Select(x => (float)x).ToArray(); } // Int64 else if ((onnxTensor.Int64Data != null) && (onnxTensor.Int64Data.Count != 0)) { Debug.Assert(shape.length == onnxTensor.Int64Data.Count); data = onnxTensor.Int64Data.Select(x => (float)x).ToArray(); } else { throw new OnnxLayerImportException("Could not read tensor data for constant tensor."); } m_Data = new Tensor(shape, new SharedArrayTensorData(data)); m_Shape = onnxShape; }
/// <summary> /// Serialize the message over the network /// </summary> /// <remarks> /// Only sends what it needs. Optionally compresses floats depending on the settings on the SmoothSync object. /// </remarks> /// <param name="writer">The NetworkWriter to write to</param> override public void Serialize(NetworkWriter writer) { // If haven't changed enough since last sent update, we don't want to send out or assign things bool sendPosition = smoothSync.shouldSendPosition(); bool sendVelocity = smoothSync.shouldSendVelocity(); bool sendAngularVelocity = smoothSync.shouldSendAngularVelocity(); bool sendRotation = smoothSync.shouldSendRotation(); // only set last sync states on clients here because server needs to send multiple serializes if (!NetworkServer.active) { if (sendPosition) { smoothSync.lastPositionWhenStateWasSent = state.position; } if (sendVelocity) { smoothSync.lastVelocityWhenStateWasSent = state.velocity; } if (sendAngularVelocity) { smoothSync.lastAngularVelocityWhenStateWasSent = state.angularVelocity; } if (sendRotation) { smoothSync.lastRotationWhenStateWasSent = state.rotation; } } writer.Write(encodeSyncInformation(sendPosition, sendRotation, sendVelocity, sendAngularVelocity)); writer.Write(smoothSync.netId); writer.WritePackedUInt32((uint)smoothSync.syncIndex); writer.WritePackedUInt32((uint)state.ownerTimestamp); // write position if (sendPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { writer.Write(HalfHelper.Compress(state.position.x)); } if (smoothSync.isSyncingYPosition) { writer.Write(HalfHelper.Compress(state.position.y)); } if (smoothSync.isSyncingZPosition) { writer.Write(HalfHelper.Compress(state.position.z)); } } else { if (smoothSync.isSyncingXPosition) { writer.Write(state.position.x); } if (smoothSync.isSyncingYPosition) { writer.Write(state.position.y); } if (smoothSync.isSyncingZPosition) { writer.Write(state.position.z); } } } // write velocity if (sendVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { writer.Write(HalfHelper.Compress(state.velocity.x)); } if (smoothSync.isSyncingYVelocity) { writer.Write(HalfHelper.Compress(state.velocity.y)); } if (smoothSync.isSyncingZVelocity) { writer.Write(HalfHelper.Compress(state.velocity.z)); } } else { if (smoothSync.isSyncingXVelocity) { writer.Write(state.velocity.x); } if (smoothSync.isSyncingYVelocity) { writer.Write(state.velocity.y); } if (smoothSync.isSyncingZVelocity) { writer.Write(state.velocity.z); } } } // write rotation if (sendRotation) { Vector3 rot = state.rotation.eulerAngles; if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { writer.Write(HalfHelper.Compress(rot.x)); } if (smoothSync.isSyncingYRotation) { writer.Write(HalfHelper.Compress(rot.y)); } if (smoothSync.isSyncingZRotation) { writer.Write(HalfHelper.Compress(rot.z)); } } else { if (smoothSync.isSyncingXRotation) { writer.Write(rot.x); } if (smoothSync.isSyncingYRotation) { writer.Write(rot.y); } if (smoothSync.isSyncingZRotation) { writer.Write(rot.z); } } } // write angular velocity if (sendAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { if (smoothSync.isSyncingXAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.x)); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.y)); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.z)); } } else { if (smoothSync.isSyncingXAngularVelocity) { writer.Write(state.angularVelocity.x); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(state.angularVelocity.y); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(state.angularVelocity.z); } } } }
/// <summary> /// Deserialize a message from the network /// </summary> /// <remarks> /// Only receives what it needs. Optionally decompresses floats depending on the settings on the SmoothSync object. /// </remarks> /// <param name="writer">The Networkreader to read from </param> override public void Deserialize(NetworkReader reader) { byte syncInfoByte = reader.ReadByte(); bool syncPosition = shouldSyncPosition(syncInfoByte); bool syncRotation = shouldSyncRotation(syncInfoByte); bool syncVelocity = shouldSyncVelocity(syncInfoByte); bool syncAngularVelocity = shouldSyncAngularVelocity(syncInfoByte); NetworkInstanceId netID = reader.ReadNetworkId(); int syncIndex = (int)reader.ReadPackedUInt32(); state.ownerTimestamp = (int)reader.ReadPackedUInt32(); GameObject ob = null; if (NetworkServer.active) { ob = NetworkServer.FindLocalObject(netID); } else { ob = ClientScene.FindLocalObject(netID); } if (!ob) { Debug.LogWarning("Could not find target for network state message."); return; } // Doesn't matter which SmoothSync is returned since they all have the same list. smoothSync = ob.GetComponent <SmoothSync>(); // Find the correct object to sync according to syncIndex for (int i = 0; i < smoothSync.childObjectSmoothSyncs.Length; i++) { if (smoothSync.childObjectSmoothSyncs[i].syncIndex == syncIndex) { smoothSync = smoothSync.childObjectSmoothSyncs[i]; } } if (!smoothSync) { Debug.LogWarning("Could not find target for network state message."); return; } // read position if (syncPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { state.position.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYPosition) { state.position.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZPosition) { state.position.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXPosition) { state.position.x = reader.ReadSingle(); } if (smoothSync.isSyncingYPosition) { state.position.y = reader.ReadSingle(); } if (smoothSync.isSyncingZPosition) { state.position.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.position = smoothSync.stateBuffer[0].position; } else { state.position = smoothSync.getPosition(); } } // read velocity if (syncVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { state.velocity.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXVelocity) { state.velocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = reader.ReadSingle(); } } } else { state.velocity = Vector3.zero; } // read rotation if (syncRotation) { Vector3 rot = new Vector3(); if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { rot.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYRotation) { rot.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZRotation) { rot.z = HalfHelper.Decompress(reader.ReadUInt16()); } state.rotation = Quaternion.Euler(rot); } else { if (smoothSync.isSyncingXRotation) { rot.x = reader.ReadSingle(); } if (smoothSync.isSyncingYRotation) { rot.y = reader.ReadSingle(); } if (smoothSync.isSyncingZRotation) { rot.z = reader.ReadSingle(); } state.rotation = Quaternion.Euler(rot); } } else { if (smoothSync.stateCount > 0) { state.rotation = smoothSync.stateBuffer[0].rotation; } else { state.rotation = smoothSync.getRotation(); } } // read anguluar velocity if (syncAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { if (smoothSync.isSyncingXAngularVelocity) { state.angularVelocity.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYAngularVelocity) { state.angularVelocity.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZAngularVelocity) { state.angularVelocity.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXAngularVelocity) { state.angularVelocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYAngularVelocity) { state.angularVelocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZAngularVelocity) { state.angularVelocity.z = reader.ReadSingle(); } } } else { state.angularVelocity = Vector3.zero; } }
/// <summary> /// Serialize the message over the network. /// </summary> /// <remarks> /// Only sends what it needs and compresses floats if you chose to. /// </remarks> /// <param name="writer">The NetworkWriter to write to.</param> override public void Serialize(NetworkWriter writer) { bool sendPosition, sendRotation, sendScale, sendVelocity, sendAngularVelocity; // If is a server trying to relay client information back out to other clients. if (NetworkServer.active && !smoothSync.hasAuthority) { sendPosition = state.serverShouldRelayPosition; sendRotation = state.serverShouldRelayRotation; sendScale = state.serverShouldRelayScale; sendVelocity = state.serverShouldRelayVelocity; sendAngularVelocity = state.serverShouldRelayAngularVelocity; } else // If is a server or client trying to send owned object information across the network. { sendPosition = smoothSync.sendPosition; sendRotation = smoothSync.sendRotation; sendScale = smoothSync.sendScale; sendVelocity = smoothSync.sendVelocity; sendAngularVelocity = smoothSync.sendAngularVelocity; } // Only set last sync States on clients here because the server needs to send multiple Serializes. if (!NetworkServer.active) { if (sendPosition) { smoothSync.lastPositionWhenStateWasSent = state.position; } if (sendRotation) { smoothSync.lastRotationWhenStateWasSent = state.rotation; } if (sendScale) { smoothSync.lastScaleWhenStateWasSent = state.scale; } if (sendVelocity) { smoothSync.lastVelocityWhenStateWasSent = state.velocity; } if (sendAngularVelocity) { smoothSync.lastAngularVelocityWhenStateWasSent = state.angularVelocity; } } writer.Write(encodeSyncInformation(sendPosition, sendRotation, sendScale, sendVelocity, sendAngularVelocity)); writer.Write(smoothSync.netID); writer.WritePackedUInt32((uint)smoothSync.syncIndex); writer.WritePackedUInt32((uint)state.ownerTimestamp); // Write position. if (sendPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { writer.Write(HalfHelper.Compress(state.position.x)); } if (smoothSync.isSyncingYPosition) { writer.Write(HalfHelper.Compress(state.position.y)); } if (smoothSync.isSyncingZPosition) { writer.Write(HalfHelper.Compress(state.position.z)); } } else { if (smoothSync.isSyncingXPosition) { writer.Write(state.position.x); } if (smoothSync.isSyncingYPosition) { writer.Write(state.position.y); } if (smoothSync.isSyncingZPosition) { writer.Write(state.position.z); } } } // Write rotation. if (sendRotation) { Vector3 rot = state.rotation.eulerAngles; if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { writer.Write(HalfHelper.Compress(rot.x)); } if (smoothSync.isSyncingYRotation) { writer.Write(HalfHelper.Compress(rot.y)); } if (smoothSync.isSyncingZRotation) { writer.Write(HalfHelper.Compress(rot.z)); } } else { if (smoothSync.isSyncingXRotation) { writer.Write(rot.x); } if (smoothSync.isSyncingYRotation) { writer.Write(rot.y); } if (smoothSync.isSyncingZRotation) { writer.Write(rot.z); } } } // Write scale. if (sendScale) { if (smoothSync.isScaleCompressed) { if (smoothSync.isSyncingXScale) { writer.Write(HalfHelper.Compress(state.scale.x)); } if (smoothSync.isSyncingYScale) { writer.Write(HalfHelper.Compress(state.scale.y)); } if (smoothSync.isSyncingZScale) { writer.Write(HalfHelper.Compress(state.scale.z)); } } else { if (smoothSync.isSyncingXScale) { writer.Write(state.scale.x); } if (smoothSync.isSyncingYScale) { writer.Write(state.scale.y); } if (smoothSync.isSyncingZScale) { writer.Write(state.scale.z); } } } // Write velocity. if (sendVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { writer.Write(HalfHelper.Compress(state.velocity.x)); } if (smoothSync.isSyncingYVelocity) { writer.Write(HalfHelper.Compress(state.velocity.y)); } if (smoothSync.isSyncingZVelocity) { writer.Write(HalfHelper.Compress(state.velocity.z)); } } else { if (smoothSync.isSyncingXVelocity) { writer.Write(state.velocity.x); } if (smoothSync.isSyncingYVelocity) { writer.Write(state.velocity.y); } if (smoothSync.isSyncingZVelocity) { writer.Write(state.velocity.z); } } } // Write angular velocity. if (sendAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { if (smoothSync.isSyncingXAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.x)); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.y)); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(HalfHelper.Compress(state.angularVelocity.z)); } } else { if (smoothSync.isSyncingXAngularVelocity) { writer.Write(state.angularVelocity.x); } if (smoothSync.isSyncingYAngularVelocity) { writer.Write(state.angularVelocity.y); } if (smoothSync.isSyncingZAngularVelocity) { writer.Write(state.angularVelocity.z); } } } }
private static float HalfToFloat(BinaryReaderEx src) { ushort val = src.ReadUInt16(Endianness.BigEndian); return(HalfHelper.HalfToSingle(val)); }
void OnEnable() { shaderSpectrum = (ComputeShader)Resources.Load("EncinoSpectrum", typeof(ComputeShader)); kernelSpectrumInit = shaderSpectrum.FindKernel("EncinoSpectrumInit"); kernelSpectrumUpdate = shaderSpectrum.FindKernel("EncinoSpectrumUpdate"); shaderFFT = (ComputeShader)Resources.Load("EncinoFFT", typeof(ComputeShader)); materialCombine = (Material)Resources.Load("EncinoCombine", typeof(Material)); bufferFFTTemp = new RenderTexture(size, size, 0, RenderTextureFormat.RGFloat); bufferFFTTemp.enableRandomWrite = true; bufferFFTTemp.Create(); bufferSpectrumH0 = new RenderTexture(size, size, 0, RenderTextureFormat.ARGBFloat); bufferSpectrumH0.enableRandomWrite = true; bufferSpectrumH0.Create(); bufferSpectrumH = CreateSpectrumUAV(); bufferSpectrumDx = CreateSpectrumUAV(); bufferSpectrumDy = CreateSpectrumUAV(); bufferHFinal = CreateFinalTexture(); bufferDxFinal = CreateFinalTexture(); bufferDyFinal = CreateFinalTexture(); bufferDisplacement = CreateCombinedTexture(); bufferGradientFold = CreateCombinedTexture(); // Butterfly { int log2Size = Mathf.RoundToInt(Mathf.Log(size, 2)); var butterflyData = new Vector2[size * log2Size]; int offset = 1, numIterations = size >> 1; for (int rowIndex = 0; rowIndex < log2Size; rowIndex++) { int rowOffset = rowIndex * size; // Weights { int start = 0, end = 2 * offset; for (int iteration = 0; iteration < numIterations; iteration++) { float bigK = 0.0f; for (int K = start; K < end; K += 2) { float phase = 2.0f * Mathf.PI * bigK * numIterations / size; float cos = Mathf.Cos(phase); float sin = Mathf.Sin(phase); butterflyData[rowOffset + K / 2].x = cos; butterflyData[rowOffset + K / 2].y = -sin; butterflyData[rowOffset + K / 2 + offset].x = -cos; butterflyData[rowOffset + K / 2 + offset].y = sin; bigK += 1.0f; } start += 4 * offset; end = start + 2 * offset; } } numIterations >>= 1; offset <<= 1; } var butterflyBytes = new byte[butterflyData.Length * sizeof(ushort) * 2]; for (uint i = 0; i < butterflyData.Length; i++) { uint byteOffset = i * sizeof(ushort) * 2; HalfHelper.SingleToHalf(butterflyData[i].x, butterflyBytes, byteOffset); HalfHelper.SingleToHalf(butterflyData[i].y, butterflyBytes, byteOffset + sizeof(ushort)); } texButterfly = new Texture2D(size, log2Size, TextureFormat.RGHalf, false); texButterfly.LoadRawTextureData(butterflyBytes); texButterfly.Apply(false, true); } // Kernel offset { int baseLog2Size = Mathf.RoundToInt(Mathf.Log(256, 2)); int log2Size = Mathf.RoundToInt(Mathf.Log(size, 2)); kernelFFTX = (log2Size - baseLog2Size) * 2; kernelFFTY = kernelFFTX + 1; } // Mesh { mesh = new Mesh(); mesh.name = "EncinoMesh"; float spacing = 1.0f / meshSize; var offset = new Vector3(-0.5f, 0.0f, -0.5f); var vertices = new List <Vector3>(); var uvs = new List <Vector2>(); for (int y = 0; y <= meshSize; y++) { for (int x = 0; x <= meshSize; x++) { vertices.Add(offset + new Vector3(x * spacing, 0.0f, y * spacing)); uvs.Add(new Vector2((float)x / meshSize, (float)y / meshSize)); } for (int x = 0; x < meshSize; x++) { if (y < meshSize) { vertices.Add(offset + new Vector3((x + 0.5f) * spacing, 0.0f, (y + 0.5f) * spacing)); uvs.Add(new Vector2((float)(x + 0.5f) / meshSize, (float)(y + 0.5f) / meshSize)); } } } var triangles = new List <int>(); for (int y = 0; y < meshSize; y++) { for (int x = 0; x < meshSize; x++) { var i0 = y * (meshSize * 2 + 1) + x; var i1 = i0 + 1; var i2 = i0 + (meshSize * 2) + 1; var i3 = i2 + 1; var ic = i0 + meshSize + 1; triangles.Add(i1); triangles.Add(i0); triangles.Add(ic); triangles.Add(i1); triangles.Add(ic); triangles.Add(i3); triangles.Add(ic); triangles.Add(i2); triangles.Add(i3); triangles.Add(i0); triangles.Add(i2); triangles.Add(ic); } } mesh.vertices = vertices.ToArray(); mesh.uv = uvs.ToArray(); mesh.triangles = triangles.ToArray(); mesh.UploadMeshData(false); mesh.RecalculateNormals(); } }
/// <summary> /// Read UVVector2 from file as floats. /// </summary> /// <param name="reader"></param> public void ReadFromFile(BinaryReader reader) { X = HalfHelper.SingleToHalf(reader.ReadSingle()); Y = HalfHelper.SingleToHalf(reader.ReadSingle()); }
/// <summary> /// Write UVVector2 as floats. /// </summary> public void WriteToFile(BinaryWriter writer) { writer.Write(HalfHelper.HalfToSingle(X)); writer.Write(HalfHelper.HalfToSingle(Y)); // writer.Write((Half)1f-Y); }
/// <summary> /// Parses the MDL file to obtain model information /// </summary> /// <param name="selectedItem">The currently selected item</param> /// <param name="selectedRace">The currently selected race</param> /// <param name="selectedBody">The currently selected body</param> /// <param name="selectedPart">The currently selected part</param> /// <param name="selectedCategory">The items category </param> public MDL(ItemData selectedItem, string selectedCategory, string selectedRace, string selectedBody, string selectedPart) { string itemType = Helper.GetCategoryType(selectedCategory); string MDLFolder = ""; if (itemType.Equals("weapon") || itemType.Equals("food")) { if (selectedPart.Equals("Secondary")) { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.SecondaryModelID, selectedItem.SecondaryModelBody); } else { MDLFolder = string.Format(Strings.WeapMDLFolder, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); MDLFile = string.Format(Strings.WeapMDLFile, selectedItem.PrimaryModelID, selectedItem.PrimaryModelBody); } } else if (itemType.Equals("accessory")) { MDLFolder = string.Format(Strings.AccMDLFolder, selectedItem.PrimaryModelID); MDLFile = string.Format(Strings.AccMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } else if (itemType.Equals("character")) { if (selectedItem.ItemName.Equals(Strings.Body)) { MDLFolder = string.Format(Strings.BodyMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.BodyMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Face)) { MDLFolder = string.Format(Strings.FaceMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.FaceMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Hair)) { MDLFolder = string.Format(Strings.HairMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.HairMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } else if (selectedItem.ItemName.Equals(Strings.Tail)) { MDLFolder = string.Format(Strings.TailMDLFolder, selectedRace, selectedBody.PadLeft(4, '0')); MDLFile = string.Format(Strings.TailMDLFile, selectedRace, selectedBody.PadLeft(4, '0'), selectedPart); } } else if (itemType.Equals("monster")) { bool isDemiHuman = false; if (selectedItem.PrimaryMTRLFolder != null) { isDemiHuman = selectedItem.PrimaryMTRLFolder.Contains("demihuman"); } string ID = ""; string body = ""; if (selectedCategory.Equals(Strings.Pets)) { ID = Info.petID[selectedItem.ItemName]; body = "0001"; } else { ID = selectedItem.PrimaryModelID.PadLeft(4, '0'); body = selectedItem.PrimaryModelBody; } if (isDemiHuman) { MDLFolder = string.Format(Strings.DemiMDLFolder, ID, body); MDLFile = string.Format(Strings.DemiMDLFile, ID, body, selectedPart); } else { MDLFolder = string.Format(Strings.MonsterMDLFolder, ID, body); MDLFile = string.Format(Strings.MonsterMDLFile, ID, body); } } else { MDLFolder = string.Format(Strings.EquipMDLFolder, selectedItem.PrimaryModelID); MDLFile = string.Format(Strings.EquipMDLFile, selectedRace, selectedItem.PrimaryModelID, Info.slotAbr[selectedCategory]); } int offset = Helper.GetItemOffset(FFCRC.GetHash(MDLFolder), FFCRC.GetHash(MDLFile)); int datNum = ((offset / 8) & 0x000f) / 2; offset = Helper.OffsetCorrection(datNum, offset); var MDLDatData = Helper.GetType3DecompressedData(offset, datNum); using (BinaryReader br = new BinaryReader(new MemoryStream(MDLDatData.Item1))) { ModelData modelData = new ModelData(); // The size of the header + (size of the mesh information block (136 bytes) * the number of meshes) + padding br.BaseStream.Seek(64 + 136 * MDLDatData.Item2 + 4, SeekOrigin.Begin); var modelStringCount = br.ReadInt32(); var stringBlockSize = br.ReadInt32(); var stringBlock = br.ReadBytes(stringBlockSize); var unknown = br.ReadBytes(4); var totalMeshCount = br.ReadInt16(); var attributeStringCount = br.ReadInt16(); var meshPartsCount = br.ReadInt16(); var materialStringCount = br.ReadInt16(); var boneStringCount = br.ReadInt16(); var boneListCount = br.ReadInt16(); var unknown1 = br.ReadInt16(); var unknown2 = br.ReadInt16(); var unknown3 = br.ReadInt16(); var unknown4 = br.ReadInt16(); var unknown5 = br.ReadInt16(); var unknown6 = br.ReadInt16(); br.ReadBytes(10); var unknown7 = br.ReadInt16(); br.ReadBytes(16); using (BinaryReader br1 = new BinaryReader(new MemoryStream(stringBlock))) { br1.BaseStream.Seek(0, SeekOrigin.Begin); for (int i = 0; i < attributeStringCount; i++) { while (br1.ReadByte() != 0) { //extract each atribute string here } } for (int i = 0; i < boneStringCount; i++) { while (br1.ReadByte() != 0) { //extact each bone string here } } for (int i = 0; i < materialStringCount; i++) { byte b; List <byte> name = new List <byte>(); while ((b = br1.ReadByte()) != 0) { name.Add(b); } string material = Encoding.ASCII.GetString(name.ToArray()); material = material.Replace("\0", ""); materialStrings.Add(material); } } br.ReadBytes(32 * unknown5); for (int i = 0; i < 3; i++) { LevelOfDetail LoD = new LevelOfDetail(); LoD.MeshOffset = br.ReadInt16(); LoD.MeshCount = br.ReadInt16(); br.ReadBytes(40); LoD.VertexDataSize = br.ReadInt32(); LoD.IndexDataSize = br.ReadInt32(); LoD.VertexOffset = br.ReadInt32(); LoD.IndexOffset = br.ReadInt32(); modelData.LoD.Add(LoD); } var savePos = br.BaseStream.Position; for (int i = 0; i < modelData.LoD.Count; i++) { List <MeshDataInfo> meshInfoList = new List <MeshDataInfo>(); for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { modelData.LoD[i].MeshList.Add(new Mesh()); meshInfoList.Clear(); br.BaseStream.Seek((i * 136) + 68, SeekOrigin.Begin); var dataBlockNum = br.ReadByte(); while (dataBlockNum != 255) { MeshDataInfo meshInfo = new MeshDataInfo() { VertexDataBlock = dataBlockNum, Offset = br.ReadByte(), DataType = br.ReadByte(), UseType = br.ReadByte() }; meshInfoList.Add(meshInfo); br.ReadBytes(4); dataBlockNum = br.ReadByte(); } modelData.LoD[i].MeshList[j].MeshDataInfoList = meshInfoList.ToArray(); } } br.BaseStream.Seek(savePos, SeekOrigin.Begin); for (int x = 0; x < modelData.LoD.Count; x++) { for (int i = 0; i < modelData.LoD[x].MeshCount; i++) { MeshInfo meshInfo = new MeshInfo() { VertexCount = br.ReadInt32(), IndexCount = br.ReadInt32(), MaterialNum = br.ReadInt16(), MeshPartOffset = br.ReadInt16(), MeshPartCount = br.ReadInt16(), BoneListIndex = br.ReadInt16(), IndexDataOffset = br.ReadInt32() }; for (int j = 0; j < 3; j++) { meshInfo.VertexDataOffsets.Add(br.ReadInt32()); } for (int k = 0; k < 3; k++) { meshInfo.VertexSizes.Add(br.ReadByte()); } meshInfo.VertexDataBlockCount = br.ReadByte(); modelData.LoD[x].MeshList[i].MeshInfo = meshInfo; } } br.ReadBytes(attributeStringCount * 4); br.ReadBytes(unknown6 * 20); for (int i = 0; i < modelData.LoD.Count; i++) { foreach (var mesh in modelData.LoD[i].MeshList) { for (int j = 0; j < mesh.MeshInfo.MeshPartCount; j++) { MeshPart meshPart = new MeshPart() { IndexOffset = br.ReadInt32(), IndexCount = br.ReadInt32(), Attributes = br.ReadInt32(), BoneOffset = br.ReadInt16(), BoneCount = br.ReadInt16() }; mesh.MeshPartList.Add(meshPart); } } } br.ReadBytes(unknown7 * 12); br.ReadBytes(materialStringCount * 4); br.ReadBytes(boneStringCount * 4); for (int i = 0; i < boneListCount; i++) { Bones bones = new Bones(); for (int j = 0; j < 64; j++) { bones.BoneData.Add(br.ReadInt16()); } bones.BoneCount = br.ReadInt32(); modelData.BoneSet.Add(bones); } br.ReadBytes(unknown1 * 16); br.ReadBytes(unknown2 * 12); br.ReadBytes(unknown3 * 4); var boneIndexSize = br.ReadInt32(); for (int i = 0; i < boneIndexSize / 2; i++) { modelData.BoneIndicies.Add(br.ReadInt16()); } int padding = br.ReadByte(); br.ReadBytes(padding); for (int i = 0; i < 4; i++) { ModelMaterial.BoundingBox boundingBox = new ModelMaterial.BoundingBox(); for (int j = 0; j < 4; j++) { boundingBox.PointA.Add(br.ReadSingle()); } for (int k = 0; k < 4; k++) { boundingBox.PointB.Add(br.ReadSingle()); } modelData.BoundingBoxes.Add(boundingBox); } for (int i = 0; i < 3; i++) { for (int j = 0; j < modelData.LoD[i].MeshCount; j++) { Mesh mesh = modelData.LoD[i].MeshList[j]; for (int k = 0; k < mesh.MeshInfo.VertexDataBlockCount; k++) { br.BaseStream.Seek(modelData.LoD[i].VertexOffset + mesh.MeshInfo.VertexDataOffsets[k], SeekOrigin.Begin); mesh.MeshVertexData.Add(br.ReadBytes(mesh.MeshInfo.VertexSizes[k] * mesh.MeshInfo.VertexCount)); } br.BaseStream.Seek(modelData.LoD[i].IndexOffset + (mesh.MeshInfo.IndexDataOffset * 2), SeekOrigin.Begin); mesh.IndexData = br.ReadBytes(2 * mesh.MeshInfo.IndexCount); } } int vertex = 0, coordinates = 0, normals = 0, tangents = 0, colors = 0; for (int i = 0; i < modelData.LoD[0].MeshCount; i++) { objBytes.Clear(); var vertexList = new Vector3Collection(); var texCoordList = new Vector2Collection(); var normalList = new Vector3Collection(); var tangentList = new Vector3Collection(); var colorsList = new Color4Collection(); var indexList = new IntCollection(); Mesh mesh = modelData.LoD[0].MeshList[i]; MeshDataInfo[] meshDataInfoList = mesh.MeshDataInfoList; int c = 0; foreach (var meshDataInfo in meshDataInfoList) { if (meshDataInfo.UseType == 0) { vertex = c; } else if (meshDataInfo.UseType == 3) { normals = c; } else if (meshDataInfo.UseType == 4) { coordinates = c; } else if (meshDataInfo.UseType == 6) { tangents = c; } else if (meshDataInfo.UseType == 7) { colors = c; } c++; } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[vertex].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[vertex].VertexDataBlock] + meshDataInfoList[vertex].Offset, SeekOrigin.Begin); if (meshDataInfoList[vertex].DataType == 13 || meshDataInfoList[vertex].DataType == 14) { System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16()); float x = HalfHelper.HalfToSingle(h1); float y = HalfHelper.HalfToSingle(h2); float z = HalfHelper.HalfToSingle(h3); objBytes.Add("v " + x.ToString() + " " + y.ToString() + " " + z.ToString() + " "); vertexList.Add(new Vector3(x, y, z)); } else if (meshDataInfoList[vertex].DataType == 2) { float x = br1.ReadSingle(); float y = br1.ReadSingle(); float z = br1.ReadSingle(); objBytes.Add("v " + x.ToString() + " " + y.ToString() + " " + z.ToString() + " "); vertexList.Add(new Vector3(x, y, z)); } } } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[coordinates].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[coordinates].VertexDataBlock] + meshDataInfoList[coordinates].Offset, SeekOrigin.Begin); System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16()); float x = HalfHelper.HalfToSingle(h1); float y = HalfHelper.HalfToSingle(h2); objBytes.Add("vt " + x.ToString() + " " + (y * -1f).ToString() + " "); texCoordList.Add(new Vector2(x, y)); } } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[normals].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[normals].VertexDataBlock] + meshDataInfoList[normals].Offset, SeekOrigin.Begin); System.Half h1 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h2 = System.Half.ToHalf((ushort)br1.ReadInt16()); System.Half h3 = System.Half.ToHalf((ushort)br1.ReadInt16()); objBytes.Add("vn " + HalfHelper.HalfToSingle(h1).ToString() + " " + HalfHelper.HalfToSingle(h2).ToString() + " " + HalfHelper.HalfToSingle(h3).ToString() + " "); normalList.Add(new Vector3(HalfHelper.HalfToSingle(h1), HalfHelper.HalfToSingle(h2), HalfHelper.HalfToSingle(h3))); } } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[tangents].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[tangents].VertexDataBlock] + meshDataInfoList[tangents].Offset, SeekOrigin.Begin); float x = br1.ReadByte() / 255f; float y = br1.ReadByte() / 255f; float z = br1.ReadByte() / 255f; tangentList.Add(new Vector3(x, y, z)); } } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.MeshVertexData[meshDataInfoList[colors].VertexDataBlock]))) { for (int j = 0; j < mesh.MeshInfo.VertexCount; j++) { br1.BaseStream.Seek(j * mesh.MeshInfo.VertexSizes[meshDataInfoList[colors].VertexDataBlock] + meshDataInfoList[colors].Offset, SeekOrigin.Begin); int a = br1.ReadByte(); int r = br1.ReadByte(); int g = br1.ReadByte(); int b = br1.ReadByte(); colorsList.Add(new Color4(r, g, b, a)); } } using (BinaryReader br1 = new BinaryReader(new MemoryStream(mesh.IndexData))) { for (int j = 0; j < mesh.MeshInfo.IndexCount; j += 3) { int i1 = br1.ReadInt16(); int i2 = br1.ReadInt16(); int i3 = br1.ReadInt16(); objBytes.Add("f " + (i1 + 1) + "/" + (i1 + 1) + "/" + (i1 + 1) + " " + (i2 + 1) + "/" + (i2 + 1) + "/" + (i2 + 1) + " " + (i3 + 1) + "/" + (i3 + 1) + "/" + (i3 + 1) + " "); indexList.Add(i1); indexList.Add(i2); indexList.Add(i3); } } ModelMeshData modelMeshData = new ModelMeshData() { Vertices = vertexList, Normals = normalList, TextureCoordinates = texCoordList, Tangents = tangentList, Indices = indexList, VertexColors = colorsList, OBJFileData = objBytes.ToArray() }; meshList.Add(modelMeshData); } } }
/// <summary> /// Deserialize a message from the network. /// </summary> /// <remarks> /// Only receives what it needs and decompresses floats if you chose to. /// </remarks> public static NetworkStateMirror Deserialize(this NetworkReader reader) { var msg = new NetworkStateMirror(); msg.state = new StateMirror(); var state = msg.state; // The first received byte tells us what we need to be syncing. byte syncInfoByte = reader.ReadByte(); bool syncPosition = shouldSyncPosition(syncInfoByte); bool syncRotation = shouldSyncRotation(syncInfoByte); bool syncScale = shouldSyncScale(syncInfoByte); bool syncVelocity = shouldSyncVelocity(syncInfoByte); bool syncAngularVelocity = shouldSyncAngularVelocity(syncInfoByte); state.atPositionalRest = shouldBeAtPositionalRest(syncInfoByte); state.atRotationalRest = shouldBeAtRotationalRest(syncInfoByte); NetworkIdentity networkIdentity = reader.ReadNetworkIdentity(); if (networkIdentity == null) { Debug.LogWarning("Could not find target for network StateMirror message."); return(new NetworkStateMirror()); } uint netID = networkIdentity.netId; int syncIndex = (int)reader.ReadUInt32(); state.ownerTimestamp = reader.ReadSingle(); // Find the GameObject GameObject ob = NetworkIdentity.spawned[netID].gameObject; if (!ob) { Debug.LogWarning("Could not find target for network StateMirror message."); return(new NetworkStateMirror()); } // It doesn't matter which SmoothSync is returned since they all have the same list. msg.smoothSync = ob.GetComponent <SmoothSyncMirror>(); if (!msg.smoothSync) { Debug.LogWarning("Could not find target for network StateMirror message."); return(new NetworkStateMirror()); } // Find the correct object to sync according to the syncIndex. for (int i = 0; i < msg.smoothSync.childObjectSmoothSyncs.Length; i++) { if (msg.smoothSync.childObjectSmoothSyncs[i].syncIndex == syncIndex) { msg.smoothSync = msg.smoothSync.childObjectSmoothSyncs[i]; } } var smoothSync = msg.smoothSync; state.receivedTimestamp = smoothSync.localTime; // If we want the server to relay non-owned object information out to other clients, set these variables so we know what we need to send. if (NetworkServer.active && !smoothSync.hasControl) { state.serverShouldRelayPosition = syncPosition; state.serverShouldRelayRotation = syncRotation; state.serverShouldRelayScale = syncScale; state.serverShouldRelayVelocity = syncVelocity; state.serverShouldRelayAngularVelocity = syncAngularVelocity; } if (smoothSync.receivedStatesCounter < smoothSync.sendRate) { smoothSync.receivedStatesCounter++; } // Read position. if (syncPosition) { if (smoothSync.isPositionCompressed) { if (smoothSync.isSyncingXPosition) { state.position.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYPosition) { state.position.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZPosition) { state.position.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXPosition) { state.position.x = reader.ReadSingle(); } if (smoothSync.isSyncingYPosition) { state.position.y = reader.ReadSingle(); } if (smoothSync.isSyncingZPosition) { state.position.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.position = smoothSync.stateBuffer[0].position; } else { state.position = smoothSync.getPosition(); } } // Read rotation. if (syncRotation) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isRotationCompressed) { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.rotation = Quaternion.Euler(state.reusableRotationVector); } else { if (smoothSync.isSyncingXRotation) { state.reusableRotationVector.x = reader.ReadSingle(); } if (smoothSync.isSyncingYRotation) { state.reusableRotationVector.y = reader.ReadSingle(); } if (smoothSync.isSyncingZRotation) { state.reusableRotationVector.z = reader.ReadSingle(); } state.rotation = Quaternion.Euler(state.reusableRotationVector); } } else { if (smoothSync.stateCount > 0) { state.rotation = smoothSync.stateBuffer[0].rotation; } else { state.rotation = smoothSync.getRotation(); } } // Read scale. if (syncScale) { if (smoothSync.isScaleCompressed) { if (smoothSync.isSyncingXScale) { state.scale.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYScale) { state.scale.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZScale) { state.scale.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXScale) { state.scale.x = reader.ReadSingle(); } if (smoothSync.isSyncingYScale) { state.scale.y = reader.ReadSingle(); } if (smoothSync.isSyncingZScale) { state.scale.z = reader.ReadSingle(); } } } else { if (smoothSync.stateCount > 0) { state.scale = smoothSync.stateBuffer[0].scale; } else { state.scale = smoothSync.getScale(); } } // Read velocity. if (syncVelocity) { if (smoothSync.isVelocityCompressed) { if (smoothSync.isSyncingXVelocity) { state.velocity.x = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = HalfHelper.Decompress(reader.ReadUInt16()); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = HalfHelper.Decompress(reader.ReadUInt16()); } } else { if (smoothSync.isSyncingXVelocity) { state.velocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYVelocity) { state.velocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZVelocity) { state.velocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedVelocity = state.velocity; } else { // If we didn't receive an updated velocity, use the latest received velocity. state.velocity = smoothSync.latestReceivedVelocity; } // Read anguluar velocity. if (syncAngularVelocity) { if (smoothSync.isAngularVelocityCompressed) { state.reusableRotationVector = Vector3.zero; if (smoothSync.isSyncingXAngularVelocity) { state.reusableRotationVector.x = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.x *= Mathf.Rad2Deg; } if (smoothSync.isSyncingYAngularVelocity) { state.reusableRotationVector.y = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.y *= Mathf.Rad2Deg; } if (smoothSync.isSyncingZAngularVelocity) { state.reusableRotationVector.z = HalfHelper.Decompress(reader.ReadUInt16()); state.reusableRotationVector.z *= Mathf.Rad2Deg; } state.angularVelocity = state.reusableRotationVector; } else { if (smoothSync.isSyncingXAngularVelocity) { state.angularVelocity.x = reader.ReadSingle(); } if (smoothSync.isSyncingYAngularVelocity) { state.angularVelocity.y = reader.ReadSingle(); } if (smoothSync.isSyncingZAngularVelocity) { state.angularVelocity.z = reader.ReadSingle(); } } smoothSync.latestReceivedAngularVelocity = state.angularVelocity; } else { // If we didn't receive an updated angular velocity, use the latest received angular velocity. state.angularVelocity = smoothSync.latestReceivedAngularVelocity; } // Update new owner information sent from the Server. if (smoothSync.isSmoothingAuthorityChanges && !NetworkServer.active) { smoothSync.ownerChangeIndicator = (int)reader.ReadByte(); } if (smoothSync.automaticallyResetTime) { state.localTimeResetIndicator = (int)reader.ReadByte(); } return(msg); }