public abstract GenericX Decompress(CompressedElement comp);
// Construct public Frame(NetworkSyncTransform _nst, NSTElementsEngine _nstElementsEngine, int index, Vector3 _pos, CompressedElement _compPos, Quaternion _rot) //, PositionElement[] positionElements, RotationElement[] rotationElements) { nst = _nst; nstElementsEngine = _nstElementsEngine; rootPos = _pos; compPos = _compPos; int numbOfElements = nstElementsEngine.transformElements.Length; elements = new List <XElement>(numbOfElements); for (int eid = 0; eid < numbOfElements; eid++) { elements.Add(new XElement( nstElementsEngine.transformElements[eid].Localized, nstElementsEngine.transformElements[eid].Compress(), false, nstElementsEngine.transformElements[eid] )); } frameid = index; customData = new byte[128]; //TODO: Make this size a user setting }
public static CompressedElement OverwriteLowerBits(CompressedElement upperbits, CompressedElement lowerbits) { return(new CompressedElement ( axisRanges[0].ZeroLowerBits(upperbits[0]) | lowerbits[0], axisRanges[1].ZeroLowerBits(upperbits[1]) | lowerbits[1], axisRanges[2].ZeroLowerBits(upperbits[2]) | lowerbits[2] )); }
public override void WriteToBitstream(ref UdpBitStream bitstream, MsgType msgType, bool forceUpdate, bool isKeyframe) { // Base class does some forceUpdate checking, keep it around. //forceUpdate = base.WriteToBitstream(ref bitstream, msgType, forceUpdate); //bool hasChanged = false; if (rotationType == XType.Quaternion) { ulong compressedQuat = QuatCompress.CompressQuatToBitsBuffer(Localized, totalBitsForQuat); // For frames between forced updates, we need to first send a flag bit for if this element is being sent if (!forceUpdate) { bool hasChanged = compressedQuat != lastSentCompressed; bitstream.WriteBool(hasChanged); // if no changes have occured we are done. if (!hasChanged) { return; } } bitstream.WriteULong(compressedQuat, totalBitsForQuat); lastSentCompressed = compressedQuat; return; } else { // Euler types... CompressedElement newValues = new CompressedElement(0, 0, 0); // populate the new compressed position, and test if any of the axes have changed. for (int axis = 0; axis < 3; axis++) { if (rotationType.IsXYZ(axis)) { newValues[axis] = CompressFloat(((Vector3)Localized)[axis], axis); } } // For frames between forced updates, we need to first send a flag bit for if this element is being sent if (!forceUpdate) { bool hasChanged = !CompressedElement.Compare(newValues, lastSentCompressed); bitstream.WriteBool(hasChanged); // if no changes have occured we are done. if (!hasChanged) { return; } } for (int axis = 0; axis < 3; axis++) { if (rotationType.IsXYZ(axis)) { bitstream.WriteUInt(newValues[axis], xyzBits[axis]); lastSentCompressed[axis] = newValues[axis]; } } } }
public static CompressedElement OverwriteLowerBits(CompressedElement upperbits, CompressedElement lowerbits) { //Debug.Log("upperx " + ((upperbits.x >> lowerBitcount[0]) << lowerBitcount[0]) + " lowerx " + lowerbits.x + " result " + (((upperbits.x >> lowerBitcount[0]) << lowerBitcount[0]) | lowerbits.x)); return(new CompressedElement ( AxisRanges(0).ZeroLowerBits(upperbits[0]) | lowerbits[0], AxisRanges(1).ZeroLowerBits(upperbits[1]) | lowerbits[1], AxisRanges(2).ZeroLowerBits(upperbits[2]) | lowerbits[2] )); }
/// <summary> /// Attempts to guess the most likely upperbits state by seeing if each axis of the new position would be /// closer to the old one if the upper bit is incremented by one, two, three etc. Stops trying when it fails to get a better result than the last increment. /// </summary> /// <param name="oldcpos">Last best position test against.</param> /// <returns>Returns a corrected CompressPos</returns> public static CompressedElement GuessUpperBitsWorld(this CompressedElement newcpos, CompressedElement oldcpos) { return(newcpos.GuessUpperBits(oldcpos, axisRanges)); }
public static void Copy(CompressedElement source, CompressedElement target) { target.x = source.x; target.y = source.y; target.z = source.z; }
//public static CompressedPos GuessUpperBitsOld(CompressedPos oldcpos, CompressedPos newcpos) //{ // CompressedPos bestGuess = new CompressedPos(); // CompressedPos oldUppers = oldcpos.ZeroLowerBits(); // for (int i = 0; i < 3; i++) // { // uint original = newcpos[i] | oldUppers[i]; // // guess if the upperbits increased or decreased based on whether lower bits were a high or low number // uint prevLowers = oldcpos[i] & maxValue[lowerBitcount[i]]; // uint midwayValue = maxValue[lowerBitcount[i] - 1]; // // value that will increase or decrease the upperbits by one // int increment = (prevLowers > midwayValue) ? (1 << lowerBitcount[i]) : -(1 << lowerBitcount[i]); // uint offset = newcpos[i] | (oldUppers[i] + increment); // int distorig = Mathf.Abs(oldcpos[i] - original); // int distoffs = Mathf.Abs(oldcpos[i] - offset); // bestGuess[i] = (distorig < distoffs) ? original : offset; // if (distorig > distoffs) Debug.Log("Used guess "); // } // return bestGuess; //} /// <summary> /// Attempts to guess the most likely upperbits state by seeing if each axis of the new position would be /// closer to the old one if the upper bit is incremented by one, two, three etc. Stops trying when it fails to get a better result than the last increment. /// </summary> /// <param name="oldcpos">Last best position test against.</param> /// <returns>Returns a corrected CompressPos</returns> public static CompressedElement GuessUpperBits(this CompressedElement newcpos, CompressedElement oldcpos) { CompressedElement oldUppers = oldcpos.ZeroLowerBits(); CompressedElement newLowers = newcpos.ZeroUpperBits(); CompressedElement bestGuess = oldUppers + newLowers; for (int i = 0; i < 3; i++) { // value that will increase or decrease the upperbits by one uint increment = ((uint)1 << AxisRanges(i).lowerBits); int multiplier = 1; // start by just applying the old uppers to the new lowers. This is the distance to beat. //uint lastguess = oldUppers[i] | newLowers[i]; long lastguessdist = System.Math.Abs((long)bestGuess[i] - oldcpos[i]); bool lookup = true; bool lookdn = true; while (multiplier < 10) { if (lookup) { uint guessup = bestGuess[i] + increment; long updist = guessup - oldcpos[i]; if (updist < lastguessdist) { bestGuess[i] = guessup; lastguessdist = updist; lookdn = false; continue; } } if (lookdn) { uint guessdn = (uint)((long)bestGuess[i] - increment); long dndist = (long)oldcpos[i] - guessdn; if (dndist < lastguessdist) { bestGuess[i] = guessdn; lastguessdist = dndist; lookup = false; continue; } } // No improvements found, we are done looking. break; //multiplier++; //Debug.Log("increment " + ((uint)(increment * multiplier)).PrintBitMask(lowerBitcount[i])); //Debug.Log("oldpositn " + oldcpos[i].PrintBitMask(lowerBitcount[i])); //Debug.Log("lastguess " + lastguess.PrintBitMask(lowerBitcount[i])); //Debug.Log(" - - - -"); } //bestGuess[i] = lastguess; } return(bestGuess); }
/// <summary> /// Basic compare of the X, Y, Z, and W values. True if they all match. /// </summary> public static bool Compare(CompressedElement a, CompressedElement b) { return(a.x == b.x && a.y == b.y && a.z == b.z); }
/// <summary> /// Replace the upperbits of the first compressed element with the upper bits of the second, using BitCullingLevel as the separation point. /// </summary> public static CompressedElement OverwriteUpperBits(this CompressedElement low, CompressedElement up, FloatRange[] ranges, BitCullingLevel bcl) { return(new CompressedElement( ranges[0].OverwriteUpperBits(low.x, up.x, bcl), ranges[1].OverwriteUpperBits(low.y, up.y, bcl), ranges[2].OverwriteUpperBits(low.z, up.z, bcl) )); }
/// <summary> /// Alternative to OverwriteUpperBits that attempts to guess the upperbits by seeing if each axis of the new position would be /// closer to the old one if the upper bit is incremented by one, two, three etc. Stops trying when it fails to get a better result. /// </summary> /// <param name="oldcpos">Last best position test against.</param> /// <returns>Returns a corrected CompressPos</returns> public static CompressedElement GuessUpperBits(this CompressedElement newcpos, CompressedElement oldcpos, FloatRange[] axesranges, BitCullingLevel bcl) { return(new CompressedElement( axesranges[0].GuessUpperBits(newcpos[0], oldcpos[0], bcl), axesranges[1].GuessUpperBits(newcpos[1], oldcpos[1], bcl), axesranges[2].GuessUpperBits(newcpos[2], oldcpos[2], bcl) )); }
/// <summary> /// Test changes between two compressed Vector3 elements and return the ideal BitCullingLevel for that change. /// </summary> public static BitCullingLevel GetGuessableBitCullLevel(CompressedElement oldComp, CompressedElement newComp, FloatRange[] fr, BitCullingLevel maxCullLvl) { for (BitCullingLevel lvl = maxCullLvl; lvl > 0; lvl--) { // Starting guess is the new lower bits using the previous upperbits if (Compare(newComp, (oldComp.ZeroLowerBits(lvl) | newComp.ZeroUpperBits(lvl)))) { return(lvl); } } return(BitCullingLevel.NoCulling); }
/// <summary> /// It is preferable to use the overload that takes and int divisor value than a float, to avoid all float math. /// </summary> public static CompressedElement Extrapolate(CompressedElement curr, CompressedElement prev, float amount = .5f) { int divisor = (int)(1f / amount); return(Extrapolate(curr, prev, divisor)); }