folderchange

This commit is contained in:
2026-02-25 17:24:42 +09:00
parent 4a25b39d7b
commit b2283d04c1
955 changed files with 58 additions and 1993 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81f481468a087c74ea3a326fd2fc33e1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a2a7b4351f0a477479c2cf11d971bb3e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe1091a74ea67954db55dd73a0be5dab
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fdbf4dac63e13c14c96f45a9bd20e412
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b57a501956808744a6f4c77d47aa9ac
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 85bff82fc19c984458a58f9f4d097ed8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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;
}
}

View File

@@ -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

View 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;
}
}

View File

@@ -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

View 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;
}
}

View 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

View File

@@ -0,0 +1,8 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HybridIKStretchJunction : MonoBehaviour
{
}

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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

View 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;
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c12f4ab377ddfdc46820089b240eaf27

View 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);
// }
//}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e6dac70e0e196a043852640887710f7b

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b509378e1379bb54cbbbb7ce530a5fe9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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öllerTrumbore 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]);
}
}

View File

@@ -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
View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 673e554486793784d92d2ef90b8dea5a
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3c160d3ac61ffb24280705bed0c10407
timeCreated: 1553410075
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View 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:

View File

@@ -0,0 +1,4 @@
fileFormatVersion: 2
guid: 91f0e133e0bfc794da70fc393c643d4e
DefaultImporter:
userData:

View 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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0847c23f6299b08449f39502733f7805
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:

View 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:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 085b09c1884d0e4439d0d764db99294c
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 573b2714aeb9d2e4e8db669feb1ca633
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2d260117c8a0ece4f828af94e62c153b
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 516ae443aec77514dbff9fa328ec083a
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 92b3b193a934e2b4ca676c01c7dc5407
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ecfaac3a146ce634293499223bcd4472
folderAsset: yes
timeCreated: 1553410075
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 0c4d3c932d67b214d929b9bd81687246
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: fde2cd5749a38e54f8d0b3f05b20dbe0
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View 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:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 196223d89bc925b4c96c2a18314c57b4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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:

View 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
}

View 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:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0e70a6eaee266b246af755bee6eb5452
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 19b593114c441f349b1510ae835c8ef8
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View 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:

View 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

View 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:

File diff suppressed because it is too large Load Diff

View 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:

View 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

View 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:

View 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

View 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:

View 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);
}

View 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:

View 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

View 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:

File diff suppressed because it is too large Load Diff

View 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:

View 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 ******************** */
/* ************************************************** */

View 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:

View 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);
}

View 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:

View 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

View 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:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 3605bda20581e5d468344c163d61f949
folderAsset: yes
timeCreated: 1553412858
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4a5c4e27d266b6945965f03f1a2ae513
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View 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:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 638d669af33f8604c9bdb68ae260b8b3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1974392f91cc1224baacac62fa96014b
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: cd674dae89266124c8327f200d9dfa3a
folderAsset: yes
timeCreated: 1567837722
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4f5339459ddbb5e48ab22202464f9d9c
timeCreated: 1567837722
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b0cf7647ff38c049841101e92aa9bc9
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More