public static void ScheduleRenderLibFiveMesh(LFTree tree, Bounds bounds, float resolution, ref RenderJobPayload payload) { UnityEngine.Profiling.Profiler.BeginSample("Schedule Render Mesh"); libfive_region3 bound = new libfive_region3(); bound.X.lower = bounds.min.x; bound.Y.lower = bounds.min.y; bound.Z.lower = bounds.min.z; bound.X.upper = bounds.max.x; bound.Y.upper = bounds.max.y; bound.Z.upper = bounds.max.z; RenderLibFiveMeshJob curRenderJob; unsafe { curRenderJob = new RenderLibFiveMeshJob() { treeToRender = tree.tree, bounds = bound, resolution = resolution, libFiveMeshPtr = payload.libFiveMeshPtr }; } payload.handle = curRenderJob.Schedule(payload.handle); JobHandle.ScheduleBatchedJobs(); UnityEngine.Profiling.Profiler.EndSample(); }
/// <summary>Creates an ellipsoid</summary> public static LFTree Ellipsoid(float radius, Vector3 focusA, Vector3 focusB) { LFTree x = LFTree.x, y = LFTree.y, z = LFTree.z; return(Sqrt(Square(x - focusA.x) + Square(y - focusA.y) + Square(z - focusA.z)) + Sqrt(Square(x - focusB.x) + Square(y - focusB.y) + Square(z - focusB.z)) - radius); }
/// <summary>Returns the intersection of any number of shapes</summary> public static LFTree Intersection(params LFTree[] shapes) { LFTree intersectedTree = shapes[0]; for (int i = 1; i < shapes.Length; i++) { intersectedTree = Max(intersectedTree, shapes[i]); } return(intersectedTree); }
/// <summary>Returns the blend of any number of shapes</summary> public static LFTree Blend(float blendAmount = 0.5f, params LFTree[] shapes) { LFTree blendedTree = shapes[0]; for (int i = 1; i < shapes.Length; i++) { blendedTree = Blend(blendedTree, shapes[i], blendAmount); } return(blendedTree); }
public static LFTree Transform(LFTree t, Matrix4x4 matrix) { Matrix4x4 invert = matrix.inverse; LFTree x = LFTree.x, y = LFTree.y, z = LFTree.z; return(t.Remap( invert.m00 * x + invert.m01 * y + invert.m02 * z + invert.m03, invert.m10 * x + invert.m11 * y + invert.m12 * z + invert.m13, invert.m20 * x + invert.m21 * y + invert.m22 * z + invert.m23)); }
public LFTree Evaluate() { UnityEngine.Profiling.Profiler.BeginSample("Evaluate LibFive Tree", this); using (LFContext.Active = new Context()) { if (op > 0 && (int)op < 100) { tree = evaluateNonary(op); } else if ((int)op < 200 && transform.childCount > 0) { var childShape = transform.GetChild(0).GetComponent <LFShape>(); if (childShape != null && childShape.isActiveAndEnabled) { tree = evaluateUnary(op, childShape.Evaluate()); } } else { var trees = new List <LFTree>(transform.childCount); for (var i = 0; i < transform.childCount; ++i) { var childShape = transform.GetChild(i).GetComponent <LFShape>(); if (childShape != null && childShape.isActiveAndEnabled) { trees.Add(childShape.Evaluate()); } } tree = evaluateNnary(op, trees.ToArray()); } localTransformHash = computeLocalTransformHash(); if (isRootNode && tree != null) { tree = LFMath.Transform(tree, transform.localToWorldMatrix); } else { tree = LFMath.Transform(tree, transform.parent.worldToLocalMatrix * transform.localToWorldMatrix); } LFContext.Active.RemoveTreeFromContext(tree); // (This prevents this node's tree from being disposed of.) } UnityEngine.Profiling.Profiler.EndSample(); return(tree); }
//Reference: https://github.com/libfive/libfive/blob/master/libfive/bind/csg.scm /// <summary>Returns the union of any number of shapes</summary> public static LFTree Union(params LFTree[] shapes) { LFTree unionedTree = shapes[0]; if (shapes.Length > 1) { for (int i = 1; i < shapes.Length; i++) { unionedTree = Min(unionedTree, shapes[i]); } } return(unionedTree); }
/// <summary>Subtracts any number of shapes from the first argument</summary> public static LFTree Difference(params LFTree[] shapes) { if (shapes.Length == 0) { Debug.LogError("Difference can't be called without arguments!"); } if (shapes.Length == 1) { return(shapes[0]); } LFTree[] subtractingShapes = new LFTree[shapes.Length - 1]; for (int i = 1; i < shapes.Length; i++) { subtractingShapes[i - 1] = shapes[i]; } return(Intersection(shapes[0], Inverse(Union(subtractingShapes)))); }
void GenerateMesh(Mesh meshToFill, bool sharpEdges = true) { using (LFContext.Active = new Context()) { float innerRadius = 0.6f + (Mathf.Sin(Time.time) * 0.05f); LFTree cylinder = LFMath.Cylinder(innerRadius, 2f, Vector3.back); LFTree toRender = LFMath.Difference( LFMath.Sphere(1f), cylinder, LFMath.ReflectXZ(cylinder), LFMath.ReflectYZ(cylinder)); toRender.RenderMesh(meshToFill, new Bounds(Vector3.zero, Vector3.one * 3.1f), resolution, 20f); if (sharpEdges) { meshToFill.RecalculateNormals(25f); } } }
LFTree evaluateUnary(LibFive_Operation op, LFTree tree) { if (tree != null) { if (op == LibFive_Operation.Transform) { return(tree); } else if (op == LibFive_Operation.Inverse) { return(-tree); } else if (op == LibFive_Operation.Mirror) { return(LFMath.SymmetricX(tree)); } else if (op == LibFive_Operation.Shell) { return(LFMath.Shell(tree, 0.025f)); } } return(this.tree); }
/// <summary>Returns the blend of two shapes</summary> public static LFTree Blend(LFTree a, LFTree b, float blendAmount = 0.5f) { return(Union(a, b, (Sqrt(Abs(a))) + (Sqrt(Abs(b))) - blendAmount)); }
/// <summary>Returns a shape that's the inverse of the input shape</summary> public static LFTree Inverse(LFTree shape) { return(-shape); }
public static LFTree nthRoot(LFTree first, LFTree second) { return(new LFTree(libfive.libfive_tree_binary((int)libfive_opcode.OP_NTH_ROOT, first, second))); }
/// <summary>Clip the given shape at the z origin, /// and duplicate the remaining shape reflected /// on the other side of the origin</summary> public static LFTree SymmetricZ(this LFTree t) { return(t.Remap(LFTree.x, LFTree.y, Abs(LFTree.z))); }
/// <summary>Creates a sphere</summary> public static LFTree Sphere(float radius, Vector3 center) { LFTree x = LFTree.x, y = LFTree.y, z = LFTree.z; return(Sqrt(Square(x - center.x) + Square(y - center.y) + Square(z - center.z)) - radius); }
///<summary>Adds an LFTree to this context (to be Disposed of when this is)</summary> public void AddTreeToContext(LFTree tree) { trees.Add(tree); }
public static LFTree NaNFill(LFTree first, LFTree second) { return(new LFTree(libfive.libfive_tree_binary((int)libfive_opcode.OP_NANFILL, first, second))); }
//Reference: https://github.com/libfive/libfive/blob/master/libfive/bind/transforms.scm /// <summary>Translates this shape</summary> public static LFTree Move(LFTree t, Vector3 translation) { return(t.Remap(LFTree.x - translation.x, LFTree.y - translation.y, LFTree.z - translation.z)); }
/// <summary>Returns a shell of a shape with the given offset</summary> public static LFTree Shell(LFTree t, float offset) { return(Abs(t) - offset); }
/// <summary>Extrudes a 2D shape on the xy plane along the z axis</summary> public static LFTree Extrude(LFTree a, float lowerZ, float upperZ) { LFTree z = LFTree.z; return(Max(a, Max(lowerZ - z, z - upperZ))); }
public static LFTree Compare(LFTree first, LFTree second) { return(new LFTree(libfive.libfive_tree_binary((int)libfive_opcode.OP_COMPARE, first, second))); }
public static LFTree Pow(LFTree first, LFTree second) { return(new LFTree(libfive.libfive_tree_binary((int)libfive_opcode.OP_POW, first, second))); }
public static LFTree Atan2(LFTree first, LFTree second) { return(new LFTree(libfive.libfive_tree_binary((int)libfive_opcode.OP_ATAN2, first, second))); }
/// <summary>Creates a sphere centered on the origin</summary> public static LFTree Circle(float radius) { LFTree x = LFTree.x, y = LFTree.y; return(Sqrt((Square(x)) + (Square(y))) - radius); }
public RenderJobPayload(ref LFTree tree) { unsafe { libFiveMeshPtr = (IntPtr *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <IntPtr>(), 4, Allocator.Persistent); } this.tree = tree; }
/// <summary>Reflect the given shape about the z origin or an optional offset"</summary> public static LFTree ReflectZ(this LFTree t, float offset = 0f) { return(t.Remap(LFTree.x, LFTree.y, (2f * offset) - LFTree.z)); }
/// <summary>Moves the given shape across the plane X=Z</summary> public static LFTree ReflectXZ(this LFTree t, float offset = 0f) { return(t.Remap(LFTree.z, LFTree.y, LFTree.x)); }
/// <summary>Clip the given shape at the x origin, /// and duplicate the remaining shape reflected /// on the other side of the origin</summary> public static LFTree SymmetricX(this LFTree t) { return(t.Remap(Abs(LFTree.x), LFTree.y, LFTree.z)); }
///<summary>Removes an LFTree from this context (so it is NOT Disposed when this context is)</summary> public void RemoveTreeFromContext(LFTree tree) { trees.Remove(tree); }
public static LFTree Reciporical(LFTree tree) { return(new LFTree(libfive.libfive_tree_unary((int)libfive_opcode.OP_RECIP, tree))); }