folderchange
This commit is contained in:
8
Assets/Plugins/HybridIK.meta
Normal file
8
Assets/Plugins/HybridIK.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81f481468a087c74ea3a326fd2fc33e1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Plugins/HybridIK/Scripts.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2a7b4351f0a477479c2cf11d971bb3e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Plugins/HybridIK/Scripts/Joint Limits.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts/Joint Limits.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe1091a74ea67954db55dd73a0be5dab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,223 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AshqarApps.DynamicJoint
|
||||
{
|
||||
public class DynamicJointLimit : MonoBehaviour
|
||||
{
|
||||
public bool enable = true;
|
||||
|
||||
[Header("Main")]
|
||||
public Vector3 mainAxis = Vector3.forward;
|
||||
|
||||
[HideInInspector]
|
||||
public Vector3 secondaryAxis = Vector3.up;
|
||||
[HideInInspector]
|
||||
public Vector3 crossAxis { get { return Vector3.Cross(mainAxis, secondaryAxis); } }
|
||||
|
||||
[HideInInspector] public Quaternion zeroRotation;
|
||||
public bool zeroRotationOverride { get; private set; }
|
||||
|
||||
public Vector3 limitsOffset;
|
||||
|
||||
private bool initialized;
|
||||
private bool applicationQuit;
|
||||
private bool zeroRotationSet;
|
||||
|
||||
protected bool isClampedToLimit = false;
|
||||
|
||||
/// <summary>
|
||||
/// The swing limit.
|
||||
/// </summary>
|
||||
[Range(0f, 180f)] public float limitAngle = 45;
|
||||
|
||||
public bool applyEveryFrame = false;
|
||||
|
||||
//[Header("Dynamics")]
|
||||
|
||||
[HideInInspector]
|
||||
public float bounce = 0;
|
||||
[HideInInspector]
|
||||
public float friction = 0;
|
||||
|
||||
/*
|
||||
* Applies uniform twist limit to the rotation
|
||||
* */
|
||||
protected Quaternion LimitTwist(Quaternion rotation, Vector3 axis, Vector3 orthoAxis, float twistLimit)
|
||||
{
|
||||
twistLimit = Mathf.Clamp(twistLimit, 0, 180);
|
||||
if (twistLimit >= 180) return rotation;
|
||||
|
||||
Vector3 normal = rotation * axis;
|
||||
Vector3 orthoTangent = orthoAxis;
|
||||
Vector3.OrthoNormalize(ref normal, ref orthoTangent);
|
||||
|
||||
Vector3 rotatedOrthoTangent = rotation * orthoAxis;
|
||||
Vector3.OrthoNormalize(ref normal, ref rotatedOrthoTangent);
|
||||
|
||||
Quaternion fixedRotation = Quaternion.FromToRotation(rotatedOrthoTangent, orthoTangent) * rotation;
|
||||
|
||||
if (twistLimit <= 0) return fixedRotation;
|
||||
|
||||
float twistAngle = Quaternion.Angle(fixedRotation, rotation);
|
||||
if (twistAngle >= twistLimit)
|
||||
{
|
||||
isClampedToLimit = true;
|
||||
}
|
||||
|
||||
// Rotate from zero twist to free twist by the limited angle
|
||||
return Quaternion.RotateTowards(fixedRotation, rotation, twistLimit);
|
||||
}
|
||||
|
||||
public virtual Vector3 GetStretchAxis()
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
public virtual Vector3 GetMainAxisWorld()
|
||||
{
|
||||
return Direction(mainAxis);
|
||||
}
|
||||
|
||||
public virtual Quaternion LimitRotation(Quaternion rotation, float jointLimitStrength = 1)
|
||||
{
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public virtual Vector3 GetMidVectorWorld()
|
||||
{
|
||||
return mainAxis;
|
||||
}
|
||||
|
||||
protected Vector3 Direction(Vector3 v)
|
||||
{
|
||||
if (transform.parent == null) return zeroRotation * v;
|
||||
return transform.parent.rotation * (zeroRotation * v);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the limited local rotation.
|
||||
/// </summary>
|
||||
public Quaternion GetLimitedLocalRotation(Quaternion localRotation, out bool changed, float jointLimitStrength = 1)
|
||||
{
|
||||
// Making sure the Rotation Limit is initiated
|
||||
if (!initialized) Awake();
|
||||
|
||||
// Subtracting defaultLocalRotation
|
||||
Quaternion rotation = Quaternion.Inverse(zeroRotation) * localRotation;
|
||||
|
||||
Quaternion limitedRotation = LimitRotation(rotation);
|
||||
#if UNITY_2018_3_OR_NEWER
|
||||
limitedRotation = Quaternion.Normalize(limitedRotation);
|
||||
#endif
|
||||
changed = limitedRotation != rotation;
|
||||
|
||||
if (!changed) return localRotation;
|
||||
|
||||
// Apply defaultLocalRotation back on
|
||||
return zeroRotation * limitedRotation;
|
||||
}
|
||||
|
||||
public float EvaluateSwingLimitAtOrthoAngle(float angle)
|
||||
{
|
||||
float sinAngle = Mathf.Abs(Mathf.Sin(Mathf.Deg2Rad * angle));
|
||||
//return sinAngle;
|
||||
return (sinAngle * limitAngle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply the rotation limit to transform.localRotation. Returns true if the limit has changed the rotation.
|
||||
/// </summary>
|
||||
public virtual bool Apply(float jointLimitStrength = 1)
|
||||
{
|
||||
isClampedToLimit = false;
|
||||
|
||||
if (jointLimitStrength == 0 || !enable)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
Quaternion targetRot = GetLimitedLocalRotation(transform.localRotation, out changed);
|
||||
|
||||
if (changed)
|
||||
{
|
||||
if (jointLimitStrength < 1)
|
||||
{
|
||||
float angle = Quaternion.Angle(transform.localRotation, targetRot);
|
||||
|
||||
Quaternion easedRotation = Quaternion.RotateTowards(transform.localRotation, targetRot, angle * jointLimitStrength);
|
||||
|
||||
transform.localRotation = easedRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localRotation = targetRot;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable this instance making sure it is initiated. Use this if you intend to manually control the updating of this Rotation Limit.
|
||||
/// </summary>
|
||||
public void Disable()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Awake();
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
public void SetZeroRotation()
|
||||
{
|
||||
zeroRotation = transform.localRotation;
|
||||
zeroRotationSet = true;
|
||||
zeroRotationOverride = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map the zero rotation point to the specified rotation.
|
||||
/// </summary>
|
||||
public void SetZeroRotation(Quaternion localRotation)
|
||||
{
|
||||
zeroRotation = localRotation;
|
||||
zeroRotationSet = true;
|
||||
zeroRotationOverride = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the angle between two vectors on a plane with the specified normal
|
||||
* */
|
||||
public static float GetOrthogonalAngle(Vector3 v1, Vector3 v2, Vector3 normal)
|
||||
{
|
||||
Vector3.OrthoNormalize(ref normal, ref v1);
|
||||
Vector3.OrthoNormalize(ref normal, ref v2);
|
||||
return Vector3.Angle(v1, v2);
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
if (applyEveryFrame)
|
||||
Apply();
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Store the local rotation to map the zero rotation point to the current rotation
|
||||
if (!zeroRotationSet) SetZeroRotation();
|
||||
|
||||
if (mainAxis == Vector3.zero)
|
||||
{
|
||||
Debug.LogError("Axis is Vector3.zero.");
|
||||
mainAxis = Vector3.forward;
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4d18e67185065d4e871e8f6eb899138
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Joint Limits/DynamicJointLimit.cs
|
||||
uploadId: 532533
|
||||
@@ -0,0 +1,100 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AshqarApps.DynamicJoint
|
||||
{
|
||||
public class DynamicJointLimitHinge : DynamicJointLimit
|
||||
{
|
||||
[Header("Hinge Limits")]
|
||||
[Range(0f, 360f)]
|
||||
public float hingeAngleOffset = 0;
|
||||
|
||||
public Vector3 cross = Vector3.up;
|
||||
|
||||
private Quaternion lastRotation = Quaternion.identity;
|
||||
|
||||
public override Vector3 GetMainAxisWorld()
|
||||
{
|
||||
Quaternion offsetRot = Quaternion.Euler(limitsOffset);
|
||||
Vector3 offsetSwingAxis = (offsetRot * this.mainAxis).normalized;
|
||||
return Direction(offsetSwingAxis);
|
||||
}
|
||||
|
||||
public override Vector3 GetStretchAxis()
|
||||
{
|
||||
return GetMainAxisWorld();
|
||||
}
|
||||
|
||||
public override Vector3 GetMidVectorWorld()
|
||||
{
|
||||
return GetPlaneAxisWorld();
|
||||
}
|
||||
|
||||
public Vector3 GetPlaneAxisWorld()
|
||||
{
|
||||
Quaternion offsetRot = Quaternion.Euler(limitsOffset);
|
||||
Vector3 swing = Direction(offsetRot * mainAxis.normalized);
|
||||
|
||||
Vector3 secondaryAxis = new Vector3(mainAxis.y, mainAxis.z, mainAxis.x);
|
||||
Vector3 cross = Direction(Vector3.Cross(mainAxis, secondaryAxis));
|
||||
cross = Direction(offsetRot * this.cross);
|
||||
Quaternion hingeOffset = Quaternion.AngleAxis(hingeAngleOffset, swing);
|
||||
return hingeOffset * cross;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the hinge rotation limit
|
||||
* */
|
||||
public Quaternion LimitHinge(Quaternion rotation)
|
||||
{
|
||||
Quaternion offsetRot = Quaternion.Euler(limitsOffset);
|
||||
|
||||
Vector3 offsetSwingAxis = (offsetRot * this.mainAxis);
|
||||
Vector3 offsetSecondaryAxis = (offsetRot * this.cross);
|
||||
Vector3.OrthoNormalize(ref offsetSwingAxis, ref offsetSecondaryAxis);
|
||||
Vector3 offsetCrossAxis = Vector3.Cross(offsetSwingAxis, offsetSecondaryAxis);
|
||||
|
||||
Quaternion hingeOffset = Quaternion.AngleAxis(hingeAngleOffset, offsetSwingAxis);
|
||||
Quaternion minRotation = Quaternion.AngleAxis(-limitAngle, offsetSwingAxis) * hingeOffset;
|
||||
Quaternion maxRotation = Quaternion.AngleAxis(limitAngle, offsetSwingAxis) * hingeOffset;
|
||||
|
||||
// Get 1 degree of freedom rotation along axis
|
||||
Quaternion free1DOFTarget = Quaternion.FromToRotation(rotation * offsetSwingAxis, offsetSwingAxis) * rotation;
|
||||
|
||||
if (limitAngle >= 180)
|
||||
return free1DOFTarget;
|
||||
|
||||
float midLimit = (limitAngle >= 90f) ? 180 - limitAngle : limitAngle;
|
||||
Quaternion free1DOFMid = Quaternion.RotateTowards(minRotation, maxRotation, midLimit);
|
||||
if (limitAngle >= 90f)
|
||||
{
|
||||
Quaternion flip180 = Quaternion.AngleAxis(180, offsetSwingAxis);
|
||||
free1DOFMid *= flip180;
|
||||
}
|
||||
|
||||
Quaternion lastRotation = free1DOFTarget;
|
||||
|
||||
float angle = Quaternion.Angle(free1DOFTarget, free1DOFMid);
|
||||
Quaternion clampedFree1DOF = Quaternion.RotateTowards(free1DOFMid, free1DOFTarget, limitAngle);
|
||||
|
||||
isClampedToLimit = angle >= limitAngle;
|
||||
|
||||
return clampedFree1DOF;
|
||||
|
||||
}
|
||||
|
||||
public override Quaternion LimitRotation(Quaternion rotation, float jointLimitStrength = 1)
|
||||
{
|
||||
lastRotation = LimitHinge(rotation);
|
||||
return lastRotation;
|
||||
}
|
||||
|
||||
public override bool Apply(float jointLimitStrength = 1)
|
||||
{
|
||||
bool hasChanged = base.Apply(jointLimitStrength);
|
||||
return isClampedToLimit;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c7a022be76393744b9f1a13d09311ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Joint Limits/DynamicJointLimitHinge.cs
|
||||
uploadId: 532533
|
||||
@@ -0,0 +1,174 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AshqarApps.DynamicJoint
|
||||
{
|
||||
public class DynamicJointLimitSwingTwist : DynamicJointLimit
|
||||
{
|
||||
[Header("Swing Twist Limits")]
|
||||
[Range(0f, 180f)] public float twistLimit = 45;
|
||||
|
||||
[Range(0f, 1f)] public float limitWidthRatio = 1;
|
||||
[Range(0f, 1f)] public float limitHeightRatio = 1;
|
||||
|
||||
public Quaternion LimitSwing(Quaternion rotation, bool visualizeMode = false)
|
||||
{
|
||||
if (this.mainAxis == Vector3.zero) return rotation; // Ignore with zero axes
|
||||
//if (rotation == Quaternion.identity) return rotation; // Assuming initial rotation is in the reachable area
|
||||
|
||||
Quaternion offsetRot = Quaternion.Euler(limitsOffset);
|
||||
if (visualizeMode)
|
||||
{
|
||||
offsetRot = Quaternion.identity;
|
||||
}
|
||||
|
||||
Vector3 offsetSwingAxis = (offsetRot * this.mainAxis).normalized;
|
||||
Vector3 offsetSecondaryAxis = (offsetRot * this.secondaryAxis).normalized;
|
||||
Vector3.OrthoNormalize(ref offsetSwingAxis, ref offsetSecondaryAxis);
|
||||
Vector3 offsetCrossAxis = Vector3.Cross(offsetSwingAxis, offsetSecondaryAxis);
|
||||
|
||||
Vector3 targetSwing = rotation * mainAxis;
|
||||
|
||||
float angle = Vector3.SignedAngle(offsetSwingAxis, targetSwing, Vector3.Cross(offsetSwingAxis, targetSwing));
|
||||
Vector3 unlimitedTargetSwing = targetSwing;
|
||||
|
||||
float maxAngle = angle > 0 ? limitAngle : -limitAngle;
|
||||
Quaternion maxRotation = Quaternion.AngleAxis(maxAngle, Vector3.Cross(offsetSwingAxis, targetSwing));
|
||||
|
||||
Vector3 maxTargetSwing = maxRotation * offsetSwingAxis;
|
||||
|
||||
// Scale Limit Based on Width Height Ratios
|
||||
Vector3 limitCircleCenter = Vector3.ProjectOnPlane(offsetSwingAxis - maxTargetSwing, offsetSwingAxis) + maxTargetSwing;
|
||||
float circleRadius = Vector3.Distance(maxTargetSwing, limitCircleCenter);
|
||||
Debug.DrawLine(transform.position + Direction(maxTargetSwing), transform.position + Direction(maxTargetSwing));
|
||||
|
||||
Vector3 projectToCircle = (maxTargetSwing - limitCircleCenter);
|
||||
float width = circleRadius * limitWidthRatio;
|
||||
float height = circleRadius * limitHeightRatio;
|
||||
|
||||
Vector3 coneX = Vector3.Project(projectToCircle, offsetSecondaryAxis);
|
||||
Vector3 coneY = Vector3.Project(projectToCircle, offsetCrossAxis);
|
||||
|
||||
if (limitHeightRatio < 1 || limitWidthRatio < 1)
|
||||
{
|
||||
//find cartesian ellipse coordinates intersection
|
||||
Vector2 center = Vector2.zero;
|
||||
Vector2 pt = new Vector2(coneX.magnitude, coneY.magnitude);
|
||||
Vector3[] candidateProjectionPoints = FindEllipseSegmentIntersections(width, height, center, pt, true);
|
||||
|
||||
//map cartesian intersection point back to joint space
|
||||
if (candidateProjectionPoints.Length > 0)
|
||||
{
|
||||
Vector3 projectedX = coneX.normalized * candidateProjectionPoints[0].x;
|
||||
Vector3 projectedY = coneY.normalized * candidateProjectionPoints[0].y;
|
||||
maxTargetSwing = (limitCircleCenter + projectedX + projectedY).normalized;
|
||||
}
|
||||
}
|
||||
|
||||
if (Vector3.Angle(offsetSwingAxis, maxTargetSwing) < Vector3.Angle(offsetSwingAxis, targetSwing))
|
||||
{
|
||||
isClampedToLimit = true;
|
||||
targetSwing = maxTargetSwing;
|
||||
}
|
||||
|
||||
// Get the limited swing axis
|
||||
Quaternion limitedSwingRotation = Quaternion.FromToRotation(offsetSwingAxis, targetSwing);
|
||||
|
||||
// Rotation from current(illegal) swing rotation to the limited(legal) swing rotation
|
||||
Quaternion toLimits = Quaternion.FromToRotation(unlimitedTargetSwing, limitedSwingRotation * offsetSwingAxis);
|
||||
|
||||
// Subtract the illegal rotation
|
||||
return toLimits * rotation;
|
||||
|
||||
}
|
||||
|
||||
public override Vector3 GetStretchAxis()
|
||||
{
|
||||
return GetMainAxisWorld();
|
||||
}
|
||||
|
||||
public override Vector3 GetMidVectorWorld()
|
||||
{
|
||||
return GetMainAxisWorld();
|
||||
}
|
||||
|
||||
public override Vector3 GetMainAxisWorld()
|
||||
{
|
||||
Quaternion offsetRot = Quaternion.Euler(limitsOffset);
|
||||
Vector3 offsetSwingAxis = (offsetRot * this.mainAxis).normalized;
|
||||
return Direction(offsetSwingAxis);
|
||||
}
|
||||
|
||||
public override Quaternion LimitRotation(Quaternion rotation, float jointLimitStrength = 1)
|
||||
{
|
||||
Quaternion swing = LimitSwing(rotation);
|
||||
return LimitTwist(swing, mainAxis, secondaryAxis, twistLimit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Find the points of intersection between
|
||||
// an ellipse and a line segment.
|
||||
public Vector3[] FindEllipseSegmentIntersections(
|
||||
float width, float height, Vector3 pt1, Vector3 pt2, bool segment_only)
|
||||
{
|
||||
// If the ellipse or line segment are empty, return no intersections.
|
||||
if ((width == 0) || (height == 0) ||
|
||||
((pt1.x == pt2.x) && (pt1.y == pt2.y)))
|
||||
return new Vector3[] { };
|
||||
|
||||
// Get the semimajor and semiminor axes.
|
||||
float a = width;
|
||||
float b = height;
|
||||
|
||||
// Calculate the quadratic parameters.
|
||||
float A = (pt2.x - pt1.x) * (pt2.x - pt1.x) / a / a +
|
||||
(pt2.y - pt1.y) * (pt2.y - pt1.y) / b / b;
|
||||
float B = 2 * pt1.x * (pt2.x - pt1.x) / a / a +
|
||||
2 * pt1.y * (pt2.y - pt1.y) / b / b;
|
||||
float C = pt1.x * pt1.x / a / a + pt1.y * pt1.y / b / b - 1;
|
||||
|
||||
// Make a list of t values.
|
||||
List<float> t_values = new List<float>();
|
||||
|
||||
// Calculate the discriminant.
|
||||
float discriminant = B * B - 4 * A * C;
|
||||
if (discriminant == 0)
|
||||
{
|
||||
// One real solution.
|
||||
t_values.Add(-B / 2 / A);
|
||||
}
|
||||
else if (discriminant > 0)
|
||||
{
|
||||
// Two real solutions.
|
||||
t_values.Add((float)((-B + Mathf.Sqrt(discriminant)) / 2 / A));
|
||||
t_values.Add((float)((-B - Mathf.Sqrt(discriminant)) / 2 / A));
|
||||
}
|
||||
|
||||
// Convert the t values into points.
|
||||
List<Vector3> points = new List<Vector3>();
|
||||
foreach (float t in t_values)
|
||||
{
|
||||
// If the points are on the segment (or we
|
||||
// don't care if they are), add them to the list.
|
||||
if (!segment_only || ((t >= 0f) && (t <= 1f)))
|
||||
{
|
||||
float x = pt1.x + (pt2.x - pt1.x) * t;
|
||||
float y = pt1.y + (pt2.y - pt1.y) * t;
|
||||
points.Add(new Vector3(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
// Return the points.
|
||||
return points.ToArray();
|
||||
}
|
||||
|
||||
public override bool Apply(float jointLimitStrength = 1)
|
||||
{
|
||||
bool hasChanged = base.Apply(jointLimitStrength);
|
||||
return isClampedToLimit;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59495989be03fc34f8db82a27c38e0ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Joint Limits/DynamicJointLimitSwingTwist.cs
|
||||
uploadId: 532533
|
||||
8
Assets/Plugins/HybridIK/Scripts/Joint Limits/Editor.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts/Joint Limits/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdbf4dac63e13c14c96f45a9bd20e412
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,325 @@
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AshqarApps.DynamicJoint
|
||||
{
|
||||
[CustomEditor(typeof(DynamicJointLimitHinge))]
|
||||
[CanEditMultipleObjects]
|
||||
public class DynamicJointLimitHingeInspector : Editor
|
||||
{
|
||||
private DynamicJointLimitHinge script { get { return target as DynamicJointLimitHinge; } }
|
||||
private Vector3 lastPoint, zeroPoint;
|
||||
|
||||
float lastHingeOffset = 0;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
GUI.changed = false;
|
||||
|
||||
base.OnInspectorGUI();
|
||||
//DrawDefaultInspector();
|
||||
|
||||
int childCount = script.transform.childCount;
|
||||
GameObject childGO = null;
|
||||
for (int i = 0; i < script.transform.childCount; ++i)
|
||||
{
|
||||
if (!script.transform.GetChild(i).tag.Contains("ExcludeFromDynamics"))
|
||||
{
|
||||
childGO = script.transform.GetChild(i).gameObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (childGO != null)
|
||||
{
|
||||
if (GUILayout.Button("Align To Child Twist"))
|
||||
{
|
||||
Vector3 toChild = childGO.transform.position - script.transform.position;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
Vector3 secondaryAxis = new Vector3(script.mainAxis.y, script.mainAxis.z, script.mainAxis.x);
|
||||
script.cross = Direction(Vector3.Cross(script.mainAxis, secondaryAxis));
|
||||
}
|
||||
else if (GUILayout.Button("Align To Child X"))
|
||||
{
|
||||
Vector3 toChild = (childGO.transform.position - script.transform.position).normalized;
|
||||
script.cross = script.transform.InverseTransformDirection(toChild);
|
||||
//Vector3 secondaryAxis = new Vector3(script.cross.y, script.cross.z, script.cross.x);
|
||||
Vector3 secondaryAxis = script.transform.InverseTransformDirection(script.transform.right);
|
||||
Vector3.OrthoNormalize(ref secondaryAxis, ref script.cross);
|
||||
//Vector3 cross = Direction(Vector3.Cross(script.cross, secondaryAxis));
|
||||
script.mainAxis = secondaryAxis;
|
||||
}
|
||||
else if (GUILayout.Button("Align To Child Y"))
|
||||
{
|
||||
Vector3 toChild = (childGO.transform.position - script.transform.position).normalized;
|
||||
script.cross = script.transform.InverseTransformDirection(toChild);
|
||||
Vector3 secondaryAxis = script.transform.InverseTransformDirection(script.transform.up);
|
||||
Vector3.OrthoNormalize(ref secondaryAxis, ref script.cross);
|
||||
script.mainAxis = secondaryAxis;
|
||||
}
|
||||
else if (GUILayout.Button("Align To Child Z"))
|
||||
{
|
||||
Vector3 toChild = (childGO.transform.position - script.transform.position).normalized;
|
||||
script.cross = script.transform.InverseTransformDirection(toChild);
|
||||
Vector3 secondaryAxis = script.transform.InverseTransformDirection(script.transform.forward);
|
||||
Vector3.OrthoNormalize(ref secondaryAxis, ref script.cross);
|
||||
script.mainAxis = secondaryAxis;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Align To X"))
|
||||
{
|
||||
Vector3 toChild = script.transform.right;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
Vector3 secondaryAxis = new Vector3(script.mainAxis.y, script.mainAxis.z, script.mainAxis.x);
|
||||
script.cross = Vector3.Cross(script.mainAxis, secondaryAxis);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Align To Y"))
|
||||
{
|
||||
Vector3 toChild = script.transform.up;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
Vector3 secondaryAxis = new Vector3(script.mainAxis.y, script.mainAxis.z, script.mainAxis.x);
|
||||
script.cross = Vector3.Cross(script.mainAxis, secondaryAxis);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Align To Z"))
|
||||
{
|
||||
Vector3 toChild = script.transform.forward;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
Vector3 secondaryAxis = new Vector3(script.mainAxis.y, script.mainAxis.z, script.mainAxis.x);
|
||||
script.cross = Vector3.Cross(script.mainAxis, secondaryAxis);
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.changed) EditorUtility.SetDirty(script);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void UpdateZeroTransform()
|
||||
{
|
||||
if (lastHingeOffset != script.hingeAngleOffset)
|
||||
{
|
||||
lastHingeOffset = script.hingeAngleOffset;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneGUI()
|
||||
{
|
||||
if (!Application.isPlaying && !script.zeroRotationOverride) script.zeroRotation = script.transform.localRotation;
|
||||
if (script.mainAxis == Vector3.zero || script.cross == Vector3.zero) return;
|
||||
|
||||
float minBoneLength = 0.15f;
|
||||
float boneLength = minBoneLength;
|
||||
if (script.transform.childCount > 0)
|
||||
{
|
||||
boneLength = Vector3.Distance(script.transform.position, script.transform.GetChild(0).position) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (script.transform.parent != null)
|
||||
{
|
||||
boneLength = Vector3.Distance(script.transform.position, script.transform.parent.position) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
boneLength = Mathf.Max(boneLength, minBoneLength);
|
||||
|
||||
|
||||
// Display the main axis
|
||||
DrawArrow(script.transform.position, Direction(script.mainAxis), colorDefault, "Axis", 0.02f);
|
||||
|
||||
Handles.color = Color.white;
|
||||
GUI.color = Color.white;
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
|
||||
// Selecting points
|
||||
Handles.color = colorHandles;
|
||||
Handles.Button(script.transform.position + Direction(script.mainAxis), script.transform.rotation, 0.02f, 0.02f, Handles.DotHandleCap);
|
||||
|
||||
Vector3 selectedPoint = script.mainAxis;
|
||||
|
||||
// Store point for undo
|
||||
Vector3 oldPoint = selectedPoint;
|
||||
|
||||
// Manual input for the point position
|
||||
AddVector3(ref selectedPoint, "Point", script, GUILayout.Width(210));
|
||||
|
||||
// Moving Points
|
||||
Vector3 pointWorld = Handles.PositionHandle(script.transform.position + Direction(selectedPoint), Quaternion.identity);
|
||||
Vector3 newPoint = InverseDirection(pointWorld - script.transform.position);
|
||||
if (newPoint != selectedPoint)
|
||||
{
|
||||
if (!Application.isPlaying) Undo.RecordObject(script, "Move Limit Point");
|
||||
script.mainAxis = newPoint.normalized;
|
||||
}
|
||||
}
|
||||
|
||||
DrawHingeLimits(boneLength);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void DrawHingeLimits(float boneLength)
|
||||
{
|
||||
Quaternion offsetRot = Quaternion.Euler(script.limitsOffset);
|
||||
|
||||
Vector3 swing = Direction(offsetRot * script.mainAxis.normalized);
|
||||
|
||||
//Vector3 secondaryAxis = new Vector3(script.mainAxis.y, script.mainAxis.z, script.mainAxis.x);
|
||||
//Vector3 cross = Direction(Vector3.Cross(script.mainAxis, secondaryAxis));
|
||||
if (script.cross.magnitude == 0) return;
|
||||
Vector3 cross = Direction(offsetRot * script.cross);
|
||||
Vector3.OrthoNormalize(ref swing, ref cross);
|
||||
Vector3 secondaryAxis = Vector3.Cross(script.mainAxis, cross);
|
||||
|
||||
Handles.CircleHandleCap(0, script.transform.position, Quaternion.LookRotation(swing, cross), boneLength, EventType.Repaint);
|
||||
|
||||
//DrawArrow(script.transform.position, cross * boneLength, colorDefault, " 0", 0.02f);
|
||||
DrawArrow(script.transform.position, cross * boneLength, colorDefault, " 0", 0.02f);
|
||||
|
||||
Quaternion hingeOffset = Quaternion.AngleAxis(script.hingeAngleOffset, swing);
|
||||
|
||||
// Arcs for the rotation limit
|
||||
Handles.color = colorDefaultTransparent;
|
||||
Handles.DrawSolidArc(script.transform.position, swing, hingeOffset * cross, -script.limitAngle, boneLength);
|
||||
Handles.DrawSolidArc(script.transform.position, swing, hingeOffset * cross, script.limitAngle, boneLength);
|
||||
|
||||
Quaternion minRotation = Quaternion.AngleAxis(-script.limitAngle, swing);
|
||||
Vector3 minHandleDir = minRotation * (hingeOffset * cross);
|
||||
Handles.DrawLine(script.transform.position, script.transform.position + minHandleDir.normalized * boneLength);
|
||||
|
||||
Quaternion maxRotation = Quaternion.AngleAxis(script.limitAngle, swing);
|
||||
Vector3 maxHandleDir = maxRotation * (hingeOffset * cross);
|
||||
Handles.DrawLine(script.transform.position, script.transform.position + maxHandleDir.normalized * boneLength);
|
||||
|
||||
Handles.color = colorHandles;
|
||||
//Draw Editable Handles
|
||||
float originalLimit = script.limitAngle;
|
||||
float limitAngleMin = script.limitAngle;
|
||||
limitAngleMin = DrawLimitHandle(limitAngleMin, script.transform.position + (minHandleDir.normalized * boneLength * 1.25f), Quaternion.identity, 0.5f, "Limit", -10);
|
||||
if (limitAngleMin != script.limitAngle)
|
||||
{
|
||||
if (!Application.isPlaying) Undo.RecordObject(script, "Min Limit");
|
||||
script.limitAngle = limitAngleMin;
|
||||
script.hingeAngleOffset -= (limitAngleMin - originalLimit);
|
||||
}
|
||||
|
||||
originalLimit = script.limitAngle;
|
||||
//Draw Editable Handles
|
||||
float limitAngleMax = script.limitAngle;
|
||||
limitAngleMax = DrawLimitHandle(limitAngleMax, script.transform.position + (maxHandleDir.normalized * boneLength * 1.25f), Quaternion.identity, 0.5f, "Limit", 10);
|
||||
if (limitAngleMax != script.limitAngle)
|
||||
{
|
||||
if (!Application.isPlaying) Undo.RecordObject(script, "Max Limit");
|
||||
script.limitAngle = limitAngleMax;
|
||||
script.hingeAngleOffset += (limitAngleMax - originalLimit);
|
||||
}
|
||||
|
||||
// clamp limits
|
||||
script.limitAngle = Mathf.Clamp(script.limitAngle, 0, 180f);
|
||||
if (script.hingeAngleOffset < 0) script.hingeAngleOffset += 360;
|
||||
if (script.hingeAngleOffset > 360) script.hingeAngleOffset -= 360;
|
||||
|
||||
}
|
||||
|
||||
private Vector3 Direction(Vector3 v)
|
||||
{
|
||||
if (script.transform.parent == null) return script.zeroRotation * v;
|
||||
return script.transform.parent.rotation * (script.zeroRotation * v);
|
||||
}
|
||||
|
||||
private Vector3 InverseDirection(Vector3 v)
|
||||
{
|
||||
if (script.transform.parent == null) return Quaternion.Inverse(script.zeroRotation) * v;
|
||||
|
||||
return Quaternion.Inverse(script.zeroRotation) * Quaternion.Inverse(script.transform.parent.rotation) * v;
|
||||
}
|
||||
|
||||
// Universal color pallettes
|
||||
public static Color colorDefault { get { return new Color(0.0f, 0.0f, 1.0f, 1.0f); } }
|
||||
|
||||
public static Color colorDefaultTransparent
|
||||
{
|
||||
get
|
||||
{
|
||||
Color d = colorDefault;
|
||||
return new Color(d.r, d.g, d.b, 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
public static Color colorHandles { get { return new Color(1.0f, 0.5f, 0.25f, 1.0f); } }
|
||||
public static Color colorRotationSphere { get { return new Color(1.0f, 1.0f, 1.0f, 0.1f); } }
|
||||
public static Color colorInvalid { get { return new Color(1.0f, 0.3f, 0.3f, 1.0f); } }
|
||||
public static Color colorValid { get { return new Color(0.2f, 1.0f, 0.2f, 1.0f); } }
|
||||
|
||||
/*
|
||||
* Draws a custom arrow to the scene
|
||||
* */
|
||||
public static void DrawArrow(Vector3 position, Vector3 direction, Color color, string label = "", float size = 0.01f)
|
||||
{
|
||||
Handles.color = color;
|
||||
Handles.DrawLine(position, position + direction);
|
||||
Handles.SphereHandleCap(0, position + direction, Quaternion.identity, size, EventType.Repaint);
|
||||
Handles.color = Color.white;
|
||||
|
||||
if (label != "")
|
||||
{
|
||||
GUI.color = color;
|
||||
Handles.Label(position + direction, label);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws a handle for adjusting rotation limits in the scene
|
||||
* */
|
||||
public static float DrawLimitHandle(float limit, Vector3 position, Quaternion rotation, float radius, string label, float openingValue, bool reverseScaleDirection = false)
|
||||
{
|
||||
float scaleFactor = reverseScaleDirection ? -1 : 1;
|
||||
|
||||
limit = scaleFactor * Handles.ScaleValueHandle(limit, position, rotation, radius, Handles.SphereHandleCap, 1);
|
||||
|
||||
string labelInfo = label + ": " + limit.ToString();
|
||||
|
||||
// If value is 0, draw a button to 'open' the value, because we cant scale 0
|
||||
if (limit == 0)
|
||||
{
|
||||
labelInfo = "Open " + label;
|
||||
|
||||
if (Handles.Button(position, rotation, radius * 0.2f, radius * 0.07f, Handles.SphereHandleCap))
|
||||
{
|
||||
limit = openingValue;
|
||||
}
|
||||
}
|
||||
|
||||
Handles.Label(position, labelInfo);
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
|
||||
public static void AddVector3(ref Vector3 input, string name, Object undoObject, params GUILayoutOption[] options)
|
||||
{
|
||||
Vector3 newValue = EditorGUILayout.Vector3Field(name, input, options);
|
||||
|
||||
if (newValue != input && !Application.isPlaying)
|
||||
{
|
||||
Undo.RecordObject(undoObject, name);
|
||||
}
|
||||
|
||||
input = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be8d162414d22194399e23501b403f03
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Joint Limits/Editor/DynamicJointLimitHingeInspector.cs
|
||||
uploadId: 532533
|
||||
@@ -0,0 +1,248 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AshqarApps.DynamicJoint
|
||||
{
|
||||
[CustomEditor(typeof(DynamicJointLimitSwingTwist))]
|
||||
[CanEditMultipleObjects]
|
||||
public class DynamicJointLimitSwingTwistInspector : Editor
|
||||
{
|
||||
private DynamicJointLimitSwingTwist script { get { return target as DynamicJointLimitSwingTwist; } }
|
||||
private int axisComponentSelected = 0;
|
||||
private Vector3 lastPoint, zeroPoint;
|
||||
private int selectedChild = 0;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
int childCount = script.transform.childCount;
|
||||
|
||||
if (childCount == 1 && GUILayout.Button("Align To Child"))
|
||||
{
|
||||
Vector3 toChild = script.transform.GetChild(0).position - script.transform.position;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
if (GUI.changed) EditorUtility.SetDirty(script);
|
||||
}
|
||||
else if (childCount > 1)
|
||||
{
|
||||
List<string> childGOs = new List<string>();
|
||||
|
||||
//if (childGOs == null)
|
||||
{
|
||||
for (int i = 0; i < script.transform.childCount; ++i)
|
||||
{
|
||||
childGOs.Add(script.transform.GetChild(i).name);
|
||||
}
|
||||
}
|
||||
|
||||
selectedChild = EditorGUILayout.Popup("Selected Child", selectedChild, childGOs.ToArray());
|
||||
|
||||
//int selectedChild = 0;
|
||||
if (GUILayout.Button("Align To Selected Child"))
|
||||
{
|
||||
GameObject childGO = script.transform.GetChild(selectedChild).gameObject;
|
||||
|
||||
if (childGO.transform.childCount > 0)
|
||||
{
|
||||
childGO = childGO.transform.GetChild(0).gameObject;
|
||||
|
||||
Vector3 toChild = childGO.transform.position - script.transform.position;
|
||||
script.mainAxis = script.transform.InverseTransformDirection(toChild.normalized);
|
||||
if (GUI.changed) EditorUtility.SetDirty(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnSceneGUI()
|
||||
{
|
||||
// Set defaultLocalRotation so that the initial local rotation will be the zero point for the rotation limit
|
||||
if (!Application.isPlaying && !script.zeroRotationOverride) script.zeroRotation = script.transform.localRotation;
|
||||
if (script.mainAxis == Vector3.zero) return;
|
||||
|
||||
//DrawRotationSphere(script.transform.position);
|
||||
|
||||
Handles.color = Color.white;
|
||||
GUI.color = Color.white;
|
||||
|
||||
float minBoneLength = 0.15f;
|
||||
float boneLength = minBoneLength;
|
||||
if (script.transform.childCount > 0)
|
||||
{
|
||||
boneLength = Vector3.Distance(script.transform.position, script.transform.GetChild(0).position) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (script.transform.parent != null)
|
||||
{
|
||||
boneLength = Vector3.Distance(script.transform.position, script.transform.parent.position) / 4;
|
||||
}
|
||||
}
|
||||
boneLength = Mathf.Max(boneLength, minBoneLength);
|
||||
|
||||
// Display the main axis
|
||||
DrawArrow(script.transform.position, Direction(script.mainAxis).normalized * boneLength, colorDefault, "Axis", 0.02f);
|
||||
DrawArrow(script.transform.position, Direction(script.secondaryAxis) * boneLength, colorDefault, "Secondary Axis", 0.02f);
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
// Selecting points
|
||||
Handles.color = colorHandles;
|
||||
if (Handles.Button(script.transform.position + Direction(script.mainAxis.normalized) * boneLength * 1.25f, script.transform.rotation, 0.02f, 0.02f, Handles.DotHandleCap))
|
||||
{
|
||||
axisComponentSelected = 0;
|
||||
}
|
||||
else if (Handles.Button(script.transform.position + Direction(script.secondaryAxis.normalized) * boneLength * 1.25f, script.transform.rotation, 0.02f, 0.02f, Handles.DotHandleCap))
|
||||
{
|
||||
axisComponentSelected = 1;
|
||||
}
|
||||
|
||||
Vector3 selectedPoint = axisComponentSelected == 0 ? script.mainAxis : script.secondaryAxis;
|
||||
|
||||
// Store point for undo
|
||||
Vector3 oldPoint = selectedPoint;
|
||||
|
||||
// Manual input for the point position
|
||||
AddVector3(ref selectedPoint, "Point", script, GUILayout.Width(210));
|
||||
//EditorGUILayout.Space();
|
||||
|
||||
// Moving Points
|
||||
Vector3 pointWorld = Handles.PositionHandle(script.transform.position + (Direction(selectedPoint.normalized) * boneLength * 1.25f), Quaternion.identity);
|
||||
Vector3 newPoint = InverseDirection(pointWorld - script.transform.position);
|
||||
if (newPoint != selectedPoint)
|
||||
{
|
||||
if (!Application.isPlaying) Undo.RecordObject(script, "Move Limit Point");
|
||||
if (axisComponentSelected == 0)
|
||||
script.mainAxis = newPoint;
|
||||
else
|
||||
script.secondaryAxis = newPoint;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3.OrthoNormalize(ref script.mainAxis, ref script.secondaryAxis);
|
||||
|
||||
DrawSwingTwistLimits(boneLength);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void DrawSwingTwistLimits(float boneLength)
|
||||
{
|
||||
Vector3 swing = script.mainAxis.normalized;
|
||||
Vector3 secondaryAxis = script.secondaryAxis.normalized; //new Vector3(swing.y, swing.z, swing.x);
|
||||
Vector3.OrthoNormalize(ref swing, ref secondaryAxis);
|
||||
Vector3 cross = Vector3.Cross(swing, secondaryAxis);
|
||||
|
||||
// DRAW TWIST
|
||||
Quaternion offsetRot = Quaternion.Euler(script.limitsOffset);
|
||||
Handles.color = colorTwistLimit;
|
||||
Handles.DrawSolidArc(script.transform.position, Direction(offsetRot * swing), Direction(offsetRot * cross), script.twistLimit, boneLength);
|
||||
Handles.DrawSolidArc(script.transform.position, Direction(offsetRot * swing), Direction(offsetRot * cross), -script.twistLimit, boneLength);
|
||||
|
||||
// Display limits
|
||||
lastPoint = script.transform.position;
|
||||
|
||||
for (int i = 0; i < 360; i += 2)
|
||||
{
|
||||
//float evaluatedLimit = script.EvaluateSwingLimitAtOrthoAngle((float)(i));
|
||||
//float evaluatedLimit = script.curveX.Evaluate(Mathf.Abs(Mathf.Sin()));
|
||||
|
||||
Quaternion offset = Quaternion.AngleAxis(i, swing);
|
||||
Quaternion evaluatedRotation = Quaternion.AngleAxis(script.limitAngle, offset * (cross));
|
||||
|
||||
Color color = colorDefaultTransparent;
|
||||
|
||||
Vector3 swingAxis = script.LimitSwing(evaluatedRotation, visualizeMode: true) * swing;
|
||||
swingAxis = offsetRot * swingAxis;
|
||||
|
||||
Vector3 limitPoint = script.transform.position + Direction(swingAxis).normalized * boneLength;
|
||||
Handles.DrawLine(script.transform.position, script.transform.position + Direction(swingAxis).normalized * boneLength);
|
||||
|
||||
Handles.color = color;
|
||||
if (i == 0) zeroPoint = limitPoint;
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
Handles.color = colorDefault;
|
||||
Handles.DrawLine(limitPoint, lastPoint);
|
||||
if (i == 358) Handles.DrawLine(limitPoint, zeroPoint);
|
||||
}
|
||||
|
||||
lastPoint = limitPoint;
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3 Direction(Vector3 v)
|
||||
{
|
||||
if (script.transform.parent == null) return script.zeroRotation * v;
|
||||
return script.transform.parent.rotation * (script.zeroRotation * v);
|
||||
}
|
||||
|
||||
private Vector3 InverseDirection(Vector3 v)
|
||||
{
|
||||
if (script.transform.parent == null) return Quaternion.Inverse(script.zeroRotation) * v;
|
||||
|
||||
return Quaternion.Inverse(script.zeroRotation) * Quaternion.Inverse(script.transform.parent.rotation) * v;
|
||||
}
|
||||
|
||||
public static Color colorDefault { get { return new Color(0.0f, 1.0f, 1.0f, 0.5f); } }
|
||||
public static Color colorDefaultTransparent
|
||||
{
|
||||
get
|
||||
{
|
||||
Color d = colorDefault;
|
||||
return new Color(d.r, d.g, d.b, 0.2f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Color colorHandles { get { return new Color(1.0f, 0.5f, 0.25f, 1.0f); } }
|
||||
public static Color colorRotationSphere { get { return new Color(1.0f, 1.0f, 1.0f, 0.1f); } }
|
||||
public static Color colorTwistLimit { get { return new Color(1.0f, 1.0f, 0.0f, 0.1f); } }
|
||||
public static Color colorInvalid { get { return new Color(1.0f, 0.3f, 0.3f, 1.0f); } }
|
||||
public static Color colorValid { get { return new Color(0.2f, 1.0f, 0.2f, 1.0f); } }
|
||||
|
||||
/*
|
||||
* Draws the default rotation limit sphere to the scene
|
||||
* */
|
||||
public static void DrawRotationSphere(Vector3 position, float radius)
|
||||
{
|
||||
Handles.color = colorRotationSphere;
|
||||
Handles.SphereHandleCap(0, position, Quaternion.identity, radius, EventType.Repaint);
|
||||
Handles.color = Color.white;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws a custom arrow to the scene
|
||||
* */
|
||||
public static void DrawArrow(Vector3 position, Vector3 direction, Color color, string label = "", float size = 0.01f)
|
||||
{
|
||||
Handles.color = color;
|
||||
Handles.DrawLine(position, position + direction);
|
||||
Handles.SphereHandleCap(0, position + direction, Quaternion.identity, size, EventType.Repaint);
|
||||
Handles.color = Color.white;
|
||||
|
||||
if (label != "")
|
||||
{
|
||||
GUI.color = color;
|
||||
Handles.Label(position + direction, label);
|
||||
GUI.color = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddVector3(ref Vector3 input, string name, Object undoObject, params GUILayoutOption[] options)
|
||||
{
|
||||
Vector3 newValue = EditorGUILayout.Vector3Field(name, input, options);
|
||||
|
||||
if (newValue != input && !Application.isPlaying)
|
||||
{
|
||||
Undo.RecordObject(undoObject, name);
|
||||
}
|
||||
|
||||
input = newValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64e32b8cc7ffc8545adde630370be74d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Joint Limits/Editor/DynamicJointLimitSwingTwistInspector.cs
|
||||
uploadId: 532533
|
||||
8
Assets/Plugins/HybridIK/Scripts/Main.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts/Main.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b57a501956808744a6f4c77d47aa9ac
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Plugins/HybridIK/Scripts/Main/Editor.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts/Main/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85bff82fc19c984458a58f9f4d097ed8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,312 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(HybridInverseKinematicsNode))]
|
||||
public class HybridIKNodeInspector : Editor
|
||||
{
|
||||
private HybridInverseKinematicsNode hybridIKNode { get { return target as HybridInverseKinematicsNode; } }
|
||||
List<string> boneHierarchy = new List<string>();
|
||||
|
||||
private int selectedIKNodeIndex = -1;
|
||||
|
||||
private int selectedIKKeyframe = -1;
|
||||
|
||||
public void DeletePoseKeyframe(int selectedPose)
|
||||
{
|
||||
foreach (HybridIKConstraint c in hybridIKNode.constraints)
|
||||
{
|
||||
if (c.positionKeys.Count > 0)
|
||||
{
|
||||
c.positionKeys.RemoveAt(selectedPose);
|
||||
}
|
||||
}
|
||||
foreach (HybridIKJoint node in hybridIKNode.nodes)
|
||||
{
|
||||
node.keyedPositions.RemoveAt(selectedPose);
|
||||
node.keyedLocalPositions.RemoveAt(selectedPose);
|
||||
node.keyedRotations.RemoveAt(selectedPose);
|
||||
}
|
||||
|
||||
selectedIKKeyframe = -1;
|
||||
hybridIKNode.ResetToZeroPose();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (selectedIKKeyframe >= 0)
|
||||
{
|
||||
if (GUILayout.Button("Select Full Chain"))
|
||||
{
|
||||
selectedIKKeyframe = -1;
|
||||
}
|
||||
|
||||
if (selectedIKKeyframe >= 0)
|
||||
{
|
||||
GUILayout.Label("IK Keyframe " + selectedIKKeyframe.ToString() + " selected");
|
||||
if (GUILayout.Button("Delete Pose Keyframe"))
|
||||
{
|
||||
DeletePoseKeyframe(selectedIKKeyframe);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedIKNodeIndex >= 0)
|
||||
{
|
||||
HybridIKJoint selectedNode = hybridIKNode.nodes[selectedIKNodeIndex];
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
if (selectedNode.jointTransform != null)
|
||||
{
|
||||
if (GUILayout.Button("Select Joint GameObject"))
|
||||
{
|
||||
Selection.activeGameObject = selectedNode.jointTransform.gameObject;
|
||||
}
|
||||
}
|
||||
if (GUILayout.Button("Select Full Chain"))
|
||||
{
|
||||
selectedIKNodeIndex = -1;
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
if (selectedIKNodeIndex >= 0)
|
||||
{
|
||||
GUILayout.Label("IK Node " + selectedIKNodeIndex.ToString() + " selected");
|
||||
selectedNode.jointRadius = EditorGUILayout.FloatField("Node Radius", selectedNode.jointRadius);
|
||||
var oldColor = GUI.backgroundColor;
|
||||
GUILayout.Label("CONSTRAINTS MODE");
|
||||
GUILayout.BeginHorizontal();
|
||||
if (selectedNode.enableKeyframeConstraints && !selectedNode.overrideConstraint) GUI.backgroundColor = Color.green;
|
||||
if (GUILayout.Button("KEYFRAMED"))
|
||||
{
|
||||
selectedNode.enableKeyframeConstraints = true;
|
||||
selectedNode.overrideConstraint = false;
|
||||
hybridIKNode.ReprocessJoints();
|
||||
}
|
||||
GUI.backgroundColor = oldColor;
|
||||
if (selectedNode.overrideConstraint) GUI.backgroundColor = Color.green;
|
||||
if (GUILayout.Button("MANUAL CONSTRAINT"))
|
||||
{
|
||||
selectedNode.enableKeyframeConstraints = false;
|
||||
selectedNode.overrideConstraint = true;
|
||||
hybridIKNode.ReprocessJoints();
|
||||
}
|
||||
GUI.backgroundColor = oldColor;
|
||||
if (!selectedNode.enableKeyframeConstraints && !selectedNode.overrideConstraint) GUI.backgroundColor = Color.green;
|
||||
if (GUILayout.Button("NONE"))
|
||||
{
|
||||
selectedNode.enableKeyframeConstraints = false;
|
||||
selectedNode.overrideConstraint = false;
|
||||
hybridIKNode.ReprocessJoints();
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
GUI.backgroundColor = oldColor;
|
||||
|
||||
if (selectedNode.overrideConstraint)
|
||||
{
|
||||
//n.position = EditorGUILayout.Vector3Field("Target Position", node.position);
|
||||
selectedNode.constraint.jointTransform = selectedNode.jointTransform;
|
||||
selectedNode.constraint.targetTransform = EditorGUILayout.ObjectField("Target Transform", selectedNode.constraint.targetTransform, typeof(Transform), true) as Transform;
|
||||
|
||||
selectedNode.constraint.constrainPosition = EditorGUILayout.Toggle("Constrain Position", selectedNode.constraint.constrainPosition);
|
||||
selectedNode.constraint.constrainRotation = EditorGUILayout.Toggle("Constrain Orientation", selectedNode.constraint.constrainRotation);
|
||||
}
|
||||
|
||||
selectedNode.enableStretch = EditorGUILayout.Toggle("Enable Stretch", selectedNode.enableStretch);
|
||||
if (selectedNode.enableStretch)
|
||||
{
|
||||
if (selectedNode.stretchLimits == null)
|
||||
{
|
||||
selectedNode.stretchLimits = new HybridIKNodeStretchLimits();
|
||||
}
|
||||
|
||||
selectedNode.stretchLimits.targetSpace = EditorGUILayout.ObjectField("Target Transform", selectedNode.stretchLimits.targetSpace, typeof(Transform), true) as Transform;
|
||||
|
||||
selectedNode.stretchLimits.minStretchLimits = EditorGUILayout.Vector3Field("Min Stretch Limits", selectedNode.stretchLimits.minStretchLimits);
|
||||
selectedNode.stretchLimits.maxStretchLimits = EditorGUILayout.Vector3Field("Max Stretch Limits", selectedNode.stretchLimits.maxStretchLimits);
|
||||
}
|
||||
|
||||
if (GUI.changed) EditorUtility.SetDirty(hybridIKNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Process IK Joint Chain"))
|
||||
{
|
||||
hybridIKNode.ResetAll();
|
||||
hybridIKNode.ProcessChain();
|
||||
}
|
||||
if (hybridIKNode.nodes != null)
|
||||
{
|
||||
if (GUILayout.Button("Set Zero Rotations to Current Pose"))
|
||||
{
|
||||
foreach (HybridIKJoint node in hybridIKNode.nodes)
|
||||
{
|
||||
node.zeroRotation = node.jointTransform.localRotation;
|
||||
node.zeroPosition = node.jointTransform.localPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnInspectorGUI();
|
||||
if (hybridIKNode.nodes == null) return;
|
||||
|
||||
if (hybridIKNode.constraints == null || hybridIKNode.constraints.Count == 0)
|
||||
{
|
||||
hybridIKNode.constraints = new List<HybridIKConstraint>();
|
||||
foreach (HybridIKJoint node in hybridIKNode.nodes)
|
||||
{
|
||||
node.keyedLocalPositions = new List<Vector3>();
|
||||
node.keyedPositions = new List<Vector3>();
|
||||
node.keyedRotations = new List<Quaternion>();
|
||||
}
|
||||
}
|
||||
|
||||
if (hybridIKNode.constraints != null)// && hybridIKNode.constraints.Count > 0)
|
||||
{
|
||||
//EditorGUILayout.LabelField("Keyframe Constraints", EditorStyles.boldLabel);
|
||||
if (GUILayout.Button("Add Joints Pose Keyframe"))
|
||||
{
|
||||
List<int> keyframeState = new List<int>();
|
||||
foreach(HybridIKJoint j in hybridIKNode.nodes)
|
||||
{
|
||||
keyframeState.Add(j.enableKeyframeConstraints ? 0 : j.overrideConstraint ? 1 : 2);
|
||||
j.enableKeyframeConstraints = true; j.overrideConstraint = false;
|
||||
}
|
||||
|
||||
hybridIKNode.ReprocessJoints();
|
||||
|
||||
HybridIKJoint root = hybridIKNode.nodes[0];
|
||||
Transform parent = root.jointTransform.parent;
|
||||
|
||||
foreach (HybridIKJoint node in hybridIKNode.nodes)
|
||||
{
|
||||
// encode rotation
|
||||
if (node.keyedRotations == null)
|
||||
node.keyedRotations = new List<Quaternion>();
|
||||
node.keyedRotations.Add(node.jointTransform.localRotation);
|
||||
|
||||
//encode local positions used for stretch
|
||||
if (node.keyedLocalPositions == null)
|
||||
node.keyedLocalPositions = new List<Vector3>();
|
||||
node.keyedLocalPositions.Add(node.jointTransform.localPosition);
|
||||
|
||||
// encode position in parent space
|
||||
if (node.keyedPositions == null)
|
||||
node.keyedPositions = new List<Vector3>();
|
||||
node.keyedPositions.Add(parent != null ? parent.InverseTransformPoint(node.GetCurrentPositionWorld()) : node.GetCurrentPositionWorld());
|
||||
|
||||
HybridIKConstraint constraint = hybridIKNode.constraints.Find(c => c.jointTransform == node.jointTransform);
|
||||
if (constraint == null)
|
||||
{
|
||||
constraint = new HybridIKConstraint();
|
||||
constraint.jointTransform = node.jointTransform;
|
||||
constraint.constrainPosition = true;
|
||||
hybridIKNode.constraints.Add(constraint);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (HybridIKConstraint c in hybridIKNode.constraints)
|
||||
{
|
||||
ConstraintPositionKey key = new ConstraintPositionKey();
|
||||
if (c.positionKeys == null) c.positionKeys = new List<ConstraintPositionKey>();
|
||||
key.constraintPositionValue = c.jointTransform.position;
|
||||
|
||||
Vector3 endPos = parent != null ? parent.InverseTransformPoint(hybridIKNode.endNode.position) : hybridIKNode.endNode.position;
|
||||
key.SetEndTargetPosition(hybridIKNode.endNode.position, parent);
|
||||
c.positionKeys.Add(key);
|
||||
}
|
||||
hybridIKNode.ResetToZeroPose();
|
||||
}
|
||||
|
||||
if (hybridIKNode.nodes != null && hybridIKNode.nodes.Count > 0 && hybridIKNode.nodes[0] != null && hybridIKNode.nodes[0].keyedPositions != null)
|
||||
{
|
||||
for (int p = 0; p < hybridIKNode.nodes[0].keyedPositions.Count; ++p)
|
||||
{
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("Key Pose " + (p + 1).ToString());
|
||||
if (GUILayout.Button("Select"))
|
||||
{
|
||||
//selectedIKKeyframe = p;
|
||||
hybridIKNode.PoseToKeyframe(p);
|
||||
Repaint();
|
||||
}
|
||||
if (GUILayout.Button("Delete Key"))
|
||||
{
|
||||
DeletePoseKeyframe(p);
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GUI.changed) EditorUtility.SetDirty(hybridIKNode);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
hybridIKNode.ResetToZeroPose();
|
||||
}
|
||||
|
||||
public void OnSceneGUI()
|
||||
{
|
||||
if (hybridIKNode.nodes == null || hybridIKNode.nodes.Count == 0) return;
|
||||
|
||||
Color originalColor = Handles.color;
|
||||
if (hybridIKNode.IsInitialized())
|
||||
{
|
||||
for (int i = 0; i < hybridIKNode.nodes.Count; ++i)
|
||||
//foreach (SweepIKNode n in hybridIKNode.nodes)
|
||||
{
|
||||
HybridIKJoint n = hybridIKNode.nodes[i];
|
||||
Color c = n.enableKeyframeConstraints ? Color.blue : n.overrideConstraint ? Color.cyan : originalColor;
|
||||
Handles.color = selectedIKNodeIndex == i ? Color.green : c;
|
||||
float nRadius = Mathf.Max(n.jointRadius, 0.05f, n.jointRadius);
|
||||
if (Handles.Button(n.GetCurrentPositionWorld(), Quaternion.identity, nRadius, nRadius,Handles.SphereHandleCap))
|
||||
{
|
||||
selectedIKNodeIndex = i;
|
||||
selectedIKKeyframe = -1;
|
||||
if (!Application.isPlaying)
|
||||
hybridIKNode.ResetToZeroPose();
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
HybridIKJoint root = hybridIKNode.GetRootIKNode();
|
||||
HybridIKJoint endIKNode = hybridIKNode.GetEndIKNode();
|
||||
|
||||
Transform parentSpace = root.jointTransform.parent;
|
||||
|
||||
foreach (HybridIKConstraint c in hybridIKNode.constraints)
|
||||
{
|
||||
if (c.positionKeys.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < c.positionKeys.Count; ++i)
|
||||
{
|
||||
ConstraintPositionKey k = c.positionKeys[i];
|
||||
Handles.color = selectedIKKeyframe == i ? Color.green : originalColor;
|
||||
if (i % 4 == 0) Handles.color = Color.green;
|
||||
if (i % 4 == 1) Handles.color = Color.blue;
|
||||
if (i % 4 == 2) Handles.color = Color.yellow;
|
||||
if (i % 4 == 3) Handles.color = Color.magenta;
|
||||
|
||||
Vector3 buttonPos = k.GetEndTargetPosition(endIKNode.targetIKSpace != null ? endIKNode.targetIKSpace : parentSpace);
|
||||
|
||||
if (Handles.Button(buttonPos, Quaternion.identity, endIKNode.jointRadius, endIKNode.jointRadius, Handles.SphereHandleCap))
|
||||
{
|
||||
selectedIKKeyframe = i;
|
||||
selectedIKNodeIndex = -1;
|
||||
|
||||
hybridIKNode.PoseToKeyframe(selectedIKKeyframe);
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Handles.color = originalColor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d33a09095add3f4cb5e399c4bc4b2d1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Main/Editor/HybridIKNodeInspector.cs
|
||||
uploadId: 532533
|
||||
85
Assets/Plugins/HybridIK/Scripts/Main/HybridIKConstraint.cs
Normal file
85
Assets/Plugins/HybridIK/Scripts/Main/HybridIKConstraint.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class HybridIKConstraint
|
||||
{
|
||||
public Transform jointTransform;
|
||||
public Transform targetTransform;
|
||||
|
||||
public Vector3 targetPosition;
|
||||
public Vector3 targetLocalPosition; //used for stretch constraints
|
||||
public Quaternion targetRotation = Quaternion.identity;
|
||||
|
||||
public bool constrainPosition = true;
|
||||
public bool constrainRotation = false;
|
||||
|
||||
public Vector3 GetPosition()
|
||||
{
|
||||
if (targetTransform != null)
|
||||
return targetTransform.position;
|
||||
return targetPosition;
|
||||
}
|
||||
|
||||
public Vector3 GetLocalPosition()
|
||||
{
|
||||
//if (targetTransform != null)
|
||||
// return targetTransform.position;
|
||||
return targetLocalPosition;
|
||||
}
|
||||
|
||||
public Quaternion GetRotation()
|
||||
{
|
||||
if (targetTransform != null)
|
||||
return targetTransform.rotation;
|
||||
return targetRotation;
|
||||
}
|
||||
|
||||
public List<ConstraintPositionKey> positionKeys;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ConstraintPositionKey
|
||||
{
|
||||
public Transform endTargetKeyTransform;
|
||||
public Transform constraintKeyTransform;
|
||||
|
||||
[HideInInspector]
|
||||
public Vector3 endTargetPositionKey;
|
||||
[HideInInspector]
|
||||
public Vector3 constraintPositionValue;
|
||||
|
||||
[HideInInspector]
|
||||
public Quaternion constraintRotationValue;
|
||||
[HideInInspector]
|
||||
public float cachedWeight = 0;
|
||||
[HideInInspector]
|
||||
public float cachedFade = 0;
|
||||
|
||||
public Transform targetSpace = null;
|
||||
|
||||
public Vector3 GetEndTargetPosition(Transform rootSpace = null)
|
||||
{
|
||||
return endTargetKeyTransform != null ? endTargetKeyTransform.position :
|
||||
(rootSpace != null ? rootSpace.TransformPoint(endTargetPositionKey) : endTargetPositionKey);
|
||||
}
|
||||
|
||||
public void SetEndTargetPosition(Vector3 newPos, Transform rootSpace = null)
|
||||
{
|
||||
endTargetPositionKey = rootSpace != null ? rootSpace.InverseTransformPoint(newPos) : newPos;
|
||||
targetSpace = rootSpace;
|
||||
}
|
||||
|
||||
public Vector3 GetConstraintKeyPosition()
|
||||
{
|
||||
return constraintKeyTransform != null ? constraintKeyTransform.position : constraintPositionValue;
|
||||
}
|
||||
|
||||
public Quaternion GetConstraintKeyRotation()
|
||||
{
|
||||
return constraintKeyTransform != null ? constraintKeyTransform.rotation : constraintRotationValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 945cb199022265a4d879826f1cf92986
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Main/HybridIKConstraint.cs
|
||||
uploadId: 532533
|
||||
181
Assets/Plugins/HybridIK/Scripts/Main/HybridIKJoint.cs
Normal file
181
Assets/Plugins/HybridIK/Scripts/Main/HybridIKJoint.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using AshqarApps.DynamicJoint;
|
||||
|
||||
[System.Serializable]
|
||||
public class HybridIKJoint
|
||||
{
|
||||
public Transform jointTransform;
|
||||
public Quaternion initialRotation;
|
||||
public Vector3 initialPosition;
|
||||
public Vector3 initialPositionWorld;
|
||||
public Vector3 previousPositionWorld;
|
||||
|
||||
public Quaternion cachedInitialRotation;
|
||||
public Vector3 cachedLocalPosition;
|
||||
|
||||
|
||||
public Vector3 targetPosition;
|
||||
public Vector3 targetLocalPosition;
|
||||
public Vector3 stretchedTargetPosition;
|
||||
public bool isStretchNode;
|
||||
|
||||
private Vector3 ikTargetPosition;
|
||||
|
||||
public bool IsEndNode = false;
|
||||
|
||||
public HybridIKJoint child = null;
|
||||
public HybridIKJoint parent = null;
|
||||
|
||||
[HideInInspector]
|
||||
public int childIndex = -1;
|
||||
[HideInInspector]
|
||||
public int parentIndex = -1;
|
||||
|
||||
public float boneLength;
|
||||
public Vector3 toParent;
|
||||
|
||||
public bool oldVecInitialized;
|
||||
public Vector3 oldVec;
|
||||
public Quaternion rotationIK;
|
||||
|
||||
public float jointRadius;
|
||||
|
||||
public DynamicJointLimit jointLimit;
|
||||
|
||||
public bool isPositionConstrained = false;
|
||||
public bool isRotationConstrained = false;
|
||||
|
||||
public bool overrideConstraint;
|
||||
public HybridIKConstraint constraint;
|
||||
public Transform targetIKSpace = null;
|
||||
|
||||
public bool enableKeyframeConstraints = true;
|
||||
|
||||
public Vector3 cachedPosition = Vector3.zero;
|
||||
public Quaternion cachedRotation = Quaternion.identity;
|
||||
public Quaternion targetRotation = Quaternion.identity;
|
||||
public List<Quaternion> keyedRotations;
|
||||
public List<Vector3> keyedPositions;
|
||||
public List<Vector3> keyedLocalPositions;
|
||||
|
||||
public Quaternion zeroRotation = Quaternion.identity;
|
||||
public Vector3 zeroPosition = Vector3.zero;
|
||||
|
||||
public Quaternion lastFrameRotation = Quaternion.identity;
|
||||
public Vector3 lastFramePosition = Vector3.zero;
|
||||
public float currentAngularVelocity = 0;
|
||||
public float currentStretchVelocity = 0;
|
||||
|
||||
public bool enableStretch = false;
|
||||
public float inwardsStretch = 0;
|
||||
public float outwardsStretch = 0;
|
||||
public Vector3 stretchAxis = Vector3.forward;
|
||||
public HybridIKNodeStretchLimits stretchLimits;
|
||||
|
||||
// Angular Motion
|
||||
public bool overrideAngularMotion = false;
|
||||
public float maxAngularMotionVelocity = 30f;
|
||||
public float angularMotionAcceleration = 5f;
|
||||
|
||||
public void ResetToZeroTransforms()
|
||||
{
|
||||
if (parent != null)
|
||||
parent.jointTransform.localRotation = parent.zeroRotation;
|
||||
this.jointTransform.localPosition = zeroPosition;
|
||||
}
|
||||
|
||||
public bool HasIKConstraint()
|
||||
{
|
||||
return ((enableKeyframeConstraints || overrideConstraint)) && constraint != null && constraint.jointTransform != null && (constraint.constrainPosition || constraint.constrainRotation);
|
||||
}
|
||||
|
||||
public bool HasPositionConstraint()
|
||||
{
|
||||
return (enableKeyframeConstraints || overrideConstraint) && constraint != null && constraint.jointTransform != null && constraint.constrainPosition;
|
||||
}
|
||||
|
||||
public bool HasRotationConstraint()
|
||||
{
|
||||
return (enableKeyframeConstraints || overrideConstraint) && constraint != null && constraint.jointTransform != null && constraint.constrainRotation;
|
||||
}
|
||||
|
||||
public HybridIKJoint(Transform t, HybridIKJoint child, float radius = 0.1f)
|
||||
{
|
||||
if (child != null)
|
||||
{
|
||||
child.boneLength = (t.position - child.jointTransform.position).magnitude;
|
||||
child.parent = this;
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
lastFrameRotation = t.localRotation;
|
||||
initialPosition = t.localPosition;
|
||||
initialRotation = t.localRotation;
|
||||
initialPositionWorld = t.position;
|
||||
targetPosition = t.position;
|
||||
|
||||
previousPositionWorld = initialPositionWorld;
|
||||
|
||||
jointTransform = t;
|
||||
|
||||
jointRadius = radius;
|
||||
|
||||
oldVec = Vector3.up;
|
||||
|
||||
keyedRotations = new List<Quaternion>();
|
||||
keyedPositions = new List<Vector3>();
|
||||
keyedLocalPositions = new List<Vector3>();
|
||||
|
||||
this.jointLimit = t.gameObject.GetComponent<DynamicJointLimit>();
|
||||
}
|
||||
|
||||
public Vector3 GetCurrentPositionWorld()
|
||||
{
|
||||
return jointTransform.position;
|
||||
}
|
||||
|
||||
public Vector3 GetInitialPositionWorld()
|
||||
{
|
||||
return initialPositionWorld;
|
||||
}
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class HybridIKNodeStretchLimits
|
||||
{
|
||||
public Transform targetSpace;
|
||||
|
||||
public Vector3 minStretchLimits;
|
||||
public Vector3 maxStretchLimits;
|
||||
|
||||
public float maxForward = 0;
|
||||
public float maxBackward = 0;
|
||||
|
||||
public float maxLeft = 0;
|
||||
public float maxRight = 0;
|
||||
|
||||
public float maxDown = 0;
|
||||
public float maxUp = 0;
|
||||
|
||||
public Vector3 ApplyStretchLimit(Vector3 targetVec, Vector3 localOrigin)
|
||||
{
|
||||
if (targetSpace == null)
|
||||
return Vector3.zero;
|
||||
|
||||
Vector3 currentPos = targetSpace.position;
|
||||
targetSpace.localPosition = localOrigin;
|
||||
Vector3 diff = currentPos - targetSpace.position;
|
||||
targetVec += diff;
|
||||
|
||||
Vector3 vec = targetSpace.InverseTransformDirection(targetVec);
|
||||
vec.x = Mathf.Clamp(vec.x, minStretchLimits.x, maxStretchLimits.x);
|
||||
vec.y = Mathf.Clamp(vec.y, minStretchLimits.y, maxStretchLimits.y);
|
||||
vec.z = Mathf.Clamp(vec.z, minStretchLimits.z, maxStretchLimits.z);
|
||||
|
||||
vec = targetSpace.TransformDirection(vec);
|
||||
|
||||
return vec;
|
||||
}
|
||||
}
|
||||
18
Assets/Plugins/HybridIK/Scripts/Main/HybridIKJoint.cs.meta
Normal file
18
Assets/Plugins/HybridIK/Scripts/Main/HybridIKJoint.cs.meta
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2022210cf5df74d4dbdb63767a36f578
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Main/HybridIKJoint.cs
|
||||
uploadId: 532533
|
||||
@@ -0,0 +1,8 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HybridIKStretchJunction : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8a651a183a8c1443a30fc1d5487ea05
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Main/HybridIKStretchJunction.cs
|
||||
uploadId: 532533
|
||||
1157
Assets/Plugins/HybridIK/Scripts/Main/HybridInverseKinematicsNode.cs
Normal file
1157
Assets/Plugins/HybridIK/Scripts/Main/HybridInverseKinematicsNode.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec18f272cdf3e704196131d48566ee83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Main/HybridInverseKinematicsNode.cs
|
||||
uploadId: 532533
|
||||
144
Assets/Plugins/HybridIK/Scripts/Main/RobotController.cs
Normal file
144
Assets/Plugins/HybridIK/Scripts/Main/RobotController.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
public class RobotController : MonoBehaviour
|
||||
{
|
||||
[Header("IK")]
|
||||
[SerializeField] private HybridInverseKinematicsNode kinematicsNode;
|
||||
|
||||
[Header("Motor State")]
|
||||
[SerializeField] private GameObject motorStatusIndicator1;
|
||||
[SerializeField] private GameObject motorStatusIndicator2;
|
||||
|
||||
[SerializeField] private Material indicatorMaterial1; // 기본색(회색)
|
||||
[SerializeField] private Material indicatorMaterial2; // 초록
|
||||
|
||||
[SerializeField] public GameObject toolEndpoint;
|
||||
[SerializeField] public Material toolEndpointHighlight;
|
||||
[SerializeField] public Material toolEndpointErrorHighlight;
|
||||
[SerializeField] public Material toolEndpointOriginal;
|
||||
|
||||
[SerializeField] public GameObject testSphere; // 타겟 위치에 표시할 오브젝트
|
||||
|
||||
public event Action OnPoseUpdateRequest;
|
||||
public event Action OnPoseUpdateReceive;
|
||||
|
||||
public Vector3 movementPosition;
|
||||
private Quaternion movementRotation;
|
||||
|
||||
private bool isMotorOn;
|
||||
public bool IsMovementRunning = false;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if (motorStatusIndicator1 != null)
|
||||
{
|
||||
motorStatusIndicator1.GetComponent<MeshRenderer>().material = indicatorMaterial1;
|
||||
}
|
||||
if (motorStatusIndicator2 != null)
|
||||
{
|
||||
motorStatusIndicator2.GetComponent<MeshRenderer>().material = indicatorMaterial1;
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
OnPoseUpdateRequest?.Invoke();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (kinematicsNode != null && kinematicsNode.enabled == false)
|
||||
{
|
||||
UpdateHandleToEndPoint();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMotorState(bool isOn)
|
||||
{
|
||||
isMotorOn = isOn;
|
||||
|
||||
|
||||
if (isMotorOn)
|
||||
{
|
||||
if (indicatorMaterial2 != null)
|
||||
{
|
||||
motorStatusIndicator1.GetComponent<MeshRenderer>().material = indicatorMaterial2;
|
||||
motorStatusIndicator2.GetComponent<MeshRenderer>().material = indicatorMaterial2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (indicatorMaterial1 != null)
|
||||
{
|
||||
motorStatusIndicator1.GetComponent<MeshRenderer>().material = indicatorMaterial1;
|
||||
motorStatusIndicator2.GetComponent<MeshRenderer>().material = indicatorMaterial1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EnableIK()
|
||||
{
|
||||
if (kinematicsNode != null) kinematicsNode.enabled = true;
|
||||
}
|
||||
|
||||
public void DisableIK()
|
||||
{
|
||||
if (kinematicsNode != null) kinematicsNode.enabled = false;
|
||||
}
|
||||
|
||||
/*
|
||||
public void SetRobotPosition(RobotData robotData) // 가상 로봇 위치 업데이트
|
||||
{
|
||||
// x, y, z, rx, ry, rz => endpoint값
|
||||
// j1, ..., j6 => 6개 축의 회전값
|
||||
if (robotData == null)
|
||||
{
|
||||
return; // 데이터가 없으면 아무것도 하지 않음
|
||||
}
|
||||
|
||||
List<Quaternion> list_jAngle = new List<Quaternion>();
|
||||
|
||||
list_jAngle.Add(Quaternion.AngleAxis(-1 * robotData.j1, Vector3.forward));
|
||||
list_jAngle.Add(Quaternion.AngleAxis((robotData.j2 - 90), Vector3.up));
|
||||
list_jAngle.Add(Quaternion.AngleAxis(robotData.j3, Vector3.up));
|
||||
list_jAngle.Add(Quaternion.AngleAxis(robotData.j4, Vector3.right));
|
||||
list_jAngle.Add(Quaternion.AngleAxis(robotData.j5, Vector3.up));
|
||||
list_jAngle.Add(Quaternion.AngleAxis(robotData.j6, Vector3.right));
|
||||
|
||||
kinematicsNode.SetJointTargetRotations(list_jAngle);
|
||||
}
|
||||
*/
|
||||
|
||||
private void UpdateHandleToEndPoint()
|
||||
{
|
||||
if (kinematicsNode == null || kinematicsNode.targetTransform == null ||
|
||||
kinematicsNode.nodes == null || kinematicsNode.nodes.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Transform endPoint = kinematicsNode.nodes[kinematicsNode.nodes.Count - 1].jointTransform;
|
||||
if (endPoint == null) return;
|
||||
|
||||
kinematicsNode.targetTransform.position = endPoint.position;
|
||||
kinematicsNode.targetTransform.rotation = endPoint.rotation;
|
||||
}
|
||||
|
||||
public Transform GetEndPoint()
|
||||
{
|
||||
Transform endPoint = kinematicsNode.nodes[kinematicsNode.nodes.Count - 1].jointTransform;
|
||||
return endPoint;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
IsMovementRunning = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c12f4ab377ddfdc46820089b240eaf27
|
||||
43
Assets/Plugins/HybridIK/Scripts/Main/TargetRangeLimiter.cs
Normal file
43
Assets/Plugins/HybridIK/Scripts/Main/TargetRangeLimiter.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using UnityEngine;
|
||||
|
||||
/// 이 Transform의 위치를 지정된 중심점으로부터 최대 거리를 벗어나지 않도록 제한
|
||||
public class TargetRangeLimiter : MonoBehaviour
|
||||
{
|
||||
[Header("Range Limit")]
|
||||
[SerializeField] private Transform centerPoint;
|
||||
|
||||
[SerializeField] private float maxDistance = 2.0f;
|
||||
|
||||
// LateUpdate를 사용하여 다른 스크립트에 의해 위치가 변경된 후 최종적으로 위치 보정
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (centerPoint == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 중심점에서 현재 핸들 위치까지의 벡터와 거리를 계산
|
||||
Vector3 directionFromCenter = transform.position - centerPoint.position;
|
||||
float currentDistance = directionFromCenter.magnitude;
|
||||
|
||||
// 2. 현재 거리가 최대 거리를 초과했는지 확인
|
||||
if (currentDistance > maxDistance)
|
||||
{
|
||||
// 3. 방향은 유지한 채, 거리를 최대 거리로 제한하는 새로운 위치 계산
|
||||
Vector3 newPosition = centerPoint.position + directionFromCenter.normalized * maxDistance;
|
||||
|
||||
// 4. 핸들의 위치를 계산된 새 위치로 강제 설정
|
||||
transform.position = newPosition;
|
||||
}
|
||||
}
|
||||
|
||||
//// 기즈모를 그려서 작업 범위를 시각적으로 보여줌 (에디터 전용)
|
||||
//private void OnDrawGizmosSelected()
|
||||
//{
|
||||
// if (centerPoint != null)
|
||||
// {
|
||||
// Gizmos.color = Color.green;
|
||||
// Gizmos.DrawWireSphere(centerPoint.position, maxDistance);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6dac70e0e196a043852640887710f7b
|
||||
8
Assets/Plugins/HybridIK/Scripts/Utils.meta
Normal file
8
Assets/Plugins/HybridIK/Scripts/Utils.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b509378e1379bb54cbbbb7ce530a5fe9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
727
Assets/Plugins/HybridIK/Scripts/Utils/GeometryMathHelperUtils.cs
Normal file
727
Assets/Plugins/HybridIK/Scripts/Utils/GeometryMathHelperUtils.cs
Normal file
@@ -0,0 +1,727 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class GeometryMathHelperUtils
|
||||
{
|
||||
//Find the line of intersection between two planes. The planes are defined by a normal and a point on that plane.
|
||||
//The outputs are a point on the line and a vector which indicates it's direction. If the planes are not parallel,
|
||||
//the function outputs true, otherwise false.
|
||||
public static bool PlanePlaneIntersection(out Vector3 linePoint, out Vector3 lineVec, Vector3 plane1Normal, Vector3 plane1Position, Vector3 plane2Normal, Vector3 plane2Position)
|
||||
{
|
||||
|
||||
linePoint = Vector3.zero;
|
||||
lineVec = Vector3.zero;
|
||||
|
||||
//We can get the direction of the line of intersection of the two planes by calculating the
|
||||
//cross product of the normals of the two planes. Note that this is just a direction and the line
|
||||
//is not fixed in space yet. We need a point for that to go with the line vector.
|
||||
lineVec = Vector3.Cross(plane1Normal, plane2Normal);
|
||||
|
||||
//Next is to calculate a point on the line to fix it's position in space. This is done by finding a vector from
|
||||
//the plane2 location, moving parallel to it's plane, and intersecting plane1. To prevent rounding
|
||||
//errors, this vector also has to be perpendicular to lineDirection. To get this vector, calculate
|
||||
//the cross product of the normal of plane2 and the lineDirection.
|
||||
Vector3 ldir = Vector3.Cross(plane2Normal, lineVec);
|
||||
|
||||
float denominator = Vector3.Dot(plane1Normal, ldir);
|
||||
|
||||
//Prevent divide by zero and rounding errors by requiring about 5 degrees angle between the planes.
|
||||
if (Mathf.Abs(denominator) > 0.006f)
|
||||
{
|
||||
|
||||
Vector3 plane1ToPlane2 = plane1Position - plane2Position;
|
||||
float t = Vector3.Dot(plane1Normal, plane1ToPlane2) / denominator;
|
||||
linePoint = plane2Position + t * ldir;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//output not valid
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//create a vector of direction "vector" with length "size"
|
||||
public static Vector3 SetVectorLength(Vector3 vector, float size)
|
||||
{
|
||||
|
||||
//normalize the vector
|
||||
Vector3 vectorNormalized = Vector3.Normalize(vector);
|
||||
|
||||
//scale the vector
|
||||
return vectorNormalized *= size;
|
||||
}
|
||||
|
||||
//Get the intersection between a line and a plane.
|
||||
//If the line and plane are not parallel, the function outputs true, otherwise false.
|
||||
public static bool LinePlaneIntersection(out Vector3 intersection, Vector3 linePoint, Vector3 lineVec, Vector3 planeNormal, Vector3 planePoint)
|
||||
{
|
||||
|
||||
float length;
|
||||
float dotNumerator;
|
||||
float dotDenominator;
|
||||
Vector3 vector;
|
||||
intersection = Vector3.zero;
|
||||
|
||||
//calculate the distance between the linePoint and the line-plane intersection point
|
||||
dotNumerator = Vector3.Dot((planePoint - linePoint), planeNormal);
|
||||
dotDenominator = Vector3.Dot(lineVec, planeNormal);
|
||||
|
||||
//line and plane are not parallel
|
||||
if (dotDenominator != 0.0f)
|
||||
{
|
||||
length = dotNumerator / dotDenominator;
|
||||
|
||||
//create a vector from the linePoint to the intersection point
|
||||
vector = SetVectorLength(lineVec, length);
|
||||
|
||||
//get the coordinates of the line-plane intersection point
|
||||
intersection = linePoint + vector;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//output not valid
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate the intersection point of two lines. Returns true if lines intersect, otherwise false.
|
||||
//Note that in 3d, two lines do not intersect most of the time. So if the two lines are not in the
|
||||
//same plane, use ClosestPointsOnTwoLines() instead.
|
||||
public static bool LineLineIntersection(out Vector3 intersection, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2)
|
||||
{
|
||||
|
||||
Vector3 lineVec3 = linePoint2 - linePoint1;
|
||||
Vector3 crossVec1and2 = Vector3.Cross(lineVec1, lineVec2);
|
||||
Vector3 crossVec3and2 = Vector3.Cross(lineVec3, lineVec2);
|
||||
|
||||
float planarFactor = Vector3.Dot(lineVec3, crossVec1and2);
|
||||
|
||||
//is coplanar, and not parrallel
|
||||
if (Mathf.Abs(planarFactor) < 0.0001f && crossVec1and2.sqrMagnitude > 0.0001f)
|
||||
{
|
||||
float s = Vector3.Dot(crossVec3and2, crossVec1and2) / crossVec1and2.sqrMagnitude;
|
||||
intersection = linePoint1 + (lineVec1 * s);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
intersection = Vector3.zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Two non-parallel lines which may or may not touch each other have a point on each line which are closest
|
||||
//to each other. This function finds those two points. If the lines are not parallel, the function
|
||||
//outputs true, otherwise false.
|
||||
public static bool ClosestPointsOnTwoLines(out Vector3 closestPointLine1, out Vector3 closestPointLine2, Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2)
|
||||
{
|
||||
|
||||
closestPointLine1 = Vector3.zero;
|
||||
closestPointLine2 = Vector3.zero;
|
||||
|
||||
float a = Vector3.Dot(lineVec1, lineVec1);
|
||||
float b = Vector3.Dot(lineVec1, lineVec2);
|
||||
float e = Vector3.Dot(lineVec2, lineVec2);
|
||||
|
||||
float d = a * e - b * b;
|
||||
|
||||
//lines are not parallel
|
||||
if (d != 0.0f)
|
||||
{
|
||||
|
||||
Vector3 r = linePoint1 - linePoint2;
|
||||
float c = Vector3.Dot(lineVec1, r);
|
||||
float f = Vector3.Dot(lineVec2, r);
|
||||
|
||||
float s = (b * f - c * e) / d;
|
||||
float t = (a * f - c * b) / d;
|
||||
|
||||
closestPointLine1 = linePoint1 + lineVec1 * s;
|
||||
closestPointLine2 = linePoint2 + lineVec2 * t;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//This function returns a point which is a projection from a point to a line.
|
||||
//The line is regarded infinite. If the line is finite, use ProjectPointOnLineSegment() instead.
|
||||
public static Vector3 ProjectPointOnLine(Vector3 linePoint, Vector3 lineVec, Vector3 point)
|
||||
{
|
||||
|
||||
//get vector from point on line to point in space
|
||||
Vector3 linePointToPoint = point - linePoint;
|
||||
|
||||
float t = Vector3.Dot(linePointToPoint, lineVec);
|
||||
|
||||
return linePoint + lineVec * t;
|
||||
}
|
||||
|
||||
//This function returns a point which is a projection from a point to a line segment.
|
||||
//If the projected point lies outside of the line segment, the projected point will
|
||||
//be clamped to the appropriate line edge.
|
||||
//If the line is infinite instead of a segment, use ProjectPointOnLine() instead.
|
||||
public static Vector3 ProjectPointOnLineSegment(Vector3 linePoint1, Vector3 linePoint2, Vector3 point)
|
||||
{
|
||||
Vector3 projectedP = Vector3.Project(point - linePoint1, linePoint2 - linePoint1) + linePoint1;
|
||||
|
||||
float lineD = Vector3.Distance(linePoint1, linePoint2);
|
||||
float d1 = Vector3.Distance(linePoint1, projectedP);
|
||||
float d2 = Vector3.Distance(linePoint2, projectedP);
|
||||
|
||||
// On the segment
|
||||
if (d1 < lineD && d2 < lineD)
|
||||
return projectedP;
|
||||
|
||||
// not on segment, evaluate against points instead
|
||||
if (Vector3.Distance(point, linePoint1) < Vector3.Distance(point, linePoint2))
|
||||
return linePoint1;
|
||||
else
|
||||
return linePoint2;
|
||||
}
|
||||
|
||||
//This function finds out on which side of a line segment the point is located.
|
||||
//The point is assumed to be on a line created by linePoint1 and linePoint2. If the point is not on
|
||||
//the line segment, project it on the line using ProjectPointOnLine() first.
|
||||
//Returns 0 if point is on the line segment.
|
||||
//Returns 1 if point is outside of the line segment and located on the side of linePoint1.
|
||||
//Returns 2 if point is outside of the line segment and located on the side of linePoint2.
|
||||
public static int PointOnWhichSideOfLineSegment(Vector3 linePoint1, Vector3 linePoint2, Vector3 point)
|
||||
{
|
||||
|
||||
Vector3 lineVec = linePoint2 - linePoint1;
|
||||
Vector3 pointVec = point - linePoint1;
|
||||
|
||||
float dot = Vector3.Dot(pointVec, lineVec);
|
||||
|
||||
//point is on side of linePoint2, compared to linePoint1
|
||||
if (dot > 0)
|
||||
{
|
||||
|
||||
//point is on the line segment
|
||||
if (pointVec.magnitude <= lineVec.magnitude)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//point is not on the line segment and it is on the side of linePoint2
|
||||
else
|
||||
{
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Point is not on side of linePoint2, compared to linePoint1.
|
||||
//Point is not on the line segment and it is on the side of linePoint1.
|
||||
else
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 ProjectPointOnTriangle (Vector3 A, Vector3 B, Vector3 C, Vector3 sourceP)
|
||||
{
|
||||
// Compute vectors
|
||||
Vector3 v0 = C - A;
|
||||
Vector3 v1 = B - A;
|
||||
|
||||
Vector3 projectedP = Vector3.ProjectOnPlane(sourceP - A, Vector3.Cross(v0.normalized, v1.normalized)) + A;
|
||||
Vector3 v2 = projectedP - A;
|
||||
|
||||
// Compute dot products
|
||||
float dot00 = Vector3.Dot(v0, v0);
|
||||
float dot01 = Vector3.Dot(v0, v1);
|
||||
float dot02 = Vector3.Dot(v0, v2);
|
||||
float dot11 = Vector3.Dot(v1, v1);
|
||||
float dot12 = Vector3.Dot(v1, v2);
|
||||
|
||||
// Compute barycentric coordinates
|
||||
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
|
||||
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
|
||||
// Check if point is in triangle
|
||||
if ((u >= 0) && (v >= 0) && (u + v < 1))
|
||||
{
|
||||
return A + (u * v0) + (v * v1);
|
||||
}
|
||||
|
||||
// Evaluate closest point to triangle linesegments
|
||||
Vector3 p1 = ProjectPointOnLineSegment(A, B, projectedP);
|
||||
Vector3 p2 = ProjectPointOnLineSegment(A, C, projectedP);
|
||||
Vector3 p3 = ProjectPointOnLineSegment(C, B, projectedP);
|
||||
|
||||
float d1 = Vector3.Distance(projectedP, p1);
|
||||
float d2 = Vector3.Distance(projectedP, p2);
|
||||
float d3 = Vector3.Distance(projectedP, p3);
|
||||
|
||||
if (d1 <= d2 && d1 <= d3) return p1;
|
||||
if (d2 <= d1 && d2 <= d3) return p2;
|
||||
if (d3 <= d2 && d3 <= d1) return p3;
|
||||
|
||||
return projectedP;
|
||||
}
|
||||
|
||||
public static Vector3 FindAveragePoint(List<Vector3> points)
|
||||
{
|
||||
Vector3 avgPoint = Vector3.zero;
|
||||
foreach (Vector3 p in points)
|
||||
{
|
||||
avgPoint += p;
|
||||
}
|
||||
avgPoint /= points.Count;
|
||||
|
||||
return avgPoint;
|
||||
}
|
||||
|
||||
public static Vector3 FindClosestPointToConvexHull(List<Vector3> hullPoints, List<int> hullTris, Vector3 targetPoint)
|
||||
{
|
||||
if (hullPoints == null || hullPoints.Count < 3 || hullTris == null || hullTris.Count < 2)
|
||||
return targetPoint;
|
||||
|
||||
float closestD = Mathf.Infinity;
|
||||
Vector3 closestProjection = targetPoint;
|
||||
|
||||
for(int t = 0; t < hullTris.Count; t += 3)
|
||||
{
|
||||
Vector3 v1 = hullPoints[hullTris[t]];
|
||||
Vector3 v2 = hullPoints[hullTris[t + 1]];
|
||||
Vector3 v3 = hullPoints[hullTris[t + 2]];
|
||||
|
||||
Vector3 projectedP = ProjectPointOnTriangle(v1, v2, v3, targetPoint);
|
||||
float d = Vector3.Distance(projectedP, targetPoint);
|
||||
if (Vector3.Distance(projectedP, targetPoint) < closestD)
|
||||
{
|
||||
d = closestD;
|
||||
closestProjection = projectedP;
|
||||
}
|
||||
}
|
||||
|
||||
return closestProjection;
|
||||
}
|
||||
|
||||
public static Vector3 ProjectPointOnConvexHull(List<Vector3> hullPoints, List<int> hullTris, Vector3 targetPoint, out bool isInside)
|
||||
{
|
||||
isInside = false;
|
||||
if (hullPoints == null || hullPoints.Count < 3 || hullTris == null || hullTris.Count < 2)
|
||||
return targetPoint;
|
||||
|
||||
Vector3 origin = FindAveragePoint(hullPoints);
|
||||
Vector3 dir = targetPoint - origin;
|
||||
Ray ray = new Ray(origin, dir);
|
||||
|
||||
Vector3 intersectionPoint;
|
||||
|
||||
for (int t = 0; t < hullTris.Count; t += 3)
|
||||
{
|
||||
Vector3 v1 = hullPoints[hullTris[t]];
|
||||
Vector3 v2 = hullPoints[hullTris[t + 1]];
|
||||
Vector3 v3 = hullPoints[hullTris[t + 2]];
|
||||
|
||||
if (RayTriangleIntersection(v1, v2, v3, ray, out intersectionPoint))
|
||||
{
|
||||
//Debug.DrawLine(origin, intersectionPoint);
|
||||
if (Vector3.Distance(origin, intersectionPoint) < Vector3.Distance(origin, targetPoint))
|
||||
{
|
||||
return intersectionPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
isInside = true;
|
||||
return targetPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return targetPoint;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the specified ray hits the triagnlge descibed by p1, p2 and p3.
|
||||
/// Möller–Trumbore ray-triangle intersection algorithm implementation.
|
||||
/// </summary>
|
||||
/// <param name="p1">Vertex 1 of the triangle.</param>
|
||||
/// <param name="p2">Vertex 2 of the triangle.</param>
|
||||
/// <param name="p3">Vertex 3 of the triangle.</param>
|
||||
/// <param name="ray">The ray to test hit for.</param>
|
||||
/// <returns><c>true</c> when the ray hits the triangle, otherwise <c>false</c></returns>
|
||||
public static bool RayTriangleIntersection(Vector3 p1, Vector3 p2, Vector3 p3, Ray ray, out Vector3 intersectionPoint)
|
||||
{
|
||||
intersectionPoint = ray.origin;
|
||||
|
||||
// Vectors from p1 to p2/p3 (edges)
|
||||
Vector3 e1, e2;
|
||||
|
||||
Vector3 p, q, t;
|
||||
float det, invDet, u, v;
|
||||
|
||||
|
||||
//Find vectors for two edges sharing vertex/point p1
|
||||
e1 = p2 - p1;
|
||||
e2 = p3 - p1;
|
||||
|
||||
// calculating determinant
|
||||
p = Vector3.Cross(ray.direction, e2);
|
||||
|
||||
//Calculate determinat
|
||||
det = Vector3.Dot(e1, p);
|
||||
|
||||
//if determinant is near zero, ray lies in plane of triangle otherwise not
|
||||
if (det > - Mathf.Epsilon && det < Mathf.Epsilon) { return false; }
|
||||
invDet = 1.0f / det;
|
||||
|
||||
//calculate distance from p1 to ray origin
|
||||
t = ray.origin - p1;
|
||||
|
||||
//Calculate u parameter
|
||||
u = Vector3.Dot(t, p) * invDet;
|
||||
|
||||
//Check for ray hit
|
||||
if (u < 0 || u > 1) { return false; }
|
||||
|
||||
//Prepare to test v parameter
|
||||
q = Vector3.Cross(t, e1);
|
||||
|
||||
//Calculate v parameter
|
||||
v = Vector3.Dot(ray.direction, q) * invDet;
|
||||
|
||||
//Check for ray hit
|
||||
if (v < 0 || u + v > 1) { return false; }
|
||||
|
||||
if ((Vector3.Dot(e2, q) * invDet) > Mathf.Epsilon)
|
||||
{
|
||||
intersectionPoint = p1 + (u * e1) + (v * e2);
|
||||
//ray does intersect
|
||||
return true;
|
||||
}
|
||||
|
||||
// No hit at all
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void Sort(Vector2 v)
|
||||
{
|
||||
if (v.x > v.y)
|
||||
{
|
||||
float c;
|
||||
c = v.x;
|
||||
v.x = v.y;
|
||||
v.y = c;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This edge to edge test is based on Franlin Antonio's gem: "Faster Line Segment Intersection", in Graphics Gems III, pp. 199-202
|
||||
/// </summary>
|
||||
private static bool EdgeEdgeTest(Vector3 v0, Vector3 v1, Vector3 u0, Vector3 u1, int i0, int i1)
|
||||
{
|
||||
float Ax, Ay, Bx, By, Cx, Cy, e, d, f;
|
||||
Ax = v1[i0] - v0[i0];
|
||||
Ay = v1[i1] - v0[i1];
|
||||
|
||||
Bx = u0[i0] - u1[i0];
|
||||
By = u0[i1] - u1[i1];
|
||||
Cx = v0[i0] - u0[i0];
|
||||
Cy = v0[i1] - u0[i1];
|
||||
f = Ay * Bx - Ax * By;
|
||||
d = By * Cx - Bx * Cy;
|
||||
if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f))
|
||||
{
|
||||
e = Ax * Cy - Ay * Cx;
|
||||
if (f > 0)
|
||||
{
|
||||
if (e >= 0 && e <= f) { return true; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e <= 0 && e >= f) { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool EdgeAgainstTriEdges(Vector3 v0, Vector3 v1, Vector3 u0, Vector3 u1, Vector3 u2, short i0, short i1)
|
||||
{
|
||||
// test edge u0,u1 against v0,v1
|
||||
if (EdgeEdgeTest(v0, v1, u0, u1, i0, i1)) { return true; }
|
||||
|
||||
// test edge u1,u2 against v0,v1
|
||||
if (EdgeEdgeTest(v0, v1, u1, u2, i0, i1)) { return true; }
|
||||
|
||||
// test edge u2,u1 against v0,v1
|
||||
if (EdgeEdgeTest(v0, v1, u2, u0, i0, i1)) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool PointInTri(Vector3 v0, Vector3 u0, Vector3 u1, Vector3 u2, short i0, short i1)
|
||||
{
|
||||
float a, b, c, d0, d1, d2;
|
||||
|
||||
// is T1 completly inside T2?
|
||||
// check if v0 is inside tri(u0,u1,u2)
|
||||
a = u1[i1] - u0[i1];
|
||||
b = -(u1[i0] - u0[i0]);
|
||||
c = -a * u0[i0] - b * u0[i1];
|
||||
d0 = a * v0[i0] + b * v0[i1] + c;
|
||||
|
||||
a = u2[i1] - u1[i1];
|
||||
b = -(u2[i0] - u1[i0]);
|
||||
c = -a * u1[i0] - b * u1[i1];
|
||||
d1 = a * v0[i0] + b * v0[i1] + c;
|
||||
|
||||
a = u0[i1] - u2[i1];
|
||||
b = -(u0[i0] - u2[i0]);
|
||||
c = -a * u2[i0] - b * u2[i1];
|
||||
d2 = a * v0[i0] + b * v0[i1] + c;
|
||||
|
||||
if (d0 * d1 > 0.0f)
|
||||
{
|
||||
if (d0 * d2 > 0.0f) { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TriTriCoplanar(Vector3 N, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 u0, Vector3 u1, Vector3 u2)
|
||||
{
|
||||
float[] A = new float[3];
|
||||
short i0, i1;
|
||||
|
||||
// first project onto an axis-aligned plane, that maximizes the area
|
||||
// of the triangles, compute indices: i0,i1.
|
||||
A[0] = Mathf.Abs(N[0]);
|
||||
A[1] = Mathf.Abs(N[1]);
|
||||
A[2] = Mathf.Abs(N[2]);
|
||||
if (A[0] > A[1])
|
||||
{
|
||||
if (A[0] > A[2])
|
||||
{
|
||||
// A[0] is greatest
|
||||
i0 = 1;
|
||||
i1 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A[2] is greatest
|
||||
i0 = 0;
|
||||
i1 = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (A[2] > A[1])
|
||||
{
|
||||
// A[2] is greatest
|
||||
i0 = 0;
|
||||
i1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A[1] is greatest
|
||||
i0 = 0;
|
||||
i1 = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// test all edges of triangle 1 against the edges of triangle 2
|
||||
if (EdgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1)) { return true; }
|
||||
if (EdgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1)) { return true; }
|
||||
if (EdgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1)) { return true; }
|
||||
|
||||
// finally, test if tri1 is totally contained in tri2 or vice versa
|
||||
if (PointInTri(v0, u0, u1, u2, i0, i1)) { return true; }
|
||||
if (PointInTri(u0, v0, v1, v2, i0, i1)) { return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static bool ComputeIntervals(float VV0, float VV1, float VV2,
|
||||
float D0, float D1, float D2, float D0D1, float D0D2,
|
||||
ref float A, ref float B, ref float C, ref float X0, ref float X1)
|
||||
{
|
||||
if (D0D1 > 0.0f)
|
||||
{
|
||||
// here we know that D0D2<=0.0
|
||||
// that is D0, D1 are on the same side, D2 on the other or on the plane
|
||||
A = VV2; B = (VV0 - VV2) * D2; C = (VV1 - VV2) * D2; X0 = D2 - D0; X1 = D2 - D1;
|
||||
}
|
||||
else if (D0D2 > 0.0f)
|
||||
{
|
||||
// here we know that d0d1<=0.0
|
||||
A = VV1; B = (VV0 - VV1) * D1; C = (VV2 - VV1) * D1; X0 = D1 - D0; X1 = D1 - D2;
|
||||
}
|
||||
else if (D1 * D2 > 0.0f || D0 != 0.0f)
|
||||
{
|
||||
// here we know that d0d1<=0.0 or that D0!=0.0
|
||||
A = VV0; B = (VV1 - VV0) * D0; C = (VV2 - VV0) * D0; X0 = D0 - D1; X1 = D0 - D2;
|
||||
}
|
||||
else if (D1 != 0.0f)
|
||||
{
|
||||
A = VV1; B = (VV0 - VV1) * D1; C = (VV2 - VV1) * D1; X0 = D1 - D0; X1 = D1 - D2;
|
||||
}
|
||||
else if (D2 != 0.0f)
|
||||
{
|
||||
A = VV2; B = (VV0 - VV2) * D2; C = (VV1 - VV2) * D2; X0 = D2 - D0; X1 = D2 - D1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the triangle V(v0, v1, v2) intersects the triangle U(u0, u1, u2).
|
||||
/// </summary>
|
||||
/// <param name="v0">Vertex 0 of V</param>
|
||||
/// <param name="v1">Vertex 1 of V</param>
|
||||
/// <param name="v2">Vertex 2 of V</param>
|
||||
/// <param name="u0">Vertex 0 of U</param>
|
||||
/// <param name="u1">Vertex 1 of U</param>
|
||||
/// <param name="u2">Vertex 2 of U</param>
|
||||
/// <returns>Returns <c>true</c> if V intersects U, otherwise <c>false</c></returns>
|
||||
public static bool TriTriIntersect(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 u0, Vector3 u1, Vector3 u2)
|
||||
{
|
||||
Vector3 e1, e2;
|
||||
Vector3 n1, n2;
|
||||
Vector3 dd;
|
||||
Vector2 isect1 = Vector2.zero, isect2 = Vector2.zero;
|
||||
|
||||
float du0, du1, du2, dv0, dv1, dv2, d1, d2;
|
||||
float du0du1, du0du2, dv0dv1, dv0dv2;
|
||||
float vp0, vp1, vp2;
|
||||
float up0, up1, up2;
|
||||
float bb, cc, max;
|
||||
|
||||
short index;
|
||||
|
||||
// compute plane equation of triangle(v0,v1,v2)
|
||||
e1 = v1 - v0;
|
||||
e2 = v2 - v0;
|
||||
n1 = Vector3.Cross(e1, e2);
|
||||
d1 = -Vector3.Dot(n1, v0);
|
||||
// plane equation 1: N1.X+d1=0 */
|
||||
|
||||
// put u0,u1,u2 into plane equation 1 to compute signed distances to the plane
|
||||
du0 = Vector3.Dot(n1, u0) + d1;
|
||||
du1 = Vector3.Dot(n1, u1) + d1;
|
||||
du2 = Vector3.Dot(n1, u2) + d1;
|
||||
|
||||
// coplanarity robustness check
|
||||
if (Mathf.Abs(du0) < Mathf.Epsilon) { du0 = 0.0f; }
|
||||
if (Mathf.Abs(du1) < Mathf.Epsilon) { du1 = 0.0f; }
|
||||
if (Mathf.Abs(du2) < Mathf.Epsilon) { du2 = 0.0f; }
|
||||
|
||||
du0du1 = du0 * du1;
|
||||
du0du2 = du0 * du2;
|
||||
|
||||
// same sign on all of them + not equal 0 ?
|
||||
if (du0du1 > 0.0f && du0du2 > 0.0f)
|
||||
{
|
||||
// no intersection occurs
|
||||
return false;
|
||||
}
|
||||
|
||||
// compute plane of triangle (u0,u1,u2)
|
||||
e1 = u1 - u0;
|
||||
e2 = u2 - u0;
|
||||
n2 = Vector3.Cross(e1, e2);
|
||||
d2 = -Vector3.Dot(n2, u0);
|
||||
|
||||
// plane equation 2: N2.X+d2=0
|
||||
// put v0,v1,v2 into plane equation 2
|
||||
dv0 = Vector3.Dot(n2, v0) + d2;
|
||||
dv1 = Vector3.Dot(n2, v1) + d2;
|
||||
dv2 = Vector3.Dot(n2, v2) + d2;
|
||||
|
||||
if (Mathf.Abs(dv0) < Mathf.Epsilon) { dv0 = 0.0f; }
|
||||
if (Mathf.Abs(dv1) < Mathf.Epsilon) { dv1 = 0.0f; }
|
||||
if (Mathf.Abs(dv2) < Mathf.Epsilon) { dv2 = 0.0f; }
|
||||
|
||||
|
||||
dv0dv1 = dv0 * dv1;
|
||||
dv0dv2 = dv0 * dv2;
|
||||
|
||||
// same sign on all of them + not equal 0 ?
|
||||
if (dv0dv1 > 0.0f && dv0dv2 > 0.0f)
|
||||
{
|
||||
// no intersection occurs
|
||||
return false;
|
||||
}
|
||||
|
||||
// compute direction of intersection line
|
||||
dd = Vector3.Cross(n1, n2);
|
||||
|
||||
// compute and index to the largest component of D
|
||||
max = (float)Mathf.Abs(dd[0]);
|
||||
index = 0;
|
||||
bb = (float)Mathf.Abs(dd[1]);
|
||||
cc = (float)Mathf.Abs(dd[2]);
|
||||
if (bb > max) { max = bb; index = 1; }
|
||||
if (cc > max) { max = cc; index = 2; }
|
||||
|
||||
// this is the simplified projection onto L
|
||||
vp0 = v0[index];
|
||||
vp1 = v1[index];
|
||||
vp2 = v2[index];
|
||||
|
||||
up0 = u0[index];
|
||||
up1 = u1[index];
|
||||
up2 = u2[index];
|
||||
|
||||
// compute interval for triangle 1
|
||||
float a = 0, b = 0, c = 0, x0 = 0, x1 = 0;
|
||||
if (ComputeIntervals(vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, ref a, ref b, ref c, ref x0, ref x1))
|
||||
{
|
||||
return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2);
|
||||
}
|
||||
|
||||
// compute interval for triangle 2
|
||||
float d = 0, e = 0, f = 0, y0 = 0, y1 = 0;
|
||||
if (ComputeIntervals(up0, up1, up2, du0, du1, du2, du0du1, du0du2, ref d, ref e, ref f, ref y0, ref y1))
|
||||
{
|
||||
return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2);
|
||||
}
|
||||
|
||||
float xx, yy, xxyy, tmp;
|
||||
xx = x0 * x1;
|
||||
yy = y0 * y1;
|
||||
xxyy = xx * yy;
|
||||
|
||||
tmp = a * xxyy;
|
||||
isect1[0] = tmp + b * x1 * yy;
|
||||
isect1[1] = tmp + c * x0 * yy;
|
||||
|
||||
tmp = d * xxyy;
|
||||
isect2[0] = tmp + e * xx * y1;
|
||||
isect2[1] = tmp + f * xx * y0;
|
||||
|
||||
Sort(isect1);
|
||||
Sort(isect2);
|
||||
|
||||
return !(isect1[1] < isect2[0] || isect2[1] < isect1[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 128a79f08e4a2d8418595cce65d7e047
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 174069
|
||||
packageName: Hybrid IK
|
||||
packageVersion: 1.02
|
||||
assetPath: Assets/HybridIK/Scripts/Utils/GeometryMathHelperUtils.cs
|
||||
uploadId: 532533
|
||||
9
Assets/Plugins/LZ4.meta
Normal file
9
Assets/Plugins/LZ4.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 673e554486793784d92d2ef90b8dea5a
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Instructions_LZ4.pdf
Normal file
BIN
Assets/Plugins/LZ4/Instructions_LZ4.pdf
Normal file
Binary file not shown.
8
Assets/Plugins/LZ4/Instructions_LZ4.pdf.meta
Normal file
8
Assets/Plugins/LZ4/Instructions_LZ4.pdf.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c160d3ac61ffb24280705bed0c10407
|
||||
timeCreated: 1553410075
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
231
Assets/Plugins/LZ4/LZ4Demo.unity
Normal file
231
Assets/Plugins/LZ4/LZ4Demo.unity
Normal file
@@ -0,0 +1,231 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &4
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 1
|
||||
m_BakeResolution: 50
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 1
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 4890085278179872738, guid: 0847c23f6299b08449f39502733f7805, type: 2}
|
||||
--- !u!196 &5
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666666
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &448084245
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 448084250}
|
||||
- component: {fileID: 448084249}
|
||||
- component: {fileID: 448084247}
|
||||
- component: {fileID: 448084246}
|
||||
- component: {fileID: 448084251}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &448084246
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &448084247
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &448084249
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19852942, g: 0.17863621, b: 0.16057527, a: 0.019607844}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 0
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &448084250
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &448084251
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 981c86a1b803d94408869e6ec746834a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
4
Assets/Plugins/LZ4/LZ4Demo.unity.meta
Normal file
4
Assets/Plugins/LZ4/LZ4Demo.unity.meta
Normal file
@@ -0,0 +1,4 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91f0e133e0bfc794da70fc393c643d4e
|
||||
DefaultImporter:
|
||||
userData:
|
||||
64
Assets/Plugins/LZ4/LZ4DemoSettings.lighting
Normal file
64
Assets/Plugins/LZ4/LZ4DemoSettings.lighting
Normal file
@@ -0,0 +1,64 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: LZ4DemoSettings
|
||||
serializedVersion: 4
|
||||
m_GIWorkflowMode: 1
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 0
|
||||
m_BakeBackend: 0
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 50
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 0
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 1
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 1
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 512
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_PVRTiledBaking: 0
|
||||
8
Assets/Plugins/LZ4/LZ4DemoSettings.lighting.meta
Normal file
8
Assets/Plugins/LZ4/LZ4DemoSettings.lighting.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0847c23f6299b08449f39502733f7805
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4890085278179872738
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
231
Assets/Plugins/LZ4/LZ4DemoWebGLtvOS.unity
Normal file
231
Assets/Plugins/LZ4/LZ4DemoWebGLtvOS.unity
Normal file
@@ -0,0 +1,231 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.2, g: 0.2, b: 0.2, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 3
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &4
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 1
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 1
|
||||
m_BakeResolution: 50
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 1
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 4890085278179872738, guid: 573b2714aeb9d2e4e8db669feb1ca633, type: 2}
|
||||
--- !u!196 &5
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666666
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &448084245
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 448084250}
|
||||
- component: {fileID: 448084249}
|
||||
- component: {fileID: 448084247}
|
||||
- component: {fileID: 448084246}
|
||||
- component: {fileID: 448084251}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &448084246
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &448084247
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
--- !u!20 &448084249
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.3455882, g: 0.25635213, b: 0.1753352, a: 0.019607844}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 0
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &448084250
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 1, z: -10}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &448084251
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 448084245}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: ab3415a07d4720340bdbada4392e5a1d, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
7
Assets/Plugins/LZ4/LZ4DemoWebGLtvOS.unity.meta
Normal file
7
Assets/Plugins/LZ4/LZ4DemoWebGLtvOS.unity.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 085b09c1884d0e4439d0d764db99294c
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
64
Assets/Plugins/LZ4/LZ4DemoWebGLtvOSSettings.lighting
Normal file
64
Assets/Plugins/LZ4/LZ4DemoWebGLtvOSSettings.lighting
Normal file
@@ -0,0 +1,64 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: LZ4DemoWebGLtvOSSettings
|
||||
serializedVersion: 4
|
||||
m_GIWorkflowMode: 1
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 0
|
||||
m_BakeBackend: 0
|
||||
m_LightmapMaxSize: 1024
|
||||
m_BakeResolution: 50
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 0
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 0
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 1
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 1
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherRayCount: 1024
|
||||
m_FinalGatherFiltering: 1
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRFilteringMode: 0
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_PVRTiledBaking: 0
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 573b2714aeb9d2e4e8db669feb1ca633
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4890085278179872738
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins.meta
Normal file
9
Assets/Plugins/LZ4/Plugins.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d260117c8a0ece4f828af94e62c153b
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/Android.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/Android.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 516ae443aec77514dbff9fa328ec083a
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
7
Assets/Plugins/LZ4/Plugins/Android/libs.meta
Normal file
7
Assets/Plugins/LZ4/Plugins/Android/libs.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 92b3b193a934e2b4ca676c01c7dc5407
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/Android/libs/arm64-v8a.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/Android/libs/arm64-v8a.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ecfaac3a146ce634293499223bcd4472
|
||||
folderAsset: yes
|
||||
timeCreated: 1553410075
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/arm64-v8a/liblz4.so
Normal file
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/arm64-v8a/liblz4.so
Normal file
Binary file not shown.
@@ -0,0 +1,97 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 150578e90870d6944922922c2e97a448
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 0
|
||||
Exclude Editor: 1
|
||||
Exclude Linux: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude LinuxUniversal: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude WebGL: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: ARM64
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Facebook: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Facebook: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: LinuxUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
7
Assets/Plugins/LZ4/Plugins/Android/libs/armeabi-v7a.meta
Normal file
7
Assets/Plugins/LZ4/Plugins/Android/libs/armeabi-v7a.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c4d3c932d67b214d929b9bd81687246
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/armeabi-v7a/liblz4.so
Normal file
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/armeabi-v7a/liblz4.so
Normal file
Binary file not shown.
@@ -0,0 +1,95 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35e1d6e4e143a4043883bd0b43358dc5
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
: OSXIntel
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
: OSXIntel64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
: WP8
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: ARMv7
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath:
|
||||
SDK: AnySDK
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
7
Assets/Plugins/LZ4/Plugins/Android/libs/x86.meta
Normal file
7
Assets/Plugins/LZ4/Plugins/Android/libs/x86.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fde2cd5749a38e54f8d0b3f05b20dbe0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/x86/liblz4.so
Normal file
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/x86/liblz4.so
Normal file
Binary file not shown.
95
Assets/Plugins/LZ4/Plugins/Android/libs/x86/liblz4.so.meta
Normal file
95
Assets/Plugins/LZ4/Plugins/Android/libs/x86/liblz4.so.meta
Normal file
@@ -0,0 +1,95 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7c00049e3663bb428c850799644cc33
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Linux
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
: OSXIntel
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
: OSXIntel64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
: WP8
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath:
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: x86
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DontProcess: False
|
||||
PlaceholderPath:
|
||||
SDK: AnySDK
|
||||
- first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CompileFlags:
|
||||
FrameworkDependencies:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Plugins/LZ4/Plugins/Android/libs/x86_64.meta
Normal file
8
Assets/Plugins/LZ4/Plugins/Android/libs/x86_64.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 196223d89bc925b4c96c2a18314c57b4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/x86_64/liblz4.so
Normal file
BIN
Assets/Plugins/LZ4/Plugins/Android/libs/x86_64/liblz4.so
Normal file
Binary file not shown.
@@ -0,0 +1,71 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35f97115a4906694e848b65c994e2a86
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
: Any
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
Exclude Android: 0
|
||||
Exclude Editor: 1
|
||||
Exclude Linux64: 1
|
||||
Exclude OSXUniversal: 1
|
||||
Exclude WebGL: 1
|
||||
Exclude Win: 1
|
||||
Exclude Win64: 1
|
||||
- first:
|
||||
Android: Android
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
CPU: X86_64
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
DefaultValueInitialized: true
|
||||
OS: AnyOS
|
||||
- first:
|
||||
Standalone: Linux64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: OSXUniversal
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: Win
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
- first:
|
||||
Standalone: Win64
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: None
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
635
Assets/Plugins/LZ4/Plugins/LZ4.cs
Normal file
635
Assets/Plugins/LZ4/Plugins/LZ4.cs
Normal file
@@ -0,0 +1,635 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
public class LZ4
|
||||
{
|
||||
#if !UNITY_WEBPLAYER || UNITY_EDITOR
|
||||
|
||||
internal static bool isle = BitConverter.IsLittleEndian;
|
||||
|
||||
#if UNITY_5_4_OR_NEWER
|
||||
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_WEBGL) && !UNITY_EDITOR || UNITY_EDITOR_LINUX
|
||||
private const string libname = "lz4";
|
||||
#elif UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
|
||||
private const string libname = "liblz4";
|
||||
#endif
|
||||
#else
|
||||
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_WEBGL) && !UNITY_EDITOR
|
||||
private const string libname = "lz4";
|
||||
#endif
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
|
||||
private const string libname = "liblz4";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_ANDROID || UNITY_STANDALONE_LINUX
|
||||
#if (!UNITY_WEBGL || UNITY_EDITOR)
|
||||
#if (UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_ANDROID || UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX)&& !UNITY_EDITOR_WIN
|
||||
[DllImport(libname, EntryPoint = "z4setPermissions")]
|
||||
internal static extern int z4setPermissions(string filePath, string _user, string _group, string _other);
|
||||
#endif
|
||||
[DllImport(libname, EntryPoint = "LZ4DecompressFile"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
internal static extern int LZ4DecompressFile(string inFile, string outFile, IntPtr bytes, IntPtr FileBuffer, int fileBufferLength);
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4CompressFile"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
internal static extern int LZ4CompressFile(string inFile, string outFile, int level, IntPtr percentage, ref float rate);
|
||||
#endif
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4releaseBuffer"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
public static extern void LZ4releaseBuffer(IntPtr buffer);
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4Create_Buffer"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
public static extern IntPtr LZ4Create_Buffer(int size);
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4AddTo_Buffer"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
private static extern void LZ4AddTo_Buffer(IntPtr destination, int offset, IntPtr buffer, int len);
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4CompressBuffer"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
internal static extern IntPtr LZ4CompressBuffer(IntPtr buffer, int bufferLength, ref int v, int level);
|
||||
|
||||
[DllImport(libname, EntryPoint = "LZ4DecompressBuffer"
|
||||
#if (UNITY_STANDALONE_WIN && ENABLE_IL2CPP) || UNITY_ANDROID
|
||||
, CallingConvention = CallingConvention.Cdecl
|
||||
#endif
|
||||
)]
|
||||
internal static extern int LZ4DecompressBuffer(IntPtr buffer, IntPtr outbuffer, int bufferLength);
|
||||
#endif
|
||||
|
||||
|
||||
#if (UNITY_IOS || UNITY_TVOS || UNITY_IPHONE || UNITY_WEBGL) && !UNITY_EDITOR
|
||||
#if (UNITY_IOS || UNITY_IPHONE) && !UNITY_WEBGL
|
||||
[DllImport("__Internal")]
|
||||
private static extern int z4setPermissions(string filePath, string _user, string _group, string _other);
|
||||
[DllImport("__Internal")]
|
||||
private static extern int LZ4DecompressFile(string inFile, string outFile, IntPtr bytes, IntPtr FileBuffer, int fileBufferLength);
|
||||
[DllImport("__Internal")]
|
||||
private static extern int LZ4CompressFile(string inFile, string outFile, int level, IntPtr percentage, ref float rate);
|
||||
#endif
|
||||
#if (UNITY_IOS || UNITY_TVOS || UNITY_IPHONE || UNITY_WEBGL)
|
||||
[DllImport("__Internal")]
|
||||
public static extern void LZ4releaseBuffer(IntPtr buffer);
|
||||
[DllImport("__Internal")]
|
||||
public static extern IntPtr LZ4Create_Buffer(int size);
|
||||
[DllImport("__Internal")]
|
||||
internal static extern void LZ4AddTo_Buffer(IntPtr destination, int offset, IntPtr buffer, int len);
|
||||
[DllImport("__Internal")]
|
||||
private static extern IntPtr LZ4CompressBuffer(IntPtr buffer, int bufferLength, ref int v, int level);
|
||||
[DllImport("__Internal")]
|
||||
private static extern int LZ4DecompressBuffer(IntPtr buffer, IntPtr outbuffer, int bufferLength);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Helper function
|
||||
internal static GCHandle gcA(object o) {
|
||||
return GCHandle.Alloc(o, GCHandleType.Pinned);
|
||||
}
|
||||
|
||||
#if ((!UNITY_WEBGL && !UNITY_TVOS) || UNITY_EDITOR)
|
||||
// set permissions of a file in user, group, other.
|
||||
// Each string should contain any or all chars of "rwx".
|
||||
// returns 0 on success
|
||||
public static int setFilePermissions(string filePath, string _user, string _group, string _other){
|
||||
#if (UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX || UNITY_ANDROID || UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX || UNITY_IOS || UNITY_TVOS || UNITY_IPHONE) && !UNITY_EDITOR_WIN
|
||||
return z4setPermissions(filePath, _user, _group, _other);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
//Helper function
|
||||
private static bool checkObject(object fileBuffer, string filePath, ref GCHandle fbuf, ref IntPtr fileBufferPointer, ref int fileBufferLength) {
|
||||
if(fileBuffer is byte[]) { byte[] tempBuf = (byte[])fileBuffer; fbuf = gcA(tempBuf); fileBufferPointer = fbuf.AddrOfPinnedObject(); fileBufferLength = tempBuf.Length; return true; }
|
||||
if(fileBuffer is IntPtr) { fileBufferPointer = (IntPtr)fileBuffer; fileBufferLength = Convert.ToInt32(filePath); }
|
||||
return false;
|
||||
}
|
||||
|
||||
//Compress a file to LZ4.
|
||||
//
|
||||
//Full paths to the files should be provided.
|
||||
//level: level of compression (1 - 9).
|
||||
//returns: rate of compression.
|
||||
//progress: provide a single item float array to get the progress of the compression in real time. (only when called from a thread/task)
|
||||
//
|
||||
public static float compress(string inFile, string outFile, int level, float[] progress) {
|
||||
if (level < 1) level = 1;
|
||||
if (level > 9) level = 9;
|
||||
float rate = 0;
|
||||
if(progress == null) progress = new float[1];
|
||||
progress[0] = 0;
|
||||
GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned);
|
||||
|
||||
int res = LZ4CompressFile(@inFile, @outFile, level, ibuf.AddrOfPinnedObject(), ref rate);
|
||||
|
||||
ibuf.Free();
|
||||
if (res != 0) return -1;
|
||||
return rate;
|
||||
}
|
||||
|
||||
//Decompress an LZ4 file.
|
||||
//
|
||||
//Full paths to the files should be provided.
|
||||
//returns: 0 on success.
|
||||
//bytes: provide a single item ulong array to get the bytes currently decompressed in real time. (only when called from a thread/task)
|
||||
// fileBuffer : A buffer that holds an LZ4 file. When assigned the function will decompress from this buffer and will ignore the filePath. (iOS, Android, MacOSX, Linux)
|
||||
// : It can be a byte[] buffer or a native IntPtr buffer (downloaded using the helper function: downloadLZ4FileNative)
|
||||
// : When an IntPtr is used as the input buffer, the size of it must be passed to the function as a string with the inFile parameter!
|
||||
//
|
||||
public static int decompress(string inFile, string outFile, ulong[] bytes, object fileBuffer = null) {
|
||||
if(bytes == null) bytes = new ulong[1];
|
||||
bytes[0] = 0;
|
||||
int res = 0;
|
||||
GCHandle ibuf = GCHandle.Alloc(bytes , GCHandleType.Pinned);
|
||||
|
||||
#if (UNITY_IPHONE || UNITY_IOS || UNITY_STANDALONE_OSX || UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
|
||||
if(fileBuffer != null) {
|
||||
int fileBufferLength = 0;
|
||||
IntPtr fileBufferPointer = IntPtr.Zero;
|
||||
GCHandle fbuf = gcA(null);
|
||||
bool managed = checkObject(fileBuffer, inFile, ref fbuf, ref fileBufferPointer, ref fileBufferLength);
|
||||
|
||||
if (!managed && fileBufferLength == 0) { Debug.Log("Please provide a valid native buffer size as a string in filePath"); return -5; }
|
||||
|
||||
res = LZ4DecompressFile(null, @outFile, ibuf.AddrOfPinnedObject(), fileBufferPointer, fileBufferLength);
|
||||
|
||||
fbuf.Free();
|
||||
ibuf.Free();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
res =LZ4DecompressFile(@inFile, @outFile, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
|
||||
ibuf.Free();
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
//Compress a byte buffer in LZ4 format.
|
||||
//
|
||||
//inBuffer: the uncompressed buffer.
|
||||
//outBuffer: a referenced buffer that will be resized to fit the lz4 compressed data.
|
||||
//level: level of compression (1 - 9).
|
||||
//includeSize: include the uncompressed size of the buffer in the resulted compressed one because lz4 does not include this.
|
||||
//returns true on success
|
||||
//
|
||||
public static bool compressBuffer(byte[] inBuffer, ref byte[] outBuffer, int level, bool includeSize = true) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
IntPtr ptr;
|
||||
|
||||
int res = 0, size = 0;
|
||||
byte[] bsiz = null;
|
||||
|
||||
//if the uncompressed size of the buffer should be included. This is a hack since lz4 lib does not support this.
|
||||
if (includeSize){
|
||||
bsiz = new byte[4];
|
||||
size = 4;
|
||||
bsiz = BitConverter.GetBytes(inBuffer.Length);
|
||||
if (!isle) Array.Reverse(bsiz);
|
||||
}
|
||||
|
||||
if (level < 1) level = 1;
|
||||
if (level > 9) level = 9;
|
||||
|
||||
ptr = LZ4CompressBuffer(cbuf.AddrOfPinnedObject(), inBuffer.Length, ref res, level);
|
||||
|
||||
cbuf.Free();
|
||||
|
||||
if (res == 0 || ptr == IntPtr.Zero) { LZ4releaseBuffer(ptr); return false; }
|
||||
|
||||
System.Array.Resize(ref outBuffer, res + size);
|
||||
|
||||
//add the uncompressed size to the buffer
|
||||
if (includeSize) { for (int i = 0; i < 4; i++) outBuffer[i+res] = bsiz[i]; /*Debug.Log(BitConverter.ToInt32(bsiz, 0));*/ }
|
||||
|
||||
Marshal.Copy(ptr, outBuffer, 0, res );
|
||||
|
||||
LZ4releaseBuffer(ptr);
|
||||
bsiz = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Compress a byte buffer in LZ4 format and return a new buffer compressed.
|
||||
//
|
||||
//inBuffer: the uncompressed buffer.
|
||||
//level: level of compression (1 - 9).
|
||||
//includeSize: include the uncompressed size of the buffer in the resulted compressed one because lz4 does not include this.
|
||||
//returns: a new buffer with the compressed data.
|
||||
//
|
||||
public static byte[] compressBuffer(byte[] inBuffer, int level, bool includeSize = true) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
IntPtr ptr;
|
||||
|
||||
int res = 0, size = 0;
|
||||
byte[] bsiz = null;
|
||||
|
||||
//if the uncompressed size of the buffer should be included. This is a hack since lz4 lib does not support this.
|
||||
if (includeSize){
|
||||
bsiz = new byte[4];
|
||||
size = 4;
|
||||
bsiz = BitConverter.GetBytes(inBuffer.Length);
|
||||
if (!isle) Array.Reverse(bsiz);
|
||||
}
|
||||
|
||||
if (level < 1) level = 1;
|
||||
if (level > 9) level = 9;
|
||||
|
||||
ptr = LZ4CompressBuffer(cbuf.AddrOfPinnedObject(), inBuffer.Length, ref res, level);
|
||||
cbuf.Free();
|
||||
|
||||
if (res == 0 || ptr == IntPtr.Zero) { LZ4releaseBuffer(ptr); return null; }
|
||||
|
||||
byte[] outBuffer = new byte[res + size];
|
||||
|
||||
//add the uncompressed size to the buffer
|
||||
if (includeSize) { for (int i = 0; i < 4; i++) outBuffer[i + res] = bsiz[i]; /*Debug.Log(BitConverter.ToInt32(bsiz, 0));*/ }
|
||||
|
||||
Marshal.Copy(ptr, outBuffer, 0, res);
|
||||
|
||||
LZ4releaseBuffer(ptr);
|
||||
bsiz = null;
|
||||
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
|
||||
//Compress a byte buffer in LZ4 format at a specific position of a fixed size outBuffer
|
||||
//
|
||||
//inBuffer: the uncompressed buffer.
|
||||
//outBuffer: a referenced buffer of fixed size that could have already some lz4 compressed buffers stored.
|
||||
//outBufferPartialIndex: the position at which the compressed data will be written to.
|
||||
//level: level of compression (1 - 9).
|
||||
//
|
||||
//returns compressed size (+4 bytes if footer is used)
|
||||
//
|
||||
public static int compressBufferPartialFixed (byte[] inBuffer, ref byte[] outBuffer,int outBufferPartialIndex, int level, bool includeSize = true) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
IntPtr ptr;
|
||||
|
||||
int res = 0, size = 0;
|
||||
byte[] bsiz = null;
|
||||
|
||||
//if the uncompressed size of the buffer should be included. This is a hack since lz4 lib does not support this.
|
||||
if (includeSize){
|
||||
bsiz = new byte[4];
|
||||
size = 4;
|
||||
bsiz = BitConverter.GetBytes(inBuffer.Length);
|
||||
if (!isle) Array.Reverse(bsiz);
|
||||
}
|
||||
|
||||
if (level < 1) level = 1;
|
||||
if (level > 9) level = 9;
|
||||
|
||||
ptr = LZ4CompressBuffer(cbuf.AddrOfPinnedObject(), inBuffer.Length, ref res, level);
|
||||
|
||||
cbuf.Free();
|
||||
|
||||
if (res == 0 || ptr == IntPtr.Zero) { LZ4releaseBuffer(ptr); return 0; }
|
||||
|
||||
//add the uncompressed size to the buffer
|
||||
if (includeSize) { for (int i = 0; i < 4; i++) outBuffer[outBufferPartialIndex + res + i ] = bsiz[i]; }
|
||||
|
||||
Marshal.Copy(ptr, outBuffer, outBufferPartialIndex, res );
|
||||
|
||||
LZ4releaseBuffer(ptr);
|
||||
bsiz = null;
|
||||
return res + size;
|
||||
}
|
||||
|
||||
|
||||
//compressedBufferSize: compressed size of the buffer to be decompressed
|
||||
//partialIndex: position of an lz4 compressed buffer
|
||||
//
|
||||
//returns the uncompressed size
|
||||
public static int decompressBufferPartialFixed (byte[] inBuffer, ref byte[] outBuffer, int partialIndex , int compressedBufferSize, bool safe = true, bool useFooter = true, int customLength = 0) {
|
||||
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
|
||||
int uncompressedSize = 0;
|
||||
|
||||
//be carefull with this. You must know exactly where your compressed data lies in the inBuffer
|
||||
int res2 = partialIndex + compressedBufferSize;
|
||||
|
||||
|
||||
//if the hacked in LZ4 footer will be used to extract the uncompressed size of the buffer. If the buffer does not have a footer
|
||||
//provide the known uncompressed size through the customLength integer.
|
||||
if (useFooter){
|
||||
res2 -= 4;
|
||||
uncompressedSize = (int)BitConverter.ToInt32(inBuffer, res2);
|
||||
}
|
||||
else{
|
||||
uncompressedSize = customLength;
|
||||
}
|
||||
|
||||
//Check if the uncompressed size is bigger then the size of the fixed buffer. Then:
|
||||
//1. write only the data that fit in it.
|
||||
//2. or return a negative number.
|
||||
//It depends on if we set the safe flag to true or not.
|
||||
if(uncompressedSize > outBuffer.Length) {
|
||||
if(safe) return -101; else uncompressedSize = outBuffer.Length;
|
||||
}
|
||||
|
||||
GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
|
||||
|
||||
IntPtr ptrPartial;
|
||||
ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + partialIndex);
|
||||
|
||||
//res should be the compressed size
|
||||
LZ4DecompressBuffer(ptrPartial, obuf.AddrOfPinnedObject(), uncompressedSize);
|
||||
|
||||
cbuf.Free();
|
||||
obuf.Free();
|
||||
|
||||
return uncompressedSize;
|
||||
}
|
||||
|
||||
|
||||
//Decompress an lz4 compressed buffer to a referenced buffer.
|
||||
//
|
||||
//inBuffer: the lz4 compressed buffer
|
||||
//outBuffer: a referenced buffer that will be resized to store the uncompressed data.
|
||||
//useFooter: if the input Buffer has the uncompressed size info.
|
||||
//customLength: provide the uncompressed size of the compressed buffer. Not needed if the usefooter is used!
|
||||
//returns true on success
|
||||
//
|
||||
public static bool decompressBuffer(byte[] inBuffer, ref byte[] outBuffer, bool useFooter = true, int customLength = 0) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
int uncompressedSize = 0, res2 = inBuffer.Length;
|
||||
|
||||
//if the hacked in LZ4 footer will be used to extract the uncompressed size of the buffer. If the buffer does not have a footer
|
||||
//provide the known uncompressed size through the customLength integer.
|
||||
if (useFooter){
|
||||
res2 -= 4;
|
||||
uncompressedSize = (int)BitConverter.ToInt32(inBuffer, res2);
|
||||
}
|
||||
else{
|
||||
uncompressedSize = customLength;
|
||||
}
|
||||
|
||||
System.Array.Resize(ref outBuffer, uncompressedSize);
|
||||
|
||||
GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
|
||||
|
||||
//res should be the compressed size
|
||||
int res = LZ4DecompressBuffer(cbuf.AddrOfPinnedObject(), obuf.AddrOfPinnedObject(), uncompressedSize);
|
||||
|
||||
cbuf.Free();
|
||||
obuf.Free();
|
||||
|
||||
if (res != res2) { /*Debug.Log("ERROR: " + res.ToString());*/ return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Decompress an lz4 compressed buffer to a referenced fixed size buffer.
|
||||
//
|
||||
//inBuffer: the lz4 compressed buffer
|
||||
//outBuffer: a referenced fixed size buffer where the data will get decompressed
|
||||
//usefooter: if the input Buffer has the uncompressed size info.
|
||||
//customLength: provide the uncompressed size of the compressed buffer. Not needed if the usefooter is used!
|
||||
//returns uncompressedSize
|
||||
//
|
||||
public static int decompressBufferFixed(byte[] inBuffer, ref byte[] outBuffer, bool safe = true, bool useFooter = true, int customLength = 0) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
int uncompressedSize = 0, res2 = inBuffer.Length;
|
||||
|
||||
//if the hacked in LZ4 footer will be used to extract the uncompressed size of the buffer. If the buffer does not have a footer
|
||||
//provide the known uncompressed size through the customLength integer.
|
||||
if (useFooter){
|
||||
res2 -= 4;
|
||||
uncompressedSize = (int)BitConverter.ToInt32(inBuffer, res2);
|
||||
}
|
||||
else{
|
||||
uncompressedSize = customLength;
|
||||
}
|
||||
|
||||
//Check if the uncompressed size is bigger then the size of the fixed buffer. Then:
|
||||
//1. write only the data that fit in it.
|
||||
//2. or return a negative number.
|
||||
//It depends on if we set the safe flag to true or not.
|
||||
if(uncompressedSize > outBuffer.Length) {
|
||||
if(safe) return -101; else uncompressedSize = outBuffer.Length;
|
||||
}
|
||||
|
||||
GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
|
||||
|
||||
//res should be the compressed size
|
||||
int res = LZ4DecompressBuffer(cbuf.AddrOfPinnedObject(), obuf.AddrOfPinnedObject(), uncompressedSize);
|
||||
|
||||
cbuf.Free();
|
||||
obuf.Free();
|
||||
|
||||
if(safe) {
|
||||
if (res != res2) { /*Debug.Log("ERROR: " + res.ToString());*/ return -101; }
|
||||
}
|
||||
|
||||
return uncompressedSize;
|
||||
}
|
||||
|
||||
|
||||
//Decompress an lz4 compressed buffer to a new buffer.
|
||||
//
|
||||
//inBuffer: the lz4 compressed buffer
|
||||
//useFooter: if the input Buffer has the uncompressed size info.
|
||||
//customLength: provide the uncompressed size of the compressed buffer. Not needed if the usefooter is used!
|
||||
//returns: a new buffer with the uncompressed data.
|
||||
//
|
||||
public static byte[] decompressBuffer(byte[] inBuffer, bool useFooter = true, int customLength = 0) {
|
||||
GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
|
||||
int uncompressedSize = 0, res2 = inBuffer.Length;
|
||||
|
||||
//if the hacked in LZ4 footer will be used to extract the uncompressed size of the buffer. If the buffer does not have a footer
|
||||
//provide the known uncompressed size through the customLength integer.
|
||||
if (useFooter)
|
||||
{
|
||||
res2 -= 4;
|
||||
uncompressedSize = (int)BitConverter.ToInt32(inBuffer, res2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uncompressedSize = customLength;
|
||||
}
|
||||
|
||||
byte[] outBuffer = new byte[uncompressedSize];
|
||||
|
||||
GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
|
||||
|
||||
//res should be the compressed size
|
||||
int res = LZ4DecompressBuffer(cbuf.AddrOfPinnedObject(), obuf.AddrOfPinnedObject(), uncompressedSize);
|
||||
|
||||
cbuf.Free();
|
||||
obuf.Free();
|
||||
|
||||
if (res != res2) { /*Debug.Log("ERROR: " + res.ToString());*/ return null; }
|
||||
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
// A reusable native memory pointer for downloading files.
|
||||
public static IntPtr nativeBuffer = IntPtr.Zero;
|
||||
public static bool nativeBufferIsBeingUsed = false;
|
||||
public static int nativeOffset = 0;
|
||||
|
||||
// A Coroutine to dowload a file to a native/unmaged memory buffer.
|
||||
// You can call it for an IntPtr.
|
||||
//
|
||||
//
|
||||
// This function can only be called for one file at a time. Don't use it to call multiple files at once.
|
||||
//
|
||||
// This is useful to avoid memory spikes when downloading large files and intend to decompress from memory.
|
||||
// With the old method, a copy of the downloaded file to memory would be produced by pinning the buffer to memory.
|
||||
// Now with this method, it is downloaded to memory and can be manipulated with no memory spikes.
|
||||
//
|
||||
// In any case, if you don't need the created in-Memory file, you should use the LZ4.LZ4releaseBuffer function to free the memory!
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// url: The url of the file you want to download to a native memory buffer.
|
||||
// downloadDone: Informs a bool that the download of the file to memory is done.
|
||||
// pointer: An IntPtr for a native memory buffer
|
||||
// fileSize: The size of the downloaded file will be returned here.
|
||||
public static IEnumerator downloadLZ4FileNative(string url, Action<bool> downloadDone, Action<IntPtr> pointer = null, Action<int> fileSize = null) {
|
||||
// Get the file lenght first, so we create a correct size native memory buffer.
|
||||
UnityWebRequest wr = UnityWebRequest.Head(url);
|
||||
|
||||
nativeBufferIsBeingUsed = true;
|
||||
|
||||
yield return wr.SendWebRequest();
|
||||
string size = wr.GetResponseHeader("Content-Length");
|
||||
|
||||
nativeBufferIsBeingUsed = false;
|
||||
|
||||
#if UNITY_2020_1_OR_NEWER
|
||||
if (wr.result == UnityWebRequest.Result.ConnectionError || wr.result == UnityWebRequest.Result.ProtocolError) {
|
||||
#else
|
||||
if (wr.isNetworkError || wr.isHttpError) {
|
||||
#endif
|
||||
Debug.LogError("Error While Getting Length: " + wr.error);
|
||||
} else {
|
||||
if (!nativeBufferIsBeingUsed) {
|
||||
|
||||
//get the size of the zip
|
||||
int zipSize = Convert.ToInt32(size);
|
||||
|
||||
// If the zip size is larger then 0
|
||||
if (zipSize > 0) {
|
||||
|
||||
nativeBuffer = LZ4Create_Buffer(zipSize);
|
||||
nativeBufferIsBeingUsed = true;
|
||||
|
||||
// buffer for the download
|
||||
byte[] bytes = new byte[2048];
|
||||
nativeOffset = 0;
|
||||
|
||||
using (UnityWebRequest wwwSK = UnityWebRequest.Get(url)) {
|
||||
|
||||
// Here we call our custom webrequest function to download our archive to a native memory buffer.
|
||||
wwwSK.downloadHandler = new CustomWebRequest4(bytes);
|
||||
|
||||
yield return wwwSK.SendWebRequest();
|
||||
|
||||
if (wwwSK.error != null) {
|
||||
Debug.Log(wwwSK.error);
|
||||
} else {
|
||||
downloadDone(true);
|
||||
|
||||
if(pointer != null) { pointer(nativeBuffer); fileSize(zipSize); }
|
||||
|
||||
//reset intermediate buffer params.
|
||||
nativeBufferIsBeingUsed = false;
|
||||
nativeOffset = 0;
|
||||
nativeBuffer = IntPtr.Zero;
|
||||
|
||||
//Debug.Log("Custom download done");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else { Debug.LogError("Native buffer is being used, or not yet freed!"); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// A custom WebRequest Override to download data to a native-unmanaged memory buffer.
|
||||
public class CustomWebRequest4 : DownloadHandlerScript {
|
||||
|
||||
public CustomWebRequest4()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public CustomWebRequest4(byte[] buffer)
|
||||
: base(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
protected override byte[] GetData() { return null; }
|
||||
|
||||
|
||||
protected override bool ReceiveData(byte[] bytesFromServer, int dataLength) {
|
||||
if (bytesFromServer == null || bytesFromServer.Length < 1) {
|
||||
Debug.Log("CustomWebRequest: Received a null/empty buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
var pbuf = gcA(bytesFromServer);
|
||||
|
||||
//Process byteFromServer
|
||||
LZ4AddTo_Buffer(nativeBuffer, nativeOffset, pbuf.AddrOfPinnedObject(), dataLength );
|
||||
nativeOffset += dataLength;
|
||||
pbuf.Free();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use the below functions only when needed. You get the same functionality from the main coroutine.
|
||||
/*
|
||||
// If all data has been received from the server
|
||||
protected override void CompleteContent()
|
||||
{
|
||||
//Debug.Log(Download Complete.");
|
||||
}
|
||||
|
||||
// If a Content-Length header is received from the server.
|
||||
protected override void ReceiveContentLength(int fileLength)
|
||||
{
|
||||
//Debug.Log("ReceiveContentLength: " + fileLength);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
12
Assets/Plugins/LZ4/Plugins/LZ4.cs.meta
Normal file
12
Assets/Plugins/LZ4/Plugins/LZ4.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f2aff91fc4b7a5478086149224b1d30
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/WebGL.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/WebGL.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e70a6eaee266b246af755bee6eb5452
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/WebGL/cpp.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/WebGL/cpp.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19b593114c441f349b1510ae835c8ef8
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1485
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.cpp
Normal file
1485
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.cpp
Normal file
File diff suppressed because it is too large
Load Diff
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.cpp.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.cpp.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3feaddf74316e0c4680d550568d8e111
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
360
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.h
Normal file
360
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.h
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
LZ3 - Fast LZ compression algorithm
|
||||
Header File
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ3 source repository : https://github.com/Cyan4973/lz3
|
||||
- LZ3 public forum : https://groups.google.com/forum/#!forum/lz3c
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* lz3.h provides block compression functions, and gives full buffer control to programmer.
|
||||
* If you need to generate inter-operable compressed data (respecting LZ3 frame specification),
|
||||
* and can let the library handle its own memory, please use lz3frame.h instead.
|
||||
*/
|
||||
|
||||
/**************************************
|
||||
* Version
|
||||
**************************************/
|
||||
#define LZ3__VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LZ3__VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ3__VERSION_RELEASE 1 /* for tweaks, bug-fixes, or development */
|
||||
#define LZ3__VERSION_NUMBER (LZ3__VERSION_MAJOR *100*100 + LZ3__VERSION_MINOR *100 + LZ3__VERSION_RELEASE)
|
||||
int LZ3__versionNumber (void);
|
||||
|
||||
/**************************************
|
||||
* Tuning parameter
|
||||
**************************************/
|
||||
/*
|
||||
* LZ3__MEMORY_USAGE :
|
||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||
* Increasing memory usage improves compression ratio
|
||||
* Reduced memory usage can improve speed, due to cache effect
|
||||
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||
*/
|
||||
#define LZ3__MEMORY_USAGE 14
|
||||
|
||||
|
||||
/**************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
|
||||
int LZ3__compress_default(const char* source, char* dest, int sourceSize, int maxDestSize);
|
||||
int LZ3__decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
|
||||
/*
|
||||
LZ3__compress_default() :
|
||||
Compresses 'sourceSize' bytes from buffer 'source'
|
||||
into already allocated 'dest' buffer of size 'maxDestSize'.
|
||||
Compression is guaranteed to succeed if 'maxDestSize' >= LZ3__compressBound(sourceSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'source' into a more limited 'dest' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
As a consequence, 'dest' content is not valid.
|
||||
This function never writes outside 'dest' buffer, nor read outside 'source' buffer.
|
||||
sourceSize : Max supported value is LZ3__MAX_INPUT_VALUE
|
||||
maxDestSize : full or partial size of buffer 'dest' (which must be already allocated)
|
||||
return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize)
|
||||
or 0 if compression fails
|
||||
|
||||
LZ3__decompress_safe() :
|
||||
compressedSize : is the precise full size of the compressed block.
|
||||
maxDecompressedSize : is the size of destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (<0).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function is protected against buffer overflow exploits, including malicious data packets.
|
||||
It never writes outside output buffer, nor reads outside input buffer.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LZ3__MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
//#define LZ3__COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ3__MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
|
||||
/*
|
||||
LZ3__compressBound() :
|
||||
Provides the maximum size that LZ3 compression may output in a "worst case" scenario (input data not compressible)
|
||||
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||
Macro LZ3__COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that LZ3__compress_default() compress faster when dest buffer size is >= LZ3__compressBound(srcSize)
|
||||
inputSize : max supported value is LZ3__MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is too large ( > LZ3__MAX_INPUT_SIZE)
|
||||
*/
|
||||
//int LZ3__compressBound(int inputSize);
|
||||
|
||||
/*
|
||||
LZ3__compress_fast() :
|
||||
Same as LZ3__compress_default(), but allows to select an "acceleration" factor.
|
||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
An acceleration value of "1" is the same as regular LZ3__compress_default()
|
||||
Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz3.c), which is 1.
|
||||
*/
|
||||
int LZ3__compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ3__compress_fast_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LZ3__sizeofState() to know how much memory must be allocated,
|
||||
and allocate it on 8-bytes boundaries (using malloc() typically).
|
||||
Then, provide it as 'void* state' to compression function.
|
||||
*/
|
||||
int LZ3__sizeofState(void);
|
||||
int LZ3__compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration);
|
||||
|
||||
|
||||
/*
|
||||
LZ3__compress_destSize() :
|
||||
Reverse the logic, by compressing as much data as possible from 'source' buffer
|
||||
into already allocated buffer 'dest' of size 'targetDestSize'.
|
||||
This function either compresses the entire 'source' content into 'dest' if it's large enough,
|
||||
or fill 'dest' buffer completely with as much data as possible from 'source'.
|
||||
*sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'.
|
||||
New value is necessarily <= old value.
|
||||
return : Nb bytes written into 'dest' (necessarily <= targetDestSize)
|
||||
or 0 if compression fails
|
||||
*/
|
||||
int LZ3__compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize);
|
||||
|
||||
|
||||
/*
|
||||
LZ3__decompress_fast() :
|
||||
originalSize : is the original and therefore uncompressed size
|
||||
return : the number of bytes read from the source buffer (in other words, the compressed size)
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes.
|
||||
note : This function fully respect memory boundaries for properly formed compressed data.
|
||||
It is a bit faster than LZ3__decompress_safe().
|
||||
However, it does not provide any protection against intentionally modified data stream (malicious input).
|
||||
Use this function in trusted environment only (data to decode comes from a trusted source).
|
||||
*/
|
||||
int LZ3__decompress_fast (const char* source, char* dest, int originalSize);
|
||||
|
||||
/*
|
||||
LZ3__decompress_safe_partial() :
|
||||
This function decompress a compressed block of size 'compressedSize' at position 'source'
|
||||
into destination buffer 'dest' of size 'maxDecompressedSize'.
|
||||
The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached,
|
||||
reducing decompression time.
|
||||
return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize)
|
||||
Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller.
|
||||
Always control how many bytes were decoded.
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets
|
||||
*/
|
||||
int LZ3__decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize);
|
||||
|
||||
|
||||
/***********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
#define LZ3__STREAMSIZE_U64 ((1 << (LZ3__MEMORY_USAGE-3)) + 4)
|
||||
#define LZ3__STREAMSIZE (LZ3__STREAMSIZE_U64 * sizeof(long long))
|
||||
/*
|
||||
* LZ3__stream_t
|
||||
* information structure to track an LZ3 stream.
|
||||
* important : init this structure content before first use !
|
||||
* note : only allocated directly the structure if you are statically linking LZ3
|
||||
* If you are using liblz3 as a DLL, please use below construction methods instead.
|
||||
*/
|
||||
typedef struct { long long table[LZ3__STREAMSIZE_U64]; } LZ3__stream_t;
|
||||
|
||||
/*
|
||||
* LZ3__resetStream
|
||||
* Use this function to init an allocated LZ3__stream_t structure
|
||||
*/
|
||||
void LZ3__resetStream (LZ3__stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ3__createStream will allocate and initialize an LZ3__stream_t structure
|
||||
* LZ3__freeStream releases its memory.
|
||||
* In the context of a DLL (liblz3), please use these methods rather than the static struct.
|
||||
* They are more future proof, in case of a change of LZ3__stream_t size.
|
||||
*/
|
||||
LZ3__stream_t* LZ3__createStream(void);
|
||||
int LZ3__freeStream (LZ3__stream_t* streamPtr);
|
||||
|
||||
/*
|
||||
* LZ3__loadDict
|
||||
* Use this function to load a static dictionary into LZ3__stream.
|
||||
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
|
||||
* Loading a size of 0 is allowed.
|
||||
* Return : dictionary size, in bytes (necessarily <= 64 KB)
|
||||
*/
|
||||
int LZ3__loadDict (LZ3__stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
/*
|
||||
* LZ3__compress_fast_continue
|
||||
* Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio.
|
||||
* Important : Previous data blocks are assumed to still be present and unmodified !
|
||||
* 'dst' buffer must be already allocated.
|
||||
* If maxDstSize >= LZ3__compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||
* If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero.
|
||||
*/
|
||||
int LZ3__compress_fast_continue (LZ3__stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration);
|
||||
|
||||
/*
|
||||
* LZ3__saveDict
|
||||
* If previously compressed data block is not guaranteed to remain available at its memory location
|
||||
* save it into a safer place (char* safeBuffer)
|
||||
* Note : you don't need to call LZ3__loadDict() afterwards,
|
||||
* dictionary is immediately usable, you can therefore call LZ3__compress_fast_continue()
|
||||
* Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error
|
||||
*/
|
||||
int LZ3__saveDict (LZ3__stream_t* streamPtr, char* safeBuffer, int dictSize);
|
||||
|
||||
|
||||
/************************************************
|
||||
* Streaming Decompression Functions
|
||||
************************************************/
|
||||
|
||||
#define LZ3__STREAMDECODESIZE_U64 4
|
||||
#define LZ3__STREAMDECODESIZE (LZ3__STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||
typedef struct { unsigned long long table[LZ3__STREAMDECODESIZE_U64]; } LZ3__streamDecode_t;
|
||||
/*
|
||||
* LZ3__streamDecode_t
|
||||
* information structure to track an LZ3 stream.
|
||||
* init this structure content using LZ3__setStreamDecode or memset() before first use !
|
||||
*
|
||||
* In the context of a DLL (liblz3) please prefer usage of construction methods below.
|
||||
* They are more future proof, in case of a change of LZ3__streamDecode_t size in the future.
|
||||
* LZ3__createStreamDecode will allocate and initialize an LZ3__streamDecode_t structure
|
||||
* LZ3__freeStreamDecode releases its memory.
|
||||
*/
|
||||
LZ3__streamDecode_t* LZ3__createStreamDecode(void);
|
||||
int LZ3__freeStreamDecode (LZ3__streamDecode_t* LZ3__stream);
|
||||
|
||||
/*
|
||||
* LZ3__setStreamDecode
|
||||
* Use this function to instruct where to find the dictionary.
|
||||
* Setting a size of 0 is allowed (same effect as reset).
|
||||
* Return : 1 if OK, 0 if error
|
||||
*/
|
||||
int LZ3__setStreamDecode (LZ3__streamDecode_t* LZ3__streamDecode, const char* dictionary, int dictSize);
|
||||
|
||||
/*
|
||||
*_continue() :
|
||||
These decoding functions allow decompression of multiple blocks in "streaming" mode.
|
||||
Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB)
|
||||
In the case of a ring buffers, decoding buffer must be either :
|
||||
- Exactly same size as encoding buffer, with same update rule (block boundaries at same positions)
|
||||
In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB).
|
||||
- Larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||
maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
- _At least_ 64 KB + 8 bytes + maxBlockSize.
|
||||
In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
and encoding ring buffer can have any size, including larger than decoding buffer.
|
||||
Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer,
|
||||
and indicate where it is saved using LZ3__setStreamDecode()
|
||||
*/
|
||||
int LZ3__decompress_safe_continue (LZ3__streamDecode_t* LZ3__streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize);
|
||||
int LZ3__decompress_fast_continue (LZ3__streamDecode_t* LZ3__streamDecode, const char* source, char* dest, int originalSize);
|
||||
|
||||
|
||||
/*
|
||||
Advanced decoding functions :
|
||||
*_usingDict() :
|
||||
These decoding functions work the same as
|
||||
a combination of LZ3__setStreamDecode() followed by LZ3__decompress_x_continue()
|
||||
They are stand-alone. They don't need nor update an LZ3__streamDecode_t structure.
|
||||
*/
|
||||
int LZ3__decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
|
||||
int LZ3__decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
/* Deprecate Warnings */
|
||||
/* Should these warnings messages be a problem,
|
||||
it is generally possible to disable them,
|
||||
with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual for example.
|
||||
You can also define LZ3__DEPRECATE_WARNING_DEFBLOCK. */
|
||||
#ifndef LZ3__DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ3__DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ3__GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if (LZ3__GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ3__DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ3__GCC_VERSION >= 301)
|
||||
# define LZ3__DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ3__DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ3__DEPRECATED for this compiler")
|
||||
# define LZ3__DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* LZ3__DEPRECATE_WARNING_DEFBLOCK */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
/* These functions are planned to start generate warnings by r131 approximately */
|
||||
int LZ3__compress (const char* source, char* dest, int sourceSize);
|
||||
int LZ3__compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
int LZ3__compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ3__compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ3__compress_continue (LZ3__stream_t* LZ3__streamPtr, const char* source, char* dest, int inputSize);
|
||||
int LZ3__compress_limitedOutput_continue (LZ3__stream_t* LZ3__streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Obsolete decompression functions */
|
||||
/* These function names are completely deprecated and must no longer be used.
|
||||
They are only provided here for compatibility with older programs.
|
||||
- LZ3__uncompress is the same as LZ3__decompress_fast
|
||||
- LZ3__uncompress_unknownOutputSize is the same as LZ3__decompress_safe
|
||||
These function prototypes are now disabled; uncomment them only if you really need them.
|
||||
It is highly recommended to stop using these prototypes and migrate to maintained ones */
|
||||
/* int LZ3__uncompress (const char* source, char* dest, int outputSize); */
|
||||
/* int LZ3__uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
|
||||
|
||||
/* Obsolete streaming functions; use new streaming interface whenever possible */
|
||||
LZ3__DEPRECATED("use LZ3__createStream() instead") void* LZ3__create (char* inputBuffer);
|
||||
LZ3__DEPRECATED("use LZ3__createStream() instead") int LZ3__sizeofStreamState(void);
|
||||
LZ3__DEPRECATED("use LZ3__resetStream() instead") int LZ3__resetStreamState(void* state, char* inputBuffer);
|
||||
LZ3__DEPRECATED("use LZ3__saveDict() instead") char* LZ3__slideInputBuffer (void* state);
|
||||
|
||||
/* Obsolete streaming decoding functions */
|
||||
LZ3__DEPRECATED("use LZ3__decompress_safe_usingDict() instead") int LZ3__decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||
LZ3__DEPRECATED("use LZ3__decompress_fast_usingDict() instead") int LZ3__decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5bbb091252993d4c9af8fb1027244a1
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1441
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.cpp
Normal file
1441
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.cpp
Normal file
File diff suppressed because it is too large
Load Diff
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.cpp.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.cpp.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e14348bbbccf3a43883b495fd4da244
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
270
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.h
Normal file
270
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.h
Normal file
@@ -0,0 +1,270 @@
|
||||
|
||||
/* LZ3F is a stand-alone API to create LZ3-compressed frames
|
||||
* fully conformant to specification v1.5.1.
|
||||
* All related operations, including memory management, are handled by the library.
|
||||
* You don't need lz3.h when using lz3frame.h.
|
||||
* */
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Error management
|
||||
* ************************************/
|
||||
typedef size_t LZ3F_errorCode_t;
|
||||
|
||||
unsigned LZ3F_isError(LZ3F_errorCode_t code);
|
||||
const char* LZ3F_getErrorName(LZ3F_errorCode_t code); /* return error code string; useful for debugging */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Frame compression types
|
||||
* ************************************/
|
||||
//#define LZ3F_DISABLE_OBSOLETE_ENUMS
|
||||
#ifndef LZ3F_DISABLE_OBSOLETE_ENUMS
|
||||
# define LZ3F_OBSOLETE_ENUM(x) ,x
|
||||
#else
|
||||
# define LZ3F_OBSOLETE_ENUM(x)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LZ3F_default=0,
|
||||
LZ3F_max64KB=4,
|
||||
LZ3F_max256KB=5,
|
||||
LZ3F_max1MB=6,
|
||||
LZ3F_max4MB=7
|
||||
LZ3F_OBSOLETE_ENUM(max64KB = LZ3F_max64KB)
|
||||
LZ3F_OBSOLETE_ENUM(max256KB = LZ3F_max256KB)
|
||||
LZ3F_OBSOLETE_ENUM(max1MB = LZ3F_max1MB)
|
||||
LZ3F_OBSOLETE_ENUM(max4MB = LZ3F_max4MB)
|
||||
} LZ3F_blockSizeID_t;
|
||||
|
||||
typedef enum {
|
||||
LZ3F_blockLinked=0,
|
||||
LZ3F_blockIndependent
|
||||
LZ3F_OBSOLETE_ENUM(blockLinked = LZ3F_blockLinked)
|
||||
LZ3F_OBSOLETE_ENUM(blockIndependent = LZ3F_blockIndependent)
|
||||
} LZ3F_blockMode_t;
|
||||
|
||||
typedef enum {
|
||||
LZ3F_noContentChecksum=0,
|
||||
LZ3F_contentChecksumEnabled
|
||||
LZ3F_OBSOLETE_ENUM(noContentChecksum = LZ3F_noContentChecksum)
|
||||
LZ3F_OBSOLETE_ENUM(contentChecksumEnabled = LZ3F_contentChecksumEnabled)
|
||||
} LZ3F_contentChecksum_t;
|
||||
|
||||
typedef enum {
|
||||
LZ3F_frame=0,
|
||||
LZ3F_skippableFrame
|
||||
LZ3F_OBSOLETE_ENUM(skippableFrame = LZ3F_skippableFrame)
|
||||
} LZ3F_frameType_t;
|
||||
|
||||
#ifndef LZ3F_DISABLE_OBSOLETE_ENUMS
|
||||
typedef LZ3F_blockSizeID_t blockSizeID_t;
|
||||
typedef LZ3F_blockMode_t blockMode_t;
|
||||
typedef LZ3F_frameType_t frameType_t;
|
||||
typedef LZ3F_contentChecksum_t contentChecksum_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
LZ3F_blockSizeID_t blockSizeID; /* max64KB, max256KB, max1MB, max4MB ; 0 == default */
|
||||
LZ3F_blockMode_t blockMode; /* blockLinked, blockIndependent ; 0 == default */
|
||||
LZ3F_contentChecksum_t contentChecksumFlag; /* noContentChecksum, contentChecksumEnabled ; 0 == default */
|
||||
LZ3F_frameType_t frameType; /* LZ3F_frame, skippableFrame ; 0 == default */
|
||||
unsigned long long contentSize; /* Size of uncompressed (original) content ; 0 == unknown */
|
||||
unsigned reserved[2]; /* must be zero for forward compatibility */
|
||||
} LZ3F_frameInfo_t;
|
||||
|
||||
typedef struct {
|
||||
LZ3F_frameInfo_t frameInfo;
|
||||
int compressionLevel; /* 0 == default (fast mode); values above 16 count as 16; values below 0 count as 0 */
|
||||
unsigned autoFlush; /* 1 == always flush (reduce need for tmp buffer) */
|
||||
unsigned reserved[4]; /* must be zero for forward compatibility */
|
||||
} LZ3F_preferences_t;
|
||||
|
||||
|
||||
/***********************************
|
||||
* Simple compression function
|
||||
* *********************************/
|
||||
size_t LZ3F_compressFrameBound(size_t srcSize, const LZ3F_preferences_t* preferencesPtr);
|
||||
|
||||
size_t LZ3F_compressFrame(void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ3F_preferences_t* preferencesPtr);
|
||||
/* LZ3F_compressFrame()
|
||||
* Compress an entire srcBuffer into a valid LZ3 frame, as defined by specification v1.5.1
|
||||
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
|
||||
* You can get the minimum value of dstMaxSize by using LZ3F_compressFrameBound()
|
||||
* If this condition is not respected, LZ3F_compressFrame() will fail (result is an errorCode)
|
||||
* The LZ3F_preferences_t structure is optional : you can provide NULL as argument. All preferences will be set to default.
|
||||
* The result of the function is the number of bytes written into dstBuffer.
|
||||
* The function outputs an error code if it fails (can be tested using LZ3F_isError())
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**********************************
|
||||
* Advanced compression functions
|
||||
**********************************/
|
||||
typedef struct LZ3F_cctx_s* LZ3F_compressionContext_t; /* must be aligned on 8-bytes */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableSrc; /* 1 == src content will remain available on future calls to LZ3F_compress(); avoid saving src content within tmp buffer as future dictionary */
|
||||
unsigned reserved[3];
|
||||
} LZ3F_compressOptions_t;
|
||||
|
||||
/* Resource Management */
|
||||
|
||||
#define LZ3F_VERSION 100
|
||||
LZ3F_errorCode_t LZ3F_createCompressionContext(LZ3F_compressionContext_t* cctxPtr, unsigned version);
|
||||
LZ3F_errorCode_t LZ3F_freeCompressionContext(LZ3F_compressionContext_t cctx);
|
||||
/* LZ3F_createCompressionContext() :
|
||||
* The first thing to do is to create a compressionContext object, which will be used in all compression operations.
|
||||
* This is achieved using LZ3F_createCompressionContext(), which takes as argument a version and an LZ3F_preferences_t structure.
|
||||
* The version provided MUST be LZ3F_VERSION. It is intended to track potential version differences between different binaries.
|
||||
* The function will provide a pointer to a fully allocated LZ3F_compressionContext_t object.
|
||||
* If the result LZ3F_errorCode_t is not zero, there was an error during context creation.
|
||||
* Object can release its memory using LZ3F_freeCompressionContext();
|
||||
*/
|
||||
|
||||
|
||||
/* Compression */
|
||||
|
||||
size_t LZ3F_compressBegin(LZ3F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ3F_preferences_t* prefsPtr);
|
||||
/* LZ3F_compressBegin() :
|
||||
* will write the frame header into dstBuffer.
|
||||
* dstBuffer must be large enough to accommodate a header (dstMaxSize). Maximum header size is 15 bytes.
|
||||
* The LZ3F_preferences_t structure is optional : you can provide NULL as argument, all preferences will then be set to default.
|
||||
* The result of the function is the number of bytes written into dstBuffer for the header
|
||||
* or an error code (can be tested using LZ3F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ3F_compressBound(size_t srcSize, const LZ3F_preferences_t* prefsPtr);
|
||||
/* LZ3F_compressBound() :
|
||||
* Provides the minimum size of Dst buffer given srcSize to handle worst case situations.
|
||||
* Different preferences can produce different results.
|
||||
* prefsPtr is optional : you can provide NULL as argument, all preferences will then be set to cover worst case.
|
||||
* This function includes frame termination cost (4 bytes, or 8 if frame checksum is enabled)
|
||||
*/
|
||||
|
||||
size_t LZ3F_compressUpdate(LZ3F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const void* srcBuffer, size_t srcSize, const LZ3F_compressOptions_t* cOptPtr);
|
||||
/* LZ3F_compressUpdate()
|
||||
* LZ3F_compressUpdate() can be called repetitively to compress as much data as necessary.
|
||||
* The most important rule is that dstBuffer MUST be large enough (dstMaxSize) to ensure compression completion even in worst case.
|
||||
* You can get the minimum value of dstMaxSize by using LZ3F_compressBound().
|
||||
* If this condition is not respected, LZ3F_compress() will fail (result is an errorCode).
|
||||
* LZ3F_compressUpdate() doesn't guarantee error recovery, so you have to reset compression context when an error occurs.
|
||||
* The LZ3F_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* The result of the function is the number of bytes written into dstBuffer : it can be zero, meaning input data was just buffered.
|
||||
* The function outputs an error code if it fails (can be tested using LZ3F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ3F_flush(LZ3F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ3F_compressOptions_t* cOptPtr);
|
||||
/* LZ3F_flush()
|
||||
* Should you need to generate compressed data immediately, without waiting for the current block to be filled,
|
||||
* you can call LZ3__flush(), which will immediately compress any remaining data buffered within cctx.
|
||||
* Note that dstMaxSize must be large enough to ensure the operation will be successful.
|
||||
* LZ3F_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* The result of the function is the number of bytes written into dstBuffer
|
||||
* (it can be zero, this means there was no data left within cctx)
|
||||
* The function outputs an error code if it fails (can be tested using LZ3F_isError())
|
||||
*/
|
||||
|
||||
size_t LZ3F_compressEnd(LZ3F_compressionContext_t cctx, void* dstBuffer, size_t dstMaxSize, const LZ3F_compressOptions_t* cOptPtr);
|
||||
/* LZ3F_compressEnd()
|
||||
* When you want to properly finish the compressed frame, just call LZ3F_compressEnd().
|
||||
* It will flush whatever data remained within compressionContext (like LZ3__flush())
|
||||
* but also properly finalize the frame, with an endMark and a checksum.
|
||||
* The result of the function is the number of bytes written into dstBuffer (necessarily >= 4 (endMark), or 8 if optional frame checksum is enabled)
|
||||
* The function outputs an error code if it fails (can be tested using LZ3F_isError())
|
||||
* The LZ3F_compressOptions_t structure is optional : you can provide NULL as argument.
|
||||
* A successful call to LZ3F_compressEnd() makes cctx available again for next compression task.
|
||||
*/
|
||||
|
||||
|
||||
/***********************************
|
||||
* Decompression functions
|
||||
***********************************/
|
||||
|
||||
typedef struct LZ3F_dctx_s* LZ3F_decompressionContext_t; /* must be aligned on 8-bytes */
|
||||
|
||||
typedef struct {
|
||||
unsigned stableDst; /* guarantee that decompressed data will still be there on next function calls (avoid storage into tmp buffers) */
|
||||
unsigned reserved[3];
|
||||
} LZ3F_decompressOptions_t;
|
||||
|
||||
|
||||
/* Resource management */
|
||||
|
||||
LZ3F_errorCode_t LZ3F_createDecompressionContext(LZ3F_decompressionContext_t* dctxPtr, unsigned version);
|
||||
LZ3F_errorCode_t LZ3F_freeDecompressionContext(LZ3F_decompressionContext_t dctx);
|
||||
/* LZ3F_createDecompressionContext() :
|
||||
* The first thing to do is to create an LZ3F_decompressionContext_t object, which will be used in all decompression operations.
|
||||
* This is achieved using LZ3F_createDecompressionContext().
|
||||
* The version provided MUST be LZ3F_VERSION. It is intended to track potential breaking differences between different versions.
|
||||
* The function will provide a pointer to a fully allocated and initialized LZ3F_decompressionContext_t object.
|
||||
* The result is an errorCode, which can be tested using LZ3F_isError().
|
||||
* dctx memory can be released using LZ3F_freeDecompressionContext();
|
||||
* The result of LZ3F_freeDecompressionContext() is indicative of the current state of decompressionContext when being released.
|
||||
* That is, it should be == 0 if decompression has been completed fully and correctly.
|
||||
*/
|
||||
|
||||
|
||||
/* Decompression */
|
||||
|
||||
size_t LZ3F_getFrameInfo(LZ3F_decompressionContext_t dctx,
|
||||
LZ3F_frameInfo_t* frameInfoPtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr);
|
||||
/* LZ3F_getFrameInfo()
|
||||
* This function decodes frame header information (such as max blockSize, frame checksum, etc.).
|
||||
* Its usage is optional : you can start by calling directly LZ3F_decompress() instead.
|
||||
* The objective is to extract frame header information, typically for allocation purposes.
|
||||
* LZ3F_getFrameInfo() can also be used anytime *after* starting decompression, on any valid LZ3F_decompressionContext_t.
|
||||
* The result is *copied* into an existing LZ3F_frameInfo_t structure which must be already allocated.
|
||||
* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* The function result is an hint of how many srcSize bytes LZ3F_decompress() expects for next call,
|
||||
* or an error code which can be tested using LZ3F_isError()
|
||||
* (typically, when there is not enough src bytes to fully decode the frame header)
|
||||
* You are expected to resume decompression from where it stopped (srcBuffer + *srcSizePtr)
|
||||
*/
|
||||
|
||||
size_t LZ3F_decompress(LZ3F_decompressionContext_t dctx,
|
||||
void* dstBuffer, size_t* dstSizePtr,
|
||||
const void* srcBuffer, size_t* srcSizePtr,
|
||||
const LZ3F_decompressOptions_t* dOptPtr);
|
||||
/* LZ3F_decompress()
|
||||
* Call this function repetitively to regenerate data compressed within srcBuffer.
|
||||
* The function will attempt to decode *srcSizePtr bytes from srcBuffer, into dstBuffer of maximum size *dstSizePtr.
|
||||
*
|
||||
* The number of bytes regenerated into dstBuffer will be provided within *dstSizePtr (necessarily <= original value).
|
||||
*
|
||||
* The number of bytes read from srcBuffer will be provided within *srcSizePtr (necessarily <= original value).
|
||||
* If number of bytes read is < number of bytes provided, then decompression operation is not completed.
|
||||
* It typically happens when dstBuffer is not large enough to contain all decoded data.
|
||||
* LZ3F_decompress() must be called again, starting from where it stopped (srcBuffer + *srcSizePtr)
|
||||
* The function will check this condition, and refuse to continue if it is not respected.
|
||||
*
|
||||
* dstBuffer is supposed to be flushed between each call to the function, since its content will be overwritten.
|
||||
* dst arguments can be changed at will with each consecutive call to the function.
|
||||
*
|
||||
* The function result is an hint of how many srcSize bytes LZ3F_decompress() expects for next call.
|
||||
* Schematically, it's the size of the current (or remaining) compressed block + header of next block.
|
||||
* Respecting the hint provides some boost to performance, since it does skip intermediate buffers.
|
||||
* This is just a hint, you can always provide any srcSize you want.
|
||||
* When a frame is fully decoded, the function result will be 0 (no more data expected).
|
||||
* If decompression failed, function result is an error code, which can be tested using LZ3F_isError().
|
||||
*
|
||||
* After a frame is fully decoded, dctx can be used again to decompress another frame.
|
||||
*/
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10bedf9e6c389a74f8f61a784caaefb5
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
81
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame_static.h
Normal file
81
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame_static.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
LZ3 auto-framing library
|
||||
Header File for static linking only
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ3 source repository : https://github.com/Cyan4973/lz3
|
||||
- LZ3 public forum : https://groups.google.com/forum/#!forum/lz3c
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* lz3frame_static.h should be used solely in the context of static linking.
|
||||
* It contains definitions which may still change overtime.
|
||||
* Never use it in the context of DLL linking.
|
||||
* */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include "lz4frame.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* Error management
|
||||
* ************************************/
|
||||
#define LZ3F_LIST_ERRORS(ITEM) \
|
||||
ITEM(OK_NoError) ITEM(ERROR_GENERIC) \
|
||||
ITEM(ERROR_maxBlockSize_invalid) ITEM(ERROR_blockMode_invalid) ITEM(ERROR_contentChecksumFlag_invalid) \
|
||||
ITEM(ERROR_compressionLevel_invalid) \
|
||||
ITEM(ERROR_headerVersion_wrong) ITEM(ERROR_blockChecksum_unsupported) ITEM(ERROR_reservedFlag_set) \
|
||||
ITEM(ERROR_allocation_failed) \
|
||||
ITEM(ERROR_srcSize_tooLarge) ITEM(ERROR_dstMaxSize_tooSmall) \
|
||||
ITEM(ERROR_frameHeader_incomplete) ITEM(ERROR_frameType_unknown) ITEM(ERROR_frameSize_wrong) \
|
||||
ITEM(ERROR_srcPtr_wrong) \
|
||||
ITEM(ERROR_decompressionFailed) \
|
||||
ITEM(ERROR_headerChecksum_invalid) ITEM(ERROR_contentChecksum_invalid) \
|
||||
ITEM(ERROR_maxCode)
|
||||
|
||||
//#define LZ3F_DISABLE_OLD_ENUMS
|
||||
#ifndef LZ3F_DISABLE_OLD_ENUMS
|
||||
#define LZ3F_GENERATE_ENUM(ENUM) LZ3F_##ENUM, ENUM = LZ3F_##ENUM,
|
||||
#else
|
||||
#define LZ3F_GENERATE_ENUM(ENUM) LZ3F_##ENUM,
|
||||
#endif
|
||||
typedef enum { LZ3F_LIST_ERRORS(LZ3F_GENERATE_ENUM) } LZ3F_errorCodes; /* enum is exposed, to handle specific errors; compare function result to -enum value */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame_static.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4frame_static.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1cf54d5b4faeac14a97c77dca9020367
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
953
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.cpp
Normal file
953
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.cpp
Normal file
@@ -0,0 +1,953 @@
|
||||
|
||||
|
||||
/**************************************
|
||||
* Tuning Parameter
|
||||
**************************************/
|
||||
static const int LZ3HC_compressionLevel_default = 9;
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes
|
||||
**************************************/
|
||||
#include "lz4hc.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* Local Compiler Options
|
||||
**************************************/
|
||||
#if defined(__GNUC__)
|
||||
# pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#if defined (__clang__)
|
||||
# pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Common LZ3 definition
|
||||
**************************************/
|
||||
#define LZ3__COMMONDEFS_ONLY
|
||||
#include "lz4.h"
|
||||
|
||||
|
||||
/**************************************
|
||||
* Compiler Options
|
||||
**************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
# include <intrin.h>
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
|
||||
#else
|
||||
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* LZ3__GCC_VERSION is defined into lz3.h */
|
||||
#if (LZ3__GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__)
|
||||
# define expect(expr,value) (__builtin_expect ((expr),(value)) )
|
||||
#else
|
||||
# define expect(expr,value) (expr)
|
||||
#endif
|
||||
|
||||
#define likely(expr) expect((expr) != 0, 1)
|
||||
#define unlikely(expr) expect((expr) != 0, 0)
|
||||
|
||||
/**************************************
|
||||
* Memory routines
|
||||
**************************************/
|
||||
#include <stdlib.h> /* malloc, calloc, free */
|
||||
#define ALLOCATOR(n,s) calloc(n,s)
|
||||
#define FREEMEM free
|
||||
#include <string.h> /* memset, memcpy */
|
||||
#define MEM_INIT memset
|
||||
|
||||
|
||||
#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Reading and writing into memory
|
||||
**************************************/
|
||||
#define STEPSIZE sizeof(size_t)
|
||||
|
||||
static unsigned LZ3__64bits(void) { return sizeof(void*)==8; }
|
||||
|
||||
static unsigned LZ3__isLittleEndian(void)
|
||||
{
|
||||
const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
|
||||
static U16 LZ3__read16(const void* memPtr)
|
||||
{
|
||||
U16 val16;
|
||||
memcpy(&val16, memPtr, 2);
|
||||
return val16;
|
||||
}
|
||||
|
||||
static U16 LZ3__readLE16(const void* memPtr)
|
||||
{
|
||||
if (LZ3__isLittleEndian())
|
||||
{
|
||||
return LZ3__read16(memPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
const BYTE* p = (const BYTE*)memPtr;
|
||||
return (U16)((U16)p[0] + (p[1]<<8));
|
||||
}
|
||||
}
|
||||
|
||||
static void LZ3__writeLE16(void* memPtr, U16 value)
|
||||
{
|
||||
if (LZ3__isLittleEndian())
|
||||
{
|
||||
memcpy(memPtr, &value, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
BYTE* p = (BYTE*)memPtr;
|
||||
p[0] = (BYTE) value;
|
||||
p[1] = (BYTE)(value>>8);
|
||||
}
|
||||
}
|
||||
|
||||
static U32 LZ3__read32(const void* memPtr)
|
||||
{
|
||||
U32 val32;
|
||||
memcpy(&val32, memPtr, 4);
|
||||
return val32;
|
||||
}
|
||||
|
||||
static U64 LZ3__read64(const void* memPtr)
|
||||
{
|
||||
U64 val64;
|
||||
memcpy(&val64, memPtr, 8);
|
||||
return val64;
|
||||
}
|
||||
|
||||
static size_t LZ3__read_ARCH(const void* p)
|
||||
{
|
||||
if (LZ3__64bits())
|
||||
return (size_t)LZ3__read64(p);
|
||||
else
|
||||
return (size_t)LZ3__read32(p);
|
||||
}
|
||||
|
||||
|
||||
static void LZ3__copy4(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 4); }
|
||||
|
||||
static void LZ3__copy8(void* dstPtr, const void* srcPtr) { memcpy(dstPtr, srcPtr, 8); }
|
||||
|
||||
/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
|
||||
static void LZ3__wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
|
||||
{
|
||||
BYTE* d = (BYTE*)dstPtr;
|
||||
const BYTE* s = (const BYTE*)srcPtr;
|
||||
BYTE* e = (BYTE*)dstEnd;
|
||||
do { LZ3__copy8(d,s); d+=8; s+=8; } while (d<e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define MINMATCH 4
|
||||
|
||||
#define COPYLENGTH 8
|
||||
#define LASTLITERALS 5
|
||||
#define MFLIMIT (COPYLENGTH+MINMATCH)
|
||||
//static const int LZ3__minLength = (MFLIMIT+1);
|
||||
|
||||
#define KB *(1 <<10)
|
||||
#define MB *(1 <<20)
|
||||
#define GB *(1U<<30)
|
||||
|
||||
#define MAXD_LOG 16
|
||||
#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
|
||||
|
||||
#define ML_BITS 4
|
||||
#define ML_MASK ((1U<<ML_BITS)-1)
|
||||
#define RUN_BITS (8-ML_BITS)
|
||||
#define RUN_MASK ((1U<<RUN_BITS)-1)
|
||||
|
||||
#define LZ3__STATIC_ASSERT(c) { enum { LZ3__static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
#define LZ3__COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ3__MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
int LZ3__compressBound(int inputSize);
|
||||
/**************************************
|
||||
* Common functions
|
||||
**************************************/
|
||||
static unsigned LZ3__NbCommonBytes ( size_t val)
|
||||
{
|
||||
if (LZ3__isLittleEndian())
|
||||
{
|
||||
if (LZ3__64bits())
|
||||
{
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanForward64( &r, (U64)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LZ3__GCC_VERSION >= 304)) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
return (__builtin_ctzll((U64)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
|
||||
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
|
||||
# endif
|
||||
}
|
||||
else /* 32 bits */
|
||||
{
|
||||
# if defined(_MSC_VER) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
unsigned long r;
|
||||
_BitScanForward( &r, (U32)val );
|
||||
return (int)(r>>3);
|
||||
# elif (defined(__clang__) || (LZ3__GCC_VERSION >= 304)) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
return (__builtin_ctz((U32)val) >> 3);
|
||||
# else
|
||||
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
|
||||
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else /* Big Endian CPU */
|
||||
{
|
||||
if (LZ3__64bits())
|
||||
{
|
||||
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse64( &r, val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LZ3__GCC_VERSION >= 304)) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
return (__builtin_clzll((U64)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
|
||||
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
}
|
||||
else /* 32 bits */
|
||||
{
|
||||
# if defined(_MSC_VER) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
unsigned long r = 0;
|
||||
_BitScanReverse( &r, (unsigned long)val );
|
||||
return (unsigned)(r>>3);
|
||||
# elif (defined(__clang__) || (LZ3__GCC_VERSION >= 304)) && !defined(LZ3__FORCE_SW_BITCOUNT)
|
||||
return (__builtin_clz((U32)val) >> 3);
|
||||
# else
|
||||
unsigned r;
|
||||
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
|
||||
r += (!val);
|
||||
return r;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned LZ3__count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
|
||||
{
|
||||
const BYTE* const pStart = pIn;
|
||||
|
||||
while (likely(pIn<pInLimit-(STEPSIZE-1)))
|
||||
{
|
||||
size_t diff = LZ3__read_ARCH(pMatch) ^ LZ3__read_ARCH(pIn);
|
||||
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
|
||||
pIn += LZ3__NbCommonBytes(diff);
|
||||
return (unsigned)(pIn - pStart);
|
||||
}
|
||||
|
||||
if (LZ3__64bits()) if ((pIn<(pInLimit-3)) && (LZ3__read32(pMatch) == LZ3__read32(pIn))) { pIn+=4; pMatch+=4; }
|
||||
if ((pIn<(pInLimit-1)) && (LZ3__read16(pMatch) == LZ3__read16(pIn))) { pIn+=2; pMatch+=2; }
|
||||
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
|
||||
return (unsigned)(pIn - pStart);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Local Constants
|
||||
**************************************/
|
||||
#define DICTIONARY_LOGSIZE 16
|
||||
#define MAXD (1<<DICTIONARY_LOGSIZE)
|
||||
#define MAXD_MASK (MAXD - 1)
|
||||
|
||||
#define HASH_LOG (DICTIONARY_LOGSIZE-1)
|
||||
#define HASHTABLESIZE (1 << HASH_LOG)
|
||||
#define HASH_MASK (HASHTABLESIZE - 1)
|
||||
|
||||
#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH)
|
||||
|
||||
static const int g_maxCompressionLevel = 16;
|
||||
|
||||
|
||||
/**************************************
|
||||
* Local Types
|
||||
**************************************/
|
||||
typedef struct
|
||||
{
|
||||
U32 hashTable[HASHTABLESIZE];
|
||||
U16 chainTable[MAXD];
|
||||
const BYTE* end; /* next block here to continue on current prefix */
|
||||
const BYTE* base; /* All index relative to this position */
|
||||
const BYTE* dictBase; /* alternate base for extDict */
|
||||
BYTE* inputBuffer; /* deprecated */
|
||||
U32 dictLimit; /* below that point, need extDict */
|
||||
U32 lowLimit; /* below that point, no more dict */
|
||||
U32 nextToUpdate; /* index from which to continue dictionary update */
|
||||
U32 compressionLevel;
|
||||
} LZ3HC_Data_Structure;
|
||||
|
||||
|
||||
/**************************************
|
||||
* Local Macros
|
||||
**************************************/
|
||||
#define HASH_FUNCTION(i) (((i) * 2654435761U) >> ((MINMATCH*8)-HASH_LOG))
|
||||
//#define DELTANEXTU16(p) chainTable[(p) & MAXD_MASK] /* flexible, MAXD dependent */
|
||||
#define DELTANEXTU16(p) chainTable[(U16)(p)] /* faster */
|
||||
|
||||
static U32 LZ3HC_hashPtr(const void* ptr) { return HASH_FUNCTION(LZ3__read32(ptr)); }
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* HC Compression
|
||||
**************************************/
|
||||
static void LZ3HC_init (LZ3HC_Data_Structure* hc4, const BYTE* start)
|
||||
{
|
||||
MEM_INIT((void*)hc4->hashTable, 0, sizeof(hc4->hashTable));
|
||||
MEM_INIT(hc4->chainTable, 0xFF, sizeof(hc4->chainTable));
|
||||
hc4->nextToUpdate = 64 KB;
|
||||
hc4->base = start - 64 KB;
|
||||
hc4->end = start;
|
||||
hc4->dictBase = start - 64 KB;
|
||||
hc4->dictLimit = 64 KB;
|
||||
hc4->lowLimit = 64 KB;
|
||||
}
|
||||
|
||||
|
||||
/* Update chains up to ip (excluded) */
|
||||
FORCE_INLINE void LZ3HC_Insert (LZ3HC_Data_Structure* hc4, const BYTE* ip)
|
||||
{
|
||||
U16* chainTable = hc4->chainTable;
|
||||
U32* HashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
const U32 target = (U32)(ip - base);
|
||||
U32 idx = hc4->nextToUpdate;
|
||||
|
||||
while(idx < target)
|
||||
{
|
||||
U32 h = LZ3HC_hashPtr(base+idx);
|
||||
size_t delta = idx - HashTable[h];
|
||||
if (delta>MAX_DISTANCE) delta = MAX_DISTANCE;
|
||||
DELTANEXTU16(idx) = (U16)delta;
|
||||
HashTable[h] = idx;
|
||||
idx++;
|
||||
}
|
||||
|
||||
hc4->nextToUpdate = target;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LZ3HC_InsertAndFindBestMatch (LZ3HC_Data_Structure* hc4, /* Index table will be updated */
|
||||
const BYTE* ip, const BYTE* const iLimit,
|
||||
const BYTE** matchpos,
|
||||
const int maxNbAttempts)
|
||||
{
|
||||
U16* const chainTable = hc4->chainTable;
|
||||
U32* const HashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
const BYTE* const dictBase = hc4->dictBase;
|
||||
const U32 dictLimit = hc4->dictLimit;
|
||||
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
|
||||
U32 matchIndex;
|
||||
const BYTE* match;
|
||||
int nbAttempts=maxNbAttempts;
|
||||
size_t ml=0;
|
||||
|
||||
/* HC4 match finder */
|
||||
LZ3HC_Insert(hc4, ip);
|
||||
matchIndex = HashTable[LZ3HC_hashPtr(ip)];
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts))
|
||||
{
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit)
|
||||
{
|
||||
match = base + matchIndex;
|
||||
if (*(match+ml) == *(ip+ml)
|
||||
&& (LZ3__read32(match) == LZ3__read32(ip)))
|
||||
{
|
||||
size_t mlt = LZ3__count(ip+MINMATCH, match+MINMATCH, iLimit) + MINMATCH;
|
||||
if (mlt > ml) { ml = mlt; *matchpos = match; }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
match = dictBase + matchIndex;
|
||||
if (LZ3__read32(match) == LZ3__read32(ip))
|
||||
{
|
||||
size_t mlt;
|
||||
const BYTE* vLimit = ip + (dictLimit - matchIndex);
|
||||
if (vLimit > iLimit) vLimit = iLimit;
|
||||
mlt = LZ3__count(ip+MINMATCH, match+MINMATCH, vLimit) + MINMATCH;
|
||||
if ((ip+mlt == vLimit) && (vLimit < iLimit))
|
||||
mlt += LZ3__count(ip+mlt, base+dictLimit, iLimit);
|
||||
if (mlt > ml) { ml = mlt; *matchpos = base + matchIndex; } /* virtual matchpos */
|
||||
}
|
||||
}
|
||||
matchIndex -= DELTANEXTU16(matchIndex);
|
||||
}
|
||||
|
||||
return (int)ml;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE int LZ3HC_InsertAndGetWiderMatch (
|
||||
LZ3HC_Data_Structure* hc4,
|
||||
const BYTE* const ip,
|
||||
const BYTE* const iLowLimit,
|
||||
const BYTE* const iHighLimit,
|
||||
int longest,
|
||||
const BYTE** matchpos,
|
||||
const BYTE** startpos,
|
||||
const int maxNbAttempts)
|
||||
{
|
||||
U16* const chainTable = hc4->chainTable;
|
||||
U32* const HashTable = hc4->hashTable;
|
||||
const BYTE* const base = hc4->base;
|
||||
const U32 dictLimit = hc4->dictLimit;
|
||||
const BYTE* const lowPrefixPtr = base + dictLimit;
|
||||
const U32 lowLimit = (hc4->lowLimit + 64 KB > (U32)(ip-base)) ? hc4->lowLimit : (U32)(ip - base) - (64 KB - 1);
|
||||
const BYTE* const dictBase = hc4->dictBase;
|
||||
U32 matchIndex;
|
||||
int nbAttempts = maxNbAttempts;
|
||||
int delta = (int)(ip-iLowLimit);
|
||||
|
||||
|
||||
/* First Match */
|
||||
LZ3HC_Insert(hc4, ip);
|
||||
matchIndex = HashTable[LZ3HC_hashPtr(ip)];
|
||||
|
||||
while ((matchIndex>=lowLimit) && (nbAttempts))
|
||||
{
|
||||
nbAttempts--;
|
||||
if (matchIndex >= dictLimit)
|
||||
{
|
||||
const BYTE* matchPtr = base + matchIndex;
|
||||
if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
|
||||
if (LZ3__read32(matchPtr) == LZ3__read32(ip))
|
||||
{
|
||||
int mlt = MINMATCH + LZ3__count(ip+MINMATCH, matchPtr+MINMATCH, iHighLimit);
|
||||
int back = 0;
|
||||
|
||||
while ((ip+back>iLowLimit)
|
||||
&& (matchPtr+back > lowPrefixPtr)
|
||||
&& (ip[back-1] == matchPtr[back-1]))
|
||||
back--;
|
||||
|
||||
mlt -= back;
|
||||
|
||||
if (mlt > longest)
|
||||
{
|
||||
longest = (int)mlt;
|
||||
*matchpos = matchPtr+back;
|
||||
*startpos = ip+back;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const BYTE* matchPtr = dictBase + matchIndex;
|
||||
if (LZ3__read32(matchPtr) == LZ3__read32(ip))
|
||||
{
|
||||
size_t mlt;
|
||||
int back=0;
|
||||
const BYTE* vLimit = ip + (dictLimit - matchIndex);
|
||||
if (vLimit > iHighLimit) vLimit = iHighLimit;
|
||||
mlt = LZ3__count(ip+MINMATCH, matchPtr+MINMATCH, vLimit) + MINMATCH;
|
||||
if ((ip+mlt == vLimit) && (vLimit < iHighLimit))
|
||||
mlt += LZ3__count(ip+mlt, base+dictLimit, iHighLimit);
|
||||
while ((ip+back > iLowLimit) && (matchIndex+back > lowLimit) && (ip[back-1] == matchPtr[back-1])) back--;
|
||||
mlt -= back;
|
||||
if ((int)mlt > longest) { longest = (int)mlt; *matchpos = base + matchIndex + back; *startpos = ip+back; }
|
||||
}
|
||||
}
|
||||
matchIndex -= DELTANEXTU16(matchIndex);
|
||||
}
|
||||
|
||||
return longest;
|
||||
}
|
||||
|
||||
|
||||
typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
|
||||
|
||||
#define LZ3HC_DEBUG 0
|
||||
#if LZ3HC_DEBUG
|
||||
static unsigned debug = 0;
|
||||
#endif
|
||||
|
||||
FORCE_INLINE int LZ3HC_encodeSequence (
|
||||
const BYTE** ip,
|
||||
BYTE** op,
|
||||
const BYTE** anchor,
|
||||
int matchLength,
|
||||
const BYTE* const match,
|
||||
limitedOutput_directive limitedOutputBuffer,
|
||||
BYTE* oend)
|
||||
{
|
||||
int length;
|
||||
BYTE* token;
|
||||
|
||||
#if LZ3HC_DEBUG
|
||||
if (debug) printf("literal : %u -- match : %u -- offset : %u\n", (U32)(*ip - *anchor), (U32)matchLength, (U32)(*ip-match));
|
||||
#endif
|
||||
|
||||
/* Encode Literal length */
|
||||
length = (int)(*ip - *anchor);
|
||||
token = (*op)++;
|
||||
if ((limitedOutputBuffer) && ((*op + (length>>8) + length + (2 + 1 + LASTLITERALS)) > oend)) return 1; /* Check output limit */
|
||||
if (length>=(int)RUN_MASK) { int len; *token=(RUN_MASK<<ML_BITS); len = length-RUN_MASK; for(; len > 254 ; len-=255) *(*op)++ = 255; *(*op)++ = (BYTE)len; }
|
||||
else *token = (BYTE)(length<<ML_BITS);
|
||||
|
||||
/* Copy Literals */
|
||||
LZ3__wildCopy(*op, *anchor, (*op) + length);
|
||||
*op += length;
|
||||
|
||||
/* Encode Offset */
|
||||
LZ3__writeLE16(*op, (U16)(*ip-match)); *op += 2;
|
||||
|
||||
/* Encode MatchLength */
|
||||
length = (int)(matchLength-MINMATCH);
|
||||
if ((limitedOutputBuffer) && (*op + (length>>8) + (1 + LASTLITERALS) > oend)) return 1; /* Check output limit */
|
||||
if (length>=(int)ML_MASK) { *token+=ML_MASK; length-=ML_MASK; for(; length > 509 ; length-=510) { *(*op)++ = 255; *(*op)++ = 255; } if (length > 254) { length-=255; *(*op)++ = 255; } *(*op)++ = (BYTE)length; }
|
||||
else *token += (BYTE)(length);
|
||||
|
||||
/* Prepare next loop */
|
||||
*ip += matchLength;
|
||||
*anchor = *ip;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int LZ3HC_compress_generic (
|
||||
void* ctxvoid,
|
||||
const char* source,
|
||||
char* dest,
|
||||
int inputSize,
|
||||
int maxOutputSize,
|
||||
int compressionLevel,
|
||||
limitedOutput_directive limit
|
||||
)
|
||||
{
|
||||
LZ3HC_Data_Structure* ctx = (LZ3HC_Data_Structure*) ctxvoid;
|
||||
const BYTE* ip = (const BYTE*) source;
|
||||
const BYTE* anchor = ip;
|
||||
const BYTE* const iend = ip + inputSize;
|
||||
const BYTE* const mflimit = iend - MFLIMIT;
|
||||
const BYTE* const matchlimit = (iend - LASTLITERALS);
|
||||
|
||||
BYTE* op = (BYTE*) dest;
|
||||
BYTE* const oend = op + maxOutputSize;
|
||||
|
||||
unsigned maxNbAttempts;
|
||||
int ml, ml2, ml3, ml0;
|
||||
const BYTE* ref=NULL;
|
||||
const BYTE* start2=NULL;
|
||||
const BYTE* ref2=NULL;
|
||||
const BYTE* start3=NULL;
|
||||
const BYTE* ref3=NULL;
|
||||
const BYTE* start0;
|
||||
const BYTE* ref0;
|
||||
|
||||
|
||||
/* init */
|
||||
if (compressionLevel > g_maxCompressionLevel) compressionLevel = g_maxCompressionLevel;
|
||||
if (compressionLevel < 1) compressionLevel = LZ3HC_compressionLevel_default;
|
||||
maxNbAttempts = 1 << (compressionLevel-1);
|
||||
ctx->end += inputSize;
|
||||
|
||||
ip++;
|
||||
|
||||
/* Main Loop */
|
||||
while (ip < mflimit)
|
||||
{
|
||||
ml = LZ3HC_InsertAndFindBestMatch (ctx, ip, matchlimit, (&ref), maxNbAttempts);
|
||||
if (!ml) { ip++; continue; }
|
||||
|
||||
/* saved, in case we would skip too much */
|
||||
start0 = ip;
|
||||
ref0 = ref;
|
||||
ml0 = ml;
|
||||
|
||||
_Search2:
|
||||
if (ip+ml < mflimit)
|
||||
ml2 = LZ3HC_InsertAndGetWiderMatch(ctx, ip + ml - 2, ip + 1, matchlimit, ml, &ref2, &start2, maxNbAttempts);
|
||||
else ml2 = ml;
|
||||
|
||||
if (ml2 == ml) /* No better match */
|
||||
{
|
||||
if (LZ3HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start0 < ip)
|
||||
{
|
||||
if (start2 < ip + ml0) /* empirical */
|
||||
{
|
||||
ip = start0;
|
||||
ref = ref0;
|
||||
ml = ml0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Here, start0==ip */
|
||||
if ((start2 - ip) < 3) /* First Match too small : removed */
|
||||
{
|
||||
ml = ml2;
|
||||
ip = start2;
|
||||
ref =ref2;
|
||||
goto _Search2;
|
||||
}
|
||||
|
||||
_Search3:
|
||||
/*
|
||||
* Currently we have :
|
||||
* ml2 > ml1, and
|
||||
* ip1+3 <= ip2 (usually < ip1+ml1)
|
||||
*/
|
||||
if ((start2 - ip) < OPTIMAL_ML)
|
||||
{
|
||||
int correction;
|
||||
int new_ml = ml;
|
||||
if (new_ml > OPTIMAL_ML) new_ml = OPTIMAL_ML;
|
||||
if (ip+new_ml > start2 + ml2 - MINMATCH) new_ml = (int)(start2 - ip) + ml2 - MINMATCH;
|
||||
correction = new_ml - (int)(start2 - ip);
|
||||
if (correction > 0)
|
||||
{
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
}
|
||||
}
|
||||
/* Now, we have start2 = ip+new_ml, with new_ml = min(ml, OPTIMAL_ML=18) */
|
||||
|
||||
if (start2 + ml2 < mflimit)
|
||||
ml3 = LZ3HC_InsertAndGetWiderMatch(ctx, start2 + ml2 - 3, start2, matchlimit, ml2, &ref3, &start3, maxNbAttempts);
|
||||
else ml3 = ml2;
|
||||
|
||||
if (ml3 == ml2) /* No better match : 2 sequences to encode */
|
||||
{
|
||||
/* ip & ref are known; Now for ml */
|
||||
if (start2 < ip+ml) ml = (int)(start2 - ip);
|
||||
/* Now, encode 2 sequences */
|
||||
if (LZ3HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
ip = start2;
|
||||
if (LZ3HC_encodeSequence(&ip, &op, &anchor, ml2, ref2, limit, oend)) return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (start3 < ip+ml+3) /* Not enough space for match 2 : remove it */
|
||||
{
|
||||
if (start3 >= (ip+ml)) /* can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1 */
|
||||
{
|
||||
if (start2 < ip+ml)
|
||||
{
|
||||
int correction = (int)(ip+ml - start2);
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
if (ml2 < MINMATCH)
|
||||
{
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
}
|
||||
}
|
||||
|
||||
if (LZ3HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
ip = start3;
|
||||
ref = ref3;
|
||||
ml = ml3;
|
||||
|
||||
start0 = start2;
|
||||
ref0 = ref2;
|
||||
ml0 = ml2;
|
||||
goto _Search2;
|
||||
}
|
||||
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
goto _Search3;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, now we have 3 ascending matches; let's write at least the first one
|
||||
* ip & ref are known; Now for ml
|
||||
*/
|
||||
if (start2 < ip+ml)
|
||||
{
|
||||
if ((start2 - ip) < (int)ML_MASK)
|
||||
{
|
||||
int correction;
|
||||
if (ml > OPTIMAL_ML) ml = OPTIMAL_ML;
|
||||
if (ip + ml > start2 + ml2 - MINMATCH) ml = (int)(start2 - ip) + ml2 - MINMATCH;
|
||||
correction = ml - (int)(start2 - ip);
|
||||
if (correction > 0)
|
||||
{
|
||||
start2 += correction;
|
||||
ref2 += correction;
|
||||
ml2 -= correction;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ml = (int)(start2 - ip);
|
||||
}
|
||||
}
|
||||
if (LZ3HC_encodeSequence(&ip, &op, &anchor, ml, ref, limit, oend)) return 0;
|
||||
|
||||
ip = start2;
|
||||
ref = ref2;
|
||||
ml = ml2;
|
||||
|
||||
start2 = start3;
|
||||
ref2 = ref3;
|
||||
ml2 = ml3;
|
||||
|
||||
goto _Search3;
|
||||
}
|
||||
|
||||
/* Encode Last Literals */
|
||||
{
|
||||
int lastRun = (int)(iend - anchor);
|
||||
if ((limit) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */
|
||||
if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun > 254 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; }
|
||||
else *op++ = (BYTE)(lastRun<<ML_BITS);
|
||||
memcpy(op, anchor, iend - anchor);
|
||||
op += iend-anchor;
|
||||
}
|
||||
|
||||
/* End */
|
||||
return (int) (((char*)op)-dest);
|
||||
}
|
||||
|
||||
|
||||
int LZ3__sizeofStateHC(void) { return sizeof(LZ3HC_Data_Structure); }
|
||||
|
||||
int LZ3__compress_HC_extStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
if (((size_t)(state)&(sizeof(void*)-1)) != 0) return 0; /* Error : state is not aligned for pointers (32 or 64 bits) */
|
||||
LZ3HC_init ((LZ3HC_Data_Structure*)state, (const BYTE*)src);
|
||||
if (maxDstSize < LZ3__compressBound(srcSize))
|
||||
return LZ3HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, limitedOutput);
|
||||
else
|
||||
return LZ3HC_compress_generic (state, src, dst, srcSize, maxDstSize, compressionLevel, noLimit);
|
||||
}
|
||||
|
||||
int LZ3__compress_HC(const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel)
|
||||
{
|
||||
LZ3HC_Data_Structure state;
|
||||
return LZ3__compress_HC_extStateHC(&state, src, dst, srcSize, maxDstSize, compressionLevel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Streaming Functions
|
||||
**************************************/
|
||||
/* allocation */
|
||||
LZ3__streamHC_t* LZ3__createStreamHC(void) { return (LZ3__streamHC_t*)malloc(sizeof(LZ3__streamHC_t)); }
|
||||
int LZ3__freeStreamHC (LZ3__streamHC_t* LZ3__streamHCPtr) { free(LZ3__streamHCPtr); return 0; }
|
||||
|
||||
|
||||
/* initialization */
|
||||
void LZ3__resetStreamHC (LZ3__streamHC_t* LZ3__streamHCPtr, int compressionLevel)
|
||||
{
|
||||
LZ3__STATIC_ASSERT(sizeof(LZ3HC_Data_Structure) <= sizeof(LZ3__streamHC_t)); /* if compilation fails here, LZ3__STREAMHCSIZE must be increased */
|
||||
((LZ3HC_Data_Structure*)LZ3__streamHCPtr)->base = NULL;
|
||||
((LZ3HC_Data_Structure*)LZ3__streamHCPtr)->compressionLevel = (unsigned)compressionLevel;
|
||||
}
|
||||
|
||||
int LZ3__loadDictHC (LZ3__streamHC_t* LZ3__streamHCPtr, const char* dictionary, int dictSize)
|
||||
{
|
||||
LZ3HC_Data_Structure* ctxPtr = (LZ3HC_Data_Structure*) LZ3__streamHCPtr;
|
||||
if (dictSize > 64 KB)
|
||||
{
|
||||
dictionary += dictSize - 64 KB;
|
||||
dictSize = 64 KB;
|
||||
}
|
||||
LZ3HC_init (ctxPtr, (const BYTE*)dictionary);
|
||||
if (dictSize >= 4) LZ3HC_Insert (ctxPtr, (const BYTE*)dictionary +(dictSize-3));
|
||||
ctxPtr->end = (const BYTE*)dictionary + dictSize;
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
/* compression */
|
||||
|
||||
static void LZ3HC_setExternalDict(LZ3HC_Data_Structure* ctxPtr, const BYTE* newBlock)
|
||||
{
|
||||
if (ctxPtr->end >= ctxPtr->base + 4)
|
||||
LZ3HC_Insert (ctxPtr, ctxPtr->end-3); /* Referencing remaining dictionary content */
|
||||
/* Only one memory segment for extDict, so any previous extDict is lost at this stage */
|
||||
ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
ctxPtr->dictLimit = (U32)(ctxPtr->end - ctxPtr->base);
|
||||
ctxPtr->dictBase = ctxPtr->base;
|
||||
ctxPtr->base = newBlock - ctxPtr->dictLimit;
|
||||
ctxPtr->end = newBlock;
|
||||
ctxPtr->nextToUpdate = ctxPtr->dictLimit; /* match referencing will resume from there */
|
||||
}
|
||||
|
||||
static int LZ3__compressHC_continue_generic (LZ3HC_Data_Structure* ctxPtr,
|
||||
const char* source, char* dest,
|
||||
int inputSize, int maxOutputSize, limitedOutput_directive limit)
|
||||
{
|
||||
/* auto-init if forgotten */
|
||||
if (ctxPtr->base == NULL)
|
||||
LZ3HC_init (ctxPtr, (const BYTE*) source);
|
||||
|
||||
/* Check overflow */
|
||||
if ((size_t)(ctxPtr->end - ctxPtr->base) > 2 GB)
|
||||
{
|
||||
size_t dictSize = (size_t)(ctxPtr->end - ctxPtr->base) - ctxPtr->dictLimit;
|
||||
if (dictSize > 64 KB) dictSize = 64 KB;
|
||||
|
||||
LZ3__loadDictHC((LZ3__streamHC_t*)ctxPtr, (const char*)(ctxPtr->end) - dictSize, (int)dictSize);
|
||||
}
|
||||
|
||||
/* Check if blocks follow each other */
|
||||
if ((const BYTE*)source != ctxPtr->end)
|
||||
LZ3HC_setExternalDict(ctxPtr, (const BYTE*)source);
|
||||
|
||||
/* Check overlapping input/dictionary space */
|
||||
{
|
||||
const BYTE* sourceEnd = (const BYTE*) source + inputSize;
|
||||
const BYTE* dictBegin = ctxPtr->dictBase + ctxPtr->lowLimit;
|
||||
const BYTE* dictEnd = ctxPtr->dictBase + ctxPtr->dictLimit;
|
||||
if ((sourceEnd > dictBegin) && ((const BYTE*)source < dictEnd))
|
||||
{
|
||||
if (sourceEnd > dictEnd) sourceEnd = dictEnd;
|
||||
ctxPtr->lowLimit = (U32)(sourceEnd - ctxPtr->dictBase);
|
||||
if (ctxPtr->dictLimit - ctxPtr->lowLimit < 4) ctxPtr->lowLimit = ctxPtr->dictLimit;
|
||||
}
|
||||
}
|
||||
|
||||
return LZ3HC_compress_generic (ctxPtr, source, dest, inputSize, maxOutputSize, ctxPtr->compressionLevel, limit);
|
||||
}
|
||||
|
||||
int LZ3__compress_HC_continue (LZ3__streamHC_t* LZ3__streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize)
|
||||
{
|
||||
if (maxOutputSize < LZ3__compressBound(inputSize))
|
||||
return LZ3__compressHC_continue_generic ((LZ3HC_Data_Structure*)LZ3__streamHCPtr, source, dest, inputSize, maxOutputSize, limitedOutput);
|
||||
else
|
||||
return LZ3__compressHC_continue_generic ((LZ3HC_Data_Structure*)LZ3__streamHCPtr, source, dest, inputSize, maxOutputSize, noLimit);
|
||||
}
|
||||
|
||||
|
||||
/* dictionary saving */
|
||||
|
||||
int LZ3__saveDictHC (LZ3__streamHC_t* LZ3__streamHCPtr, char* safeBuffer, int dictSize)
|
||||
{
|
||||
LZ3HC_Data_Structure* streamPtr = (LZ3HC_Data_Structure*)LZ3__streamHCPtr;
|
||||
int prefixSize = (int)(streamPtr->end - (streamPtr->base + streamPtr->dictLimit));
|
||||
if (dictSize > 64 KB) dictSize = 64 KB;
|
||||
if (dictSize < 4) dictSize = 0;
|
||||
if (dictSize > prefixSize) dictSize = prefixSize;
|
||||
memmove(safeBuffer, streamPtr->end - dictSize, dictSize);
|
||||
{
|
||||
U32 endIndex = (U32)(streamPtr->end - streamPtr->base);
|
||||
streamPtr->end = (const BYTE*)safeBuffer + dictSize;
|
||||
streamPtr->base = streamPtr->end - endIndex;
|
||||
streamPtr->dictLimit = endIndex - dictSize;
|
||||
streamPtr->lowLimit = endIndex - dictSize;
|
||||
if (streamPtr->nextToUpdate < streamPtr->dictLimit) streamPtr->nextToUpdate = streamPtr->dictLimit;
|
||||
}
|
||||
return dictSize;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Deprecated Functions
|
||||
***********************************/
|
||||
/* Deprecated compression functions */
|
||||
/* These functions are planned to start generate warnings by r131 approximately */
|
||||
int LZ3__compressHC(const char* src, char* dst, int srcSize) { return LZ3__compress_HC (src, dst, srcSize, LZ3__compressBound(srcSize), 0); }
|
||||
int LZ3__compressHC_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize) { return LZ3__compress_HC(src, dst, srcSize, maxDstSize, 0); }
|
||||
int LZ3__compressHC2(const char* src, char* dst, int srcSize, int cLevel) { return LZ3__compress_HC (src, dst, srcSize, LZ3__compressBound(srcSize), cLevel); }
|
||||
int LZ3__compressHC2_limitedOutput(const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ3__compress_HC(src, dst, srcSize, maxDstSize, cLevel); }
|
||||
int LZ3__compressHC_withStateHC (void* state, const char* src, char* dst, int srcSize) { return LZ3__compress_HC_extStateHC (state, src, dst, srcSize, LZ3__compressBound(srcSize), 0); }
|
||||
int LZ3__compressHC_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ3__compress_HC_extStateHC (state, src, dst, srcSize, maxDstSize, 0); }
|
||||
int LZ3__compressHC2_withStateHC (void* state, const char* src, char* dst, int srcSize, int cLevel) { return LZ3__compress_HC_extStateHC(state, src, dst, srcSize, LZ3__compressBound(srcSize), cLevel); }
|
||||
int LZ3__compressHC2_limitedOutput_withStateHC (void* state, const char* src, char* dst, int srcSize, int maxDstSize, int cLevel) { return LZ3__compress_HC_extStateHC(state, src, dst, srcSize, maxDstSize, cLevel); }
|
||||
int LZ3__compressHC_continue (LZ3__streamHC_t* ctx, const char* src, char* dst, int srcSize) { return LZ3__compress_HC_continue (ctx, src, dst, srcSize, LZ3__compressBound(srcSize)); }
|
||||
int LZ3__compressHC_limitedOutput_continue (LZ3__streamHC_t* ctx, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ3__compress_HC_continue (ctx, src, dst, srcSize, maxDstSize); }
|
||||
|
||||
|
||||
/* Deprecated streaming functions */
|
||||
/* These functions currently generate deprecation warnings */
|
||||
int LZ3__sizeofStreamStateHC(void) { return LZ3__STREAMHCSIZE; }
|
||||
|
||||
int LZ3__resetStreamStateHC(void* state, char* inputBuffer)
|
||||
{
|
||||
if ((((size_t)state) & (sizeof(void*)-1)) != 0) return 1; /* Error : pointer is not aligned for pointer (32 or 64 bits) */
|
||||
LZ3HC_init((LZ3HC_Data_Structure*)state, (const BYTE*)inputBuffer);
|
||||
((LZ3HC_Data_Structure*)state)->inputBuffer = (BYTE*)inputBuffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* LZ3__createHC (char* inputBuffer)
|
||||
{
|
||||
void* hc4 = ALLOCATOR(1, sizeof(LZ3HC_Data_Structure));
|
||||
if (hc4 == NULL) return NULL; /* not enough memory */
|
||||
LZ3HC_init ((LZ3HC_Data_Structure*)hc4, (const BYTE*)inputBuffer);
|
||||
((LZ3HC_Data_Structure*)hc4)->inputBuffer = (BYTE*)inputBuffer;
|
||||
return hc4;
|
||||
}
|
||||
|
||||
int LZ3__freeHC (void* LZ3HC_Data)
|
||||
{
|
||||
FREEMEM(LZ3HC_Data);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int LZ3__compressHC2_continue (void* LZ3HC_Data, const char* source, char* dest, int inputSize, int compressionLevel)
|
||||
{
|
||||
return LZ3HC_compress_generic (LZ3HC_Data, source, dest, inputSize, 0, compressionLevel, noLimit);
|
||||
}
|
||||
|
||||
int LZ3__compressHC2_limitedOutput_continue (void* LZ3HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel)
|
||||
{
|
||||
return LZ3HC_compress_generic (LZ3HC_Data, source, dest, inputSize, maxOutputSize, compressionLevel, limitedOutput);
|
||||
}
|
||||
|
||||
char* LZ3__slideInputBufferHC(void* LZ3HC_Data)
|
||||
{
|
||||
LZ3HC_Data_Structure* hc4 = (LZ3HC_Data_Structure*)LZ3HC_Data;
|
||||
int dictSize = LZ3__saveDictHC((LZ3__streamHC_t*)LZ3HC_Data, (char*)(hc4->inputBuffer), 64 KB);
|
||||
return (char*)(hc4->inputBuffer + dictSize);
|
||||
}
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.cpp.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.cpp.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7897d562f1859394396e7338ace48ff5
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
189
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.h
Normal file
189
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
LZ3 HC - High Compression Mode of LZ3
|
||||
Header File
|
||||
Copyright (C) 2011-2015, Yann Collet.
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ3 source repository : https://github.com/Cyan4973/lz3
|
||||
- LZ3 public forum : https://groups.google.com/forum/#!forum/lz3c
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************
|
||||
* Includes
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**************************************
|
||||
* Block Compression
|
||||
**************************************/
|
||||
int LZ3__compress_HC (const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
/*
|
||||
LZ3__compress_HC :
|
||||
Destination buffer 'dst' must be already allocated.
|
||||
Compression completion is guaranteed if 'dst' buffer is sized to handle worst circumstances (data not compressible)
|
||||
Worst size evaluation is provided by function LZ3__compressBound() (see "lz3.h")
|
||||
srcSize : Max supported value is LZ3__MAX_INPUT_SIZE (see "lz3.h")
|
||||
compressionLevel : Recommended values are between 4 and 9, although any value between 0 and 16 will work.
|
||||
0 means "use default value" (see lz3hc.c).
|
||||
Values >16 behave the same as 16.
|
||||
return : the number of bytes written into buffer 'dst'
|
||||
or 0 if compression fails.
|
||||
*/
|
||||
|
||||
|
||||
/* Note :
|
||||
Decompression functions are provided within LZ3 source code (see "lz3.h") (BSD license)
|
||||
*/
|
||||
|
||||
|
||||
int LZ3__sizeofStateHC(void);
|
||||
int LZ3__compress_HC_extStateHC(void* state, const char* src, char* dst, int srcSize, int maxDstSize, int compressionLevel);
|
||||
/*
|
||||
LZ3__compress_HC_extStateHC() :
|
||||
Use this function if you prefer to manually allocate memory for compression tables.
|
||||
To know how much memory must be allocated for the compression tables, use :
|
||||
int LZ3__sizeofStateHC();
|
||||
|
||||
Allocated memory must be aligned on 8-bytes boundaries (which a normal malloc() will do properly).
|
||||
|
||||
The allocated memory can then be provided to the compression functions using 'void* state' parameter.
|
||||
LZ3__compress_HC_extStateHC() is equivalent to previously described function.
|
||||
It just uses externally allocated memory for stateHC.
|
||||
*/
|
||||
|
||||
|
||||
/**************************************
|
||||
* Streaming Compression
|
||||
**************************************/
|
||||
#define LZ3__STREAMHCSIZE 262192
|
||||
#define LZ3__STREAMHCSIZE_SIZET (LZ3__STREAMHCSIZE / sizeof(size_t))
|
||||
typedef struct { size_t table[LZ3__STREAMHCSIZE_SIZET]; } LZ3__streamHC_t;
|
||||
/*
|
||||
LZ3__streamHC_t
|
||||
This structure allows static allocation of LZ3 HC streaming state.
|
||||
State must then be initialized using LZ3__resetStreamHC() before first use.
|
||||
|
||||
Static allocation should only be used in combination with static linking.
|
||||
If you want to use LZ3 as a DLL, please use construction functions below, which are future-proof.
|
||||
*/
|
||||
|
||||
|
||||
LZ3__streamHC_t* LZ3__createStreamHC(void);
|
||||
int LZ3__freeStreamHC (LZ3__streamHC_t* streamHCPtr);
|
||||
/*
|
||||
These functions create and release memory for LZ3 HC streaming state.
|
||||
Newly created states are already initialized.
|
||||
Existing state space can be re-used anytime using LZ3__resetStreamHC().
|
||||
If you use LZ3 as a DLL, use these functions instead of static structure allocation,
|
||||
to avoid size mismatch between different versions.
|
||||
*/
|
||||
|
||||
void LZ3__resetStreamHC (LZ3__streamHC_t* streamHCPtr, int compressionLevel);
|
||||
int LZ3__loadDictHC (LZ3__streamHC_t* streamHCPtr, const char* dictionary, int dictSize);
|
||||
|
||||
int LZ3__compress_HC_continue (LZ3__streamHC_t* streamHCPtr, const char* src, char* dst, int srcSize, int maxDstSize);
|
||||
|
||||
int LZ3__saveDictHC (LZ3__streamHC_t* streamHCPtr, char* safeBuffer, int maxDictSize);
|
||||
|
||||
/*
|
||||
These functions compress data in successive blocks of any size, using previous blocks as dictionary.
|
||||
One key assumption is that previous blocks (up to 64 KB) remain read-accessible while compressing next blocks.
|
||||
There is an exception for ring buffers, which can be smaller 64 KB.
|
||||
Such case is automatically detected and correctly handled by LZ3__compress_HC_continue().
|
||||
|
||||
Before starting compression, state must be properly initialized, using LZ3__resetStreamHC().
|
||||
A first "fictional block" can then be designated as initial dictionary, using LZ3__loadDictHC() (Optional).
|
||||
|
||||
Then, use LZ3__compress_HC_continue() to compress each successive block.
|
||||
It works like LZ3__compress_HC(), but use previous memory blocks as dictionary to improve compression.
|
||||
Previous memory blocks (including initial dictionary when present) must remain accessible and unmodified during compression.
|
||||
As a reminder, size 'dst' buffer to handle worst cases, using LZ3__compressBound(), to ensure success of compression operation.
|
||||
|
||||
If, for any reason, previous data blocks can't be preserved unmodified in memory during next compression block,
|
||||
you must save it to a safer memory space, using LZ3__saveDictHC().
|
||||
Return value of LZ3__saveDictHC() is the size of dictionary effectively saved into 'safeBuffer'.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**************************************
|
||||
* Deprecated Functions
|
||||
**************************************/
|
||||
/* Deprecate Warnings */
|
||||
/* Should these warnings messages be a problem,
|
||||
it is generally possible to disable them,
|
||||
with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual for example.
|
||||
You can also define LZ3__DEPRECATE_WARNING_DEFBLOCK. */
|
||||
#ifndef LZ3__DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ3__DEPRECATE_WARNING_DEFBLOCK
|
||||
# define LZ3__GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if (LZ3__GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ3__DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ3__GCC_VERSION >= 301)
|
||||
# define LZ3__DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ3__DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ3__DEPRECATED for this compiler")
|
||||
# define LZ3__DEPRECATED(message)
|
||||
# endif
|
||||
#endif // LZ3__DEPRECATE_WARNING_DEFBLOCK
|
||||
|
||||
/* compression functions */
|
||||
/* these functions are planned to trigger warning messages by r131 approximately */
|
||||
int LZ3__compressHC (const char* source, char* dest, int inputSize);
|
||||
int LZ3__compressHC_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ3__compressHC2 (const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
int LZ3__compressHC2_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
int LZ3__compressHC_withStateHC (void* state, const char* source, char* dest, int inputSize);
|
||||
int LZ3__compressHC_limitedOutput_withStateHC (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
int LZ3__compressHC2_withStateHC (void* state, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
int LZ3__compressHC2_limitedOutput_withStateHC(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
int LZ3__compressHC_continue (LZ3__streamHC_t* LZ3__streamHCPtr, const char* source, char* dest, int inputSize);
|
||||
int LZ3__compressHC_limitedOutput_continue (LZ3__streamHC_t* LZ3__streamHCPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Streaming functions following the older model; should no longer be used */
|
||||
LZ3__DEPRECATED("use LZ3__createStreamHC() instead") void* LZ3__createHC (char* inputBuffer);
|
||||
LZ3__DEPRECATED("use LZ3__saveDictHC() instead") char* LZ3__slideInputBufferHC (void* LZ3HC_Data);
|
||||
LZ3__DEPRECATED("use LZ3__freeStreamHC() instead") int LZ3__freeHC (void* LZ3HC_Data);
|
||||
LZ3__DEPRECATED("use LZ3__compress_HC_continue() instead") int LZ3__compressHC2_continue (void* LZ3HC_Data, const char* source, char* dest, int inputSize, int compressionLevel);
|
||||
LZ3__DEPRECATED("use LZ3__compress_HC_continue() instead") int LZ3__compressHC2_limitedOutput_continue (void* LZ3HC_Data, const char* source, char* dest, int inputSize, int maxOutputSize, int compressionLevel);
|
||||
LZ3__DEPRECATED("use LZ3__createStreamHC() instead") int LZ3__sizeofStreamStateHC(void);
|
||||
LZ3__DEPRECATED("use LZ3__resetStreamHC() instead") int LZ3__resetStreamStateHC(void* state, char* inputBuffer);
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4hc.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8143639c0b7f67d4a8cea5202933138c
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1079
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.cpp
Normal file
1079
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.cpp
Normal file
File diff suppressed because it is too large
Load Diff
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.cpp.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.cpp.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8e5fcca88aab684eab88643cb1bda84
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
32
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.h
Normal file
32
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.h
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
/* ************************************************** */
|
||||
/* Special input/output values */
|
||||
/* ************************************************** */
|
||||
#define NULL_OUTPUT "null"
|
||||
static char const stdinmark[] = "stdin";
|
||||
static char const stdoutmark[] = "stdout";
|
||||
#ifdef _WIN32
|
||||
static char const nulmark[] = "nul";
|
||||
#else
|
||||
static char const nulmark[] = "/dev/null";
|
||||
#endif
|
||||
|
||||
|
||||
/* ************************************************** */
|
||||
/* ****************** Functions ********************* */
|
||||
/* ************************************************** */
|
||||
|
||||
//int __declspec(dllexport) LZ3CompressFile (const char* input_filename, const char* output_filename, int compressionlevel);
|
||||
//int __declspec(dllexport) LZ3DecompressFile(const char* input_filename, const char* output_filename);
|
||||
|
||||
|
||||
//int LZ3ComressFiles(const char** inFileNamesTable, int ifntSize, const char* suffix, int compressionlevel);
|
||||
//int LZ3DecomressFiles(const char** inFileNamesTable, int ifntSize, const char* suffix);
|
||||
|
||||
/* ************************************************** */
|
||||
/* ****************** Parameters ******************** */
|
||||
/* ************************************************** */
|
||||
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/lz4w.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f10009d6a3e390c40b709701a079784c
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
882
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.cpp
Normal file
882
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
|
||||
/**************************************
|
||||
* Tuning parameters
|
||||
**************************************/
|
||||
/* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
|
||||
* For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
|
||||
* If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
|
||||
* You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
|
||||
*/
|
||||
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# define XXH_USE_UNALIGNED_ACCESS 1
|
||||
#endif
|
||||
|
||||
/* XXH_ACCEPT_NULL_INPUT_POINTER :
|
||||
* If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
|
||||
* When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
|
||||
* By default, this option is disabled. To enable it, uncomment below define :
|
||||
*/
|
||||
/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
|
||||
|
||||
/* XXH_FORCE_NATIVE_FORMAT :
|
||||
* By default, xxHash library provides endian-independant Hash values, based on little-endian convention.
|
||||
* Results are therefore identical for little-endian and big-endian CPU.
|
||||
* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
|
||||
* Should endian-independance be of no importance for your application, you may set the #define below to 1.
|
||||
* It will improve speed for Big-endian CPU.
|
||||
* This option has no impact on Little_Endian CPU.
|
||||
*/
|
||||
#define XXH_FORCE_NATIVE_FORMAT 0
|
||||
|
||||
|
||||
/**************************************
|
||||
* Compiler Specific Options
|
||||
***************************************/
|
||||
#ifdef _MSC_VER /* Visual Studio */
|
||||
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
|
||||
# define FORCE_INLINE static __forceinline
|
||||
#else
|
||||
# if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# ifdef __GNUC__
|
||||
# define FORCE_INLINE static inline __attribute__((always_inline))
|
||||
# else
|
||||
# define FORCE_INLINE static inline
|
||||
# endif
|
||||
# else
|
||||
# define FORCE_INLINE static
|
||||
# endif /* __STDC_VERSION__ */
|
||||
#endif
|
||||
|
||||
|
||||
/**************************************
|
||||
* Includes & Memory related functions
|
||||
***************************************/
|
||||
#include "xxhash.h"
|
||||
/* Modify the local functions below should you wish to use some other memory routines */
|
||||
/* for malloc(), free() */
|
||||
#include <stdlib.h>
|
||||
static void* XXH_malloc(size_t s) { return malloc(s); }
|
||||
static void XXH_free (void* p) { free(p); }
|
||||
/* for memcpy() */
|
||||
#include <string.h>
|
||||
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
|
||||
|
||||
|
||||
/**************************************
|
||||
* Basic Types
|
||||
***************************************/
|
||||
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
|
||||
# include <stdint.h>
|
||||
typedef uint8_t BYTE;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
#else
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
typedef unsigned long long U64;
|
||||
#endif
|
||||
|
||||
static U32 XXH_read32(const void* memPtr)
|
||||
{
|
||||
U32 val32;
|
||||
memcpy(&val32, memPtr, 4);
|
||||
return val32;
|
||||
}
|
||||
|
||||
static U64 XXH_read64(const void* memPtr)
|
||||
{
|
||||
U64 val64;
|
||||
memcpy(&val64, memPtr, 8);
|
||||
return val64;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************
|
||||
* Compiler-specific Functions and Macros
|
||||
******************************************/
|
||||
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
|
||||
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
|
||||
#if defined(_MSC_VER)
|
||||
# define XXH_rotl32(x,r) _rotl(x,r)
|
||||
# define XXH_rotl64(x,r) _rotl64(x,r)
|
||||
#else
|
||||
# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
|
||||
# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) /* Visual Studio */
|
||||
# define XXH_swap32 _byteswap_ulong
|
||||
# define XXH_swap64 _byteswap_uint64
|
||||
#elif GCC_VERSION >= 403
|
||||
# define XXH_swap32 __builtin_bswap32
|
||||
# define XXH_swap64 __builtin_bswap64
|
||||
#else
|
||||
static U32 XXH_swap32 (U32 x)
|
||||
{
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
static U64 XXH_swap64 (U64 x)
|
||||
{
|
||||
return ((x << 56) & 0xff00000000000000ULL) |
|
||||
((x << 40) & 0x00ff000000000000ULL) |
|
||||
((x << 24) & 0x0000ff0000000000ULL) |
|
||||
((x << 8) & 0x000000ff00000000ULL) |
|
||||
((x >> 8) & 0x00000000ff000000ULL) |
|
||||
((x >> 24) & 0x0000000000ff0000ULL) |
|
||||
((x >> 40) & 0x000000000000ff00ULL) |
|
||||
((x >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************
|
||||
* Architecture Macros
|
||||
***************************************/
|
||||
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
|
||||
#ifndef XXH_CPU_LITTLE_ENDIAN /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example using a compiler switch */
|
||||
static const int one = 1;
|
||||
# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one))
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Memory reads
|
||||
*****************************/
|
||||
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE32_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
if (align==XXH_unaligned)
|
||||
return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
|
||||
else
|
||||
return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
|
||||
{
|
||||
return XXH_readLE64_align(ptr, endian, XXH_unaligned);
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* Macros
|
||||
***************************************/
|
||||
#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */
|
||||
|
||||
|
||||
/***************************************
|
||||
* Constants
|
||||
***************************************/
|
||||
#define PRIME32_1 2654435761U
|
||||
#define PRIME32_2 2246822519U
|
||||
#define PRIME32_3 3266489917U
|
||||
#define PRIME32_4 668265263U
|
||||
#define PRIME32_5 374761393U
|
||||
|
||||
#define PRIME64_1 11400714785074694791ULL
|
||||
#define PRIME64_2 14029467366897019727ULL
|
||||
#define PRIME64_3 1609587929392839161ULL
|
||||
#define PRIME64_4 9650029242287828579ULL
|
||||
#define PRIME64_5 2870177450012600261ULL
|
||||
|
||||
|
||||
/*****************************
|
||||
* Simple Hash Functions
|
||||
*****************************/
|
||||
FORCE_INLINE U32 XX_H32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U32 h32;
|
||||
#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
U32 v2 = seed + PRIME32_2;
|
||||
U32 v3 = seed + 0;
|
||||
U32 v4 = seed - PRIME32_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get32bits(p) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_get32bits(p) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_get32bits(p) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_get32bits(p) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_get32bits(p) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
unsigned XX_H32 (const void* input, size_t len, unsigned seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XX_H32_state_t state;
|
||||
XX_H32_reset(&state, seed);
|
||||
XX_H32_update(&state, input, len);
|
||||
return XX_H32_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 3) == 0) /* Input is 4-bytes aligned, leverage the speed benefit */
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XX_H32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XX_H32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCE_INLINE U64 XX_H64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
|
||||
{
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* bEnd = p + len;
|
||||
U64 h64;
|
||||
#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (p==NULL)
|
||||
{
|
||||
len=0;
|
||||
bEnd=p=(const BYTE*)(size_t)32;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len>=32)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
U64 v2 = seed + PRIME64_2;
|
||||
U64 v3 = seed + 0;
|
||||
U64 v4 = seed - PRIME64_1;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
v2 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
v3 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
v4 += XXH_get64bits(p) * PRIME64_2;
|
||||
p+=8;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64 * PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_get64bits(p);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XX_H64 (const void* input, size_t len, unsigned long long seed)
|
||||
{
|
||||
#if 0
|
||||
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
|
||||
XX_H64_state_t state;
|
||||
XX_H64_reset(&state, seed);
|
||||
XX_H64_update(&state, input, len);
|
||||
return XX_H64_digest(&state);
|
||||
#else
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
# if !defined(XXH_USE_UNALIGNED_ACCESS)
|
||||
if ((((size_t)input) & 7)==0) /* Input is aligned, let's leverage the speed advantage */
|
||||
{
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
|
||||
else
|
||||
return XX_H64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
|
||||
}
|
||||
# endif
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
|
||||
else
|
||||
return XX_H64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************
|
||||
* Advanced Hash Functions
|
||||
****************************************************/
|
||||
|
||||
/*** Allocation ***/
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U32 seed;
|
||||
U32 v1;
|
||||
U32 v2;
|
||||
U32 v3;
|
||||
U32 v4;
|
||||
U32 mem32[4]; /* defined as U32 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
U64 total_len;
|
||||
U64 seed;
|
||||
U64 v1;
|
||||
U64 v2;
|
||||
U64 v3;
|
||||
U64 v4;
|
||||
U64 mem64[4]; /* defined as U64 for alignment */
|
||||
U32 memsize;
|
||||
} XXH_istate64_t;
|
||||
|
||||
|
||||
XX_H32_state_t* XX_H32_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XX_H32_state_t) >= sizeof(XXH_istate32_t)); /* A compilation error here means XX_H32_state_t is not large enough */
|
||||
return (XX_H32_state_t*)XXH_malloc(sizeof(XX_H32_state_t));
|
||||
}
|
||||
XXH_errorcode XX_H32_freeState(XX_H32_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XX_H64_state_t* XX_H64_createState(void)
|
||||
{
|
||||
XXH_STATIC_ASSERT(sizeof(XX_H64_state_t) >= sizeof(XXH_istate64_t)); /* A compilation error here means XX_H64_state_t is not large enough */
|
||||
return (XX_H64_state_t*)XXH_malloc(sizeof(XX_H64_state_t));
|
||||
}
|
||||
XXH_errorcode XX_H64_freeState(XX_H64_state_t* statePtr)
|
||||
{
|
||||
XXH_free(statePtr);
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
/*** Hash feed ***/
|
||||
|
||||
XXH_errorcode XX_H32_reset(XX_H32_state_t* state_in, U32 seed)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME32_1 + PRIME32_2;
|
||||
state->v2 = seed + PRIME32_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME32_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XX_H64_reset(XX_H64_state_t* state_in, unsigned long long seed)
|
||||
{
|
||||
XXH_istate64_t* state = (XXH_istate64_t*) state_in;
|
||||
state->seed = seed;
|
||||
state->v1 = seed + PRIME64_1 + PRIME64_2;
|
||||
state->v2 = seed + PRIME64_2;
|
||||
state->v3 = seed + 0;
|
||||
state->v4 = seed - PRIME64_1;
|
||||
state->total_len = 0;
|
||||
state->memsize = 0;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XX_H32_update_endian (XX_H32_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate32_t* state = (XXH_istate32_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 16) /* fill in tmp buffer */
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) /* some data left from previous update */
|
||||
{
|
||||
XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
|
||||
{
|
||||
const U32* p32 = state->mem32;
|
||||
state->v1 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v1 = XXH_rotl32(state->v1, 13);
|
||||
state->v1 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v2 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v2 = XXH_rotl32(state->v2, 13);
|
||||
state->v2 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v3 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v3 = XXH_rotl32(state->v3, 13);
|
||||
state->v3 *= PRIME32_1;
|
||||
p32++;
|
||||
state->v4 += XXH_readLE32(p32, endian) * PRIME32_2;
|
||||
state->v4 = XXH_rotl32(state->v4, 13);
|
||||
state->v4 *= PRIME32_1;
|
||||
p32++;
|
||||
}
|
||||
p += 16-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p <= bEnd-16)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 16;
|
||||
U32 v1 = state->v1;
|
||||
U32 v2 = state->v2;
|
||||
U32 v3 = state->v3;
|
||||
U32 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v1 = XXH_rotl32(v1, 13);
|
||||
v1 *= PRIME32_1;
|
||||
p+=4;
|
||||
v2 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v2 = XXH_rotl32(v2, 13);
|
||||
v2 *= PRIME32_1;
|
||||
p+=4;
|
||||
v3 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v3 = XXH_rotl32(v3, 13);
|
||||
v3 *= PRIME32_1;
|
||||
p+=4;
|
||||
v4 += XXH_readLE32(p, endian) * PRIME32_2;
|
||||
v4 = XXH_rotl32(v4, 13);
|
||||
v4 *= PRIME32_1;
|
||||
p+=4;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem32, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XX_H32_update (XX_H32_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H32_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XX_H32_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U32 XX_H32_digest_endian (const XX_H32_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
const XXH_istate32_t* state = (const XXH_istate32_t*) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem32;
|
||||
const BYTE* bEnd = (const BYTE*)(state->mem32) + state->memsize;
|
||||
U32 h32;
|
||||
|
||||
if (state->total_len >= 16)
|
||||
{
|
||||
h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
|
||||
}
|
||||
else
|
||||
{
|
||||
h32 = state->seed + PRIME32_5;
|
||||
}
|
||||
|
||||
h32 += (U32) state->total_len;
|
||||
|
||||
while (p+4<=bEnd)
|
||||
{
|
||||
h32 += XXH_readLE32(p, endian) * PRIME32_3;
|
||||
h32 = XXH_rotl32(h32, 17) * PRIME32_4;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h32 += (*p) * PRIME32_5;
|
||||
h32 = XXH_rotl32(h32, 11) * PRIME32_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h32 ^= h32 >> 15;
|
||||
h32 *= PRIME32_2;
|
||||
h32 ^= h32 >> 13;
|
||||
h32 *= PRIME32_3;
|
||||
h32 ^= h32 >> 16;
|
||||
|
||||
return h32;
|
||||
}
|
||||
|
||||
|
||||
U32 XX_H32_digest (const XX_H32_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H32_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XX_H32_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE XXH_errorcode XX_H64_update_endian (XX_H64_state_t* state_in, const void* input, size_t len, XXH_endianess endian)
|
||||
{
|
||||
XXH_istate64_t * state = (XXH_istate64_t *) state_in;
|
||||
const BYTE* p = (const BYTE*)input;
|
||||
const BYTE* const bEnd = p + len;
|
||||
|
||||
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
|
||||
if (input==NULL) return XXH_ERROR;
|
||||
#endif
|
||||
|
||||
state->total_len += len;
|
||||
|
||||
if (state->memsize + len < 32) /* fill in tmp buffer */
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
|
||||
state->memsize += (U32)len;
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
if (state->memsize) /* some data left from previous update */
|
||||
{
|
||||
XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
|
||||
{
|
||||
const U64* p64 = state->mem64;
|
||||
state->v1 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v1 = XXH_rotl64(state->v1, 31);
|
||||
state->v1 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v2 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v2 = XXH_rotl64(state->v2, 31);
|
||||
state->v2 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v3 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v3 = XXH_rotl64(state->v3, 31);
|
||||
state->v3 *= PRIME64_1;
|
||||
p64++;
|
||||
state->v4 += XXH_readLE64(p64, endian) * PRIME64_2;
|
||||
state->v4 = XXH_rotl64(state->v4, 31);
|
||||
state->v4 *= PRIME64_1;
|
||||
p64++;
|
||||
}
|
||||
p += 32-state->memsize;
|
||||
state->memsize = 0;
|
||||
}
|
||||
|
||||
if (p+32 <= bEnd)
|
||||
{
|
||||
const BYTE* const limit = bEnd - 32;
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
do
|
||||
{
|
||||
v1 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
p+=8;
|
||||
v2 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
p+=8;
|
||||
v3 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
p+=8;
|
||||
v4 += XXH_readLE64(p, endian) * PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
p+=8;
|
||||
}
|
||||
while (p<=limit);
|
||||
|
||||
state->v1 = v1;
|
||||
state->v2 = v2;
|
||||
state->v3 = v3;
|
||||
state->v4 = v4;
|
||||
}
|
||||
|
||||
if (p < bEnd)
|
||||
{
|
||||
XXH_memcpy(state->mem64, p, bEnd-p);
|
||||
state->memsize = (int)(bEnd-p);
|
||||
}
|
||||
|
||||
return XXH_OK;
|
||||
}
|
||||
|
||||
XXH_errorcode XX_H64_update (XX_H64_state_t* state_in, const void* input, size_t len)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H64_update_endian(state_in, input, len, XXH_littleEndian);
|
||||
else
|
||||
return XX_H64_update_endian(state_in, input, len, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
|
||||
FORCE_INLINE U64 XX_H64_digest_endian (const XX_H64_state_t* state_in, XXH_endianess endian)
|
||||
{
|
||||
const XXH_istate64_t * state = (const XXH_istate64_t *) state_in;
|
||||
const BYTE * p = (const BYTE*)state->mem64;
|
||||
const BYTE* bEnd = (const BYTE*)state->mem64 + state->memsize;
|
||||
U64 h64;
|
||||
|
||||
if (state->total_len >= 32)
|
||||
{
|
||||
U64 v1 = state->v1;
|
||||
U64 v2 = state->v2;
|
||||
U64 v3 = state->v3;
|
||||
U64 v4 = state->v4;
|
||||
|
||||
h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
|
||||
|
||||
v1 *= PRIME64_2;
|
||||
v1 = XXH_rotl64(v1, 31);
|
||||
v1 *= PRIME64_1;
|
||||
h64 ^= v1;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v2 *= PRIME64_2;
|
||||
v2 = XXH_rotl64(v2, 31);
|
||||
v2 *= PRIME64_1;
|
||||
h64 ^= v2;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v3 *= PRIME64_2;
|
||||
v3 = XXH_rotl64(v3, 31);
|
||||
v3 *= PRIME64_1;
|
||||
h64 ^= v3;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
|
||||
v4 *= PRIME64_2;
|
||||
v4 = XXH_rotl64(v4, 31);
|
||||
v4 *= PRIME64_1;
|
||||
h64 ^= v4;
|
||||
h64 = h64*PRIME64_1 + PRIME64_4;
|
||||
}
|
||||
else
|
||||
{
|
||||
h64 = state->seed + PRIME64_5;
|
||||
}
|
||||
|
||||
h64 += (U64) state->total_len;
|
||||
|
||||
while (p+8<=bEnd)
|
||||
{
|
||||
U64 k1 = XXH_readLE64(p, endian);
|
||||
k1 *= PRIME64_2;
|
||||
k1 = XXH_rotl64(k1,31);
|
||||
k1 *= PRIME64_1;
|
||||
h64 ^= k1;
|
||||
h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
|
||||
p+=8;
|
||||
}
|
||||
|
||||
if (p+4<=bEnd)
|
||||
{
|
||||
h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
|
||||
h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
|
||||
p+=4;
|
||||
}
|
||||
|
||||
while (p<bEnd)
|
||||
{
|
||||
h64 ^= (*p) * PRIME64_5;
|
||||
h64 = XXH_rotl64(h64, 11) * PRIME64_1;
|
||||
p++;
|
||||
}
|
||||
|
||||
h64 ^= h64 >> 33;
|
||||
h64 *= PRIME64_2;
|
||||
h64 ^= h64 >> 29;
|
||||
h64 *= PRIME64_3;
|
||||
h64 ^= h64 >> 32;
|
||||
|
||||
return h64;
|
||||
}
|
||||
|
||||
|
||||
unsigned long long XX_H64_digest (const XX_H64_state_t* state_in)
|
||||
{
|
||||
XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
|
||||
|
||||
if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
|
||||
return XX_H64_digest_endian(state_in, XXH_littleEndian);
|
||||
else
|
||||
return XX_H64_digest_endian(state_in, XXH_bigEndian);
|
||||
}
|
||||
|
||||
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.cpp.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.cpp.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52ae2e366e2b8514aa157ffb1cb9c7bd
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
192
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.h
Normal file
192
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
xxHash - Extremely Fast Hash algorithm
|
||||
Header File
|
||||
Copyright (C) 2012-2015, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- xxHash source repository : https://github.com/Cyan4973/xxHash
|
||||
*/
|
||||
|
||||
/* Notice extracted from xxHash homepage :
|
||||
|
||||
xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
|
||||
It also successfully passes all tests from the SMHasher suite.
|
||||
|
||||
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
|
||||
|
||||
Name Speed Q.Score Author
|
||||
xxHash 5.4 GB/s 10
|
||||
CrapWow 3.2 GB/s 2 Andrew
|
||||
MumurHash 3a 2.7 GB/s 10 Austin Appleby
|
||||
SpookyHash 2.0 GB/s 10 Bob Jenkins
|
||||
SBox 1.4 GB/s 9 Bret Mulvey
|
||||
Lookup3 1.2 GB/s 9 Bob Jenkins
|
||||
SuperFastHash 1.2 GB/s 1 Paul Hsieh
|
||||
CityHash64 1.05 GB/s 10 Pike & Alakuijala
|
||||
FNV 0.55 GB/s 5 Fowler, Noll, Vo
|
||||
CRC32 0.43 GB/s 9
|
||||
MD5-32 0.33 GB/s 10 Ronald L. Rivest
|
||||
SHA1-32 0.28 GB/s 10
|
||||
|
||||
Q.Score is a measure of quality of the hash function.
|
||||
It depends on successfully passing SMHasher test set.
|
||||
10 is a perfect score.
|
||||
|
||||
A 64-bits version, named XX_H64, is available since r35.
|
||||
It offers much better speed, but for 64-bits applications only.
|
||||
Name Speed on 64 bits Speed on 32 bits
|
||||
XX_H64 13.8 GB/s 1.9 GB/s
|
||||
XX_H32 6.8 GB/s 6.0 GB/s
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Definitions
|
||||
*****************************/
|
||||
#include <stddef.h> /* size_t */
|
||||
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
||||
|
||||
|
||||
/*****************************
|
||||
* Namespace Emulation
|
||||
*****************************/
|
||||
/* Motivations :
|
||||
|
||||
If you need to include xxHash into your library,
|
||||
but wish to avoid xxHash symbols to be present on your library interface
|
||||
in an effort to avoid potential name collision if another library also includes xxHash,
|
||||
|
||||
you can use XXH_NAMESPACE, which will automatically prefix any symbol from xxHash
|
||||
with the value of XXH_NAMESPACE (so avoid to keep it NULL, and avoid numeric values).
|
||||
|
||||
Note that no change is required within the calling program :
|
||||
it can still call xxHash functions using their regular name.
|
||||
They will be automatically translated by this header.
|
||||
*/
|
||||
#ifdef XXH_NAMESPACE
|
||||
# define XXH_CAT(A,B) A##B
|
||||
# define XXH_NAME2(A,B) XXH_CAT(A,B)
|
||||
# define XX_H32 XXH_NAME2(XXH_NAMESPACE, XX_H32)
|
||||
# define XX_H64 XXH_NAME2(XXH_NAMESPACE, XX_H64)
|
||||
# define XX_H32_createState XXH_NAME2(XXH_NAMESPACE, XX_H32_createState)
|
||||
# define XX_H64_createState XXH_NAME2(XXH_NAMESPACE, XX_H64_createState)
|
||||
# define XX_H32_freeState XXH_NAME2(XXH_NAMESPACE, XX_H32_freeState)
|
||||
# define XX_H64_freeState XXH_NAME2(XXH_NAMESPACE, XX_H64_freeState)
|
||||
# define XX_H32_reset XXH_NAME2(XXH_NAMESPACE, XX_H32_reset)
|
||||
# define XX_H64_reset XXH_NAME2(XXH_NAMESPACE, XX_H64_reset)
|
||||
# define XX_H32_update XXH_NAME2(XXH_NAMESPACE, XX_H32_update)
|
||||
# define XX_H64_update XXH_NAME2(XXH_NAMESPACE, XX_H64_update)
|
||||
# define XX_H32_digest XXH_NAME2(XXH_NAMESPACE, XX_H32_digest)
|
||||
# define XX_H64_digest XXH_NAME2(XXH_NAMESPACE, XX_H64_digest)
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************
|
||||
* Simple Hash Functions
|
||||
*****************************/
|
||||
|
||||
unsigned int XX_H32 (const void* input, size_t length, unsigned seed);
|
||||
unsigned long long XX_H64 (const void* input, size_t length, unsigned long long seed);
|
||||
|
||||
/*
|
||||
XX_H32() :
|
||||
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
||||
The memory between input & input+length must be valid (allocated and read-accessible).
|
||||
"seed" can be used to alter the result predictably.
|
||||
This function successfully passes all SMHasher tests.
|
||||
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
|
||||
XX_H64() :
|
||||
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
||||
Faster on 64-bits systems. Slower on 32-bits systems.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************
|
||||
* Advanced Hash Functions
|
||||
*****************************/
|
||||
typedef struct { long long ll[ 6]; } XX_H32_state_t;
|
||||
typedef struct { long long ll[11]; } XX_H64_state_t;
|
||||
|
||||
/*
|
||||
These structures allow static allocation of XXH states.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
|
||||
If you prefer dynamic allocation, please refer to functions below.
|
||||
*/
|
||||
|
||||
XX_H32_state_t* XX_H32_createState(void);
|
||||
XXH_errorcode XX_H32_freeState(XX_H32_state_t* statePtr);
|
||||
|
||||
XX_H64_state_t* XX_H64_createState(void);
|
||||
XXH_errorcode XX_H64_freeState(XX_H64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions create and release memory for XXH state.
|
||||
States must then be initialized using XXHnn_reset() before first use.
|
||||
*/
|
||||
|
||||
|
||||
XXH_errorcode XX_H32_reset (XX_H32_state_t* statePtr, unsigned seed);
|
||||
XXH_errorcode XX_H32_update (XX_H32_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned int XX_H32_digest (const XX_H32_state_t* statePtr);
|
||||
|
||||
XXH_errorcode XX_H64_reset (XX_H64_state_t* statePtr, unsigned long long seed);
|
||||
XXH_errorcode XX_H64_update (XX_H64_state_t* statePtr, const void* input, size_t length);
|
||||
unsigned long long XX_H64_digest (const XX_H64_state_t* statePtr);
|
||||
|
||||
/*
|
||||
These functions calculate the xxHash of an input provided in multiple smaller packets,
|
||||
as opposed to an input provided as a single block.
|
||||
|
||||
XXH state space must first be allocated, using either static or dynamic method provided above.
|
||||
|
||||
Start a new hash by initializing state with a seed, using XXHnn_reset().
|
||||
|
||||
Then, feed the hash state by calling XXHnn_update() as many times as necessary.
|
||||
Obviously, input must be valid, meaning allocated and read accessible.
|
||||
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
||||
|
||||
Finally, you can produce a hash anytime, by using XXHnn_digest().
|
||||
This function returns the final nn-bits hash.
|
||||
You can nonetheless continue feeding the hash state with more input,
|
||||
and therefore get some new hashes, by calling again XXHnn_digest().
|
||||
|
||||
When you are done, don't forget to free XXH state space, using typically XXHnn_freeState().
|
||||
*/
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.h.meta
Normal file
37
Assets/Plugins/LZ4/Plugins/WebGL/cpp/xxhash.h.meta
Normal file
@@ -0,0 +1,37 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f76b62f793e182d43863dc5527a5b393
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Facebook: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
WebGL: WebGL
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/iOS.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/iOS.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3605bda20581e5d468344c163d61f949
|
||||
folderAsset: yes
|
||||
timeCreated: 1553412858
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a
Normal file
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a
Normal file
Binary file not shown.
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a.Simulator.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a.Simulator.zip
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a5c4e27d266b6945965f03f1a2ae513
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
33
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a.meta
Normal file
33
Assets/Plugins/LZ4/Plugins/iOS/liblz4.a.meta
Normal file
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c7f4d607bc225c4f897d42e04e8720f
|
||||
timeCreated: 1567837724
|
||||
licenseType: Store
|
||||
PluginImporter:
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
platformData:
|
||||
data:
|
||||
first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
data:
|
||||
first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
data:
|
||||
first:
|
||||
iPhone: iOS
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.bitcode.xcode10.3.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.bitcode.xcode10.3.zip
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 638d669af33f8604c9bdb68ae260b8b3
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.bitcode.xcode11.4.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/iOS/liblz4.bitcode.xcode11.4.zip
Normal file
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1974392f91cc1224baacac62fa96014b
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
9
Assets/Plugins/LZ4/Plugins/iOS/non-bitcode.meta
Normal file
9
Assets/Plugins/LZ4/Plugins/iOS/non-bitcode.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd674dae89266124c8327f200d9dfa3a
|
||||
folderAsset: yes
|
||||
timeCreated: 1567837722
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/iOS/non-bitcode/liblz4.a.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/iOS/non-bitcode/liblz4.a.zip
Normal file
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f5339459ddbb5e48ab22202464f9d9c
|
||||
timeCreated: 1567837722
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/liblz4.bundle-Intel.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/liblz4.bundle-Intel.zip
Normal file
Binary file not shown.
7
Assets/Plugins/LZ4/Plugins/liblz4.bundle-Intel.zip.meta
Normal file
7
Assets/Plugins/LZ4/Plugins/liblz4.bundle-Intel.zip.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b0cf7647ff38c049841101e92aa9bc9
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Plugins/LZ4/Plugins/liblz4.bundle-SiliconSupport.zip
Normal file
BIN
Assets/Plugins/LZ4/Plugins/liblz4.bundle-SiliconSupport.zip
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user