Exemplo n.º 1
0
    private string GetShapeCode(SDFShape shape, string parentPosition)
    {
        Vector3 offset = shape.transform.localPosition;
        Vector3 up     = shape.transform.localRotation * Vector3.up;
        // Vector3 right = shape.transform.localRotation * Vector3.right;
        // Vector3 forward = shape.transform.localRotation * Vector3.forward;

        Vector3 parameters = shape.GetParameters();

        switch (shape.shapeType)
        {
        case SDFShape.ShapeType.Plane:
            return("dot(" + parentPosition + " - " + ConstructVariable(offset) + ", " + ConstructVariable(up) + ")");

        case SDFShape.ShapeType.FracturedPlane:
            //return "wsPos.y + (clamp(wsPos.x, 0.0, 2.0) * 0.05 + clamp(wsPos.z + .5, 0.0, 1.0) * .1)";
            return("frPlane(wsPos)");

        case SDFShape.ShapeType.Sphere:
            return("length(wsPos) - .5");

        case SDFShape.ShapeType.Cube:
            return("fBox(wsPos," + ConstructVariable(shape.GetParameters()) + ")");

        case SDFShape.ShapeType.Cylinder:
            return("fCylinder(wsPos, " + ConstructVariable(parameters.x) + "," + ConstructVariable(parameters.y) + ")");
        }

        return("0.0"); // Worst case
    }
Exemplo n.º 2
0
    private Vector3 GetShapeLocalScale(SDFShape shape)
    {
        if (shape.shapeType == SDFShape.ShapeType.Cube ||
            shape.shapeType == SDFShape.ShapeType.Cylinder)
        {
            return(Vector3.one);
        }

        return(shape.transform.localScale);
    }
Exemplo n.º 3
0
    private bool UseTransform(SDFShape shape)
    {
        switch (shape.shapeType)
        {
        case SDFShape.ShapeType.Plane:
            return(false);

        default:
            return(true);
        }
    }
Exemplo n.º 4
0
    private void BuildNodeTree(GameObject go, List <Node> nodeList, int depth)
    {
        if (!go.activeInHierarchy)
        {
            return;
        }

        SDFOperation op    = go.GetComponent <SDFOperation>();
        SDFShape     shape = go.GetComponent <SDFShape>();

        Vector3 scale = go.transform.localScale;

        if (shape)
        {
            scale = GetShapeLocalScale(shape);
        }

        Node node = new Node();

        node.transform            = Matrix4x4.TRS(go.transform.localPosition, go.transform.localRotation, scale).inverse;
        node.type                 = 0;
        node.depth                = depth;
        node.domainDistortionType = 0;
        node.domainDistortion     = Vector3.one;
        node.bias                 = 1f;

        if (op)
        {
            node.type                 = 0;
            node.parameters           = (int)op.operationType;
            node.domainDistortionType = (int)op.distortionType;
            node.domainDistortion     = op.domainRepeat; // For now...
            node.bias                 = 1f;
        }
        else if (shape)
        {
            node.type             = 1;
            node.parameters       = (int)shape.shapeType;
            node.domainDistortion = shape.GetParameters();
            node.bias             = shape.sdfBias;
        }

        nodeList.Add(node);

        foreach (Transform child in go.transform)
        {
            BuildNodeTree(child.gameObject, nodeList, depth + 1);
        }
    }
Exemplo n.º 5
0
    private string GenerateCodeForNode(Dictionary <int, bool> visitMap, Dictionary <int, bool> dVisitMap, Dictionary <SDFOperation, int> nodeMap, GameObject go, int depth, List <Matrix4x4> matrices)
    {
        string output = "";

        SDFOperation op = go.GetComponent <SDFOperation>();

        if (op)
        {
            if (verboseOutput)
            {
                output += GetTabs(depth + 1) + "{\n";
            }

            int    stackIndex        = nodeMap[op];
            bool   firstTime         = !visitMap.ContainsKey(stackIndex);
            string nodeStackPosition = GetStackPositionVariableName(stackIndex, firstTime);
            visitMap[stackIndex] = true;

            float defaultDistance = op.operationType == SDFOperation.OperationType.Intersection ? 1000f : 0f;

            // stack[stackTop].sdf = node.parameters == 2 ? 0.0 : 1000.0; // Make sure we initialize knowing the operation
            // output += GetTabs(depth + 2) + GetStackDistanceVariableName(stackIndex, true) + " = " + defaultDistance.ToString("0.00") + ";\n";

            Matrix4x4 localInverse = Matrix4x4.TRS(op.transform.localPosition, op.transform.localRotation, op.transform.localScale).inverse;

            if (localInverse != Matrix4x4.identity)
            {
                string sourcePosition = nodeStackPosition;

                if (depth > 0)
                {
                    int parentStackIndex = nodeMap[go.transform.parent.gameObject.GetComponent <SDFOperation>()];
                    sourcePosition = GetStackPositionVariableName(parentStackIndex);
                }

                if (op.transform.localRotation == Quaternion.identity)
                {
                    Vector4 offset = op.transform.localPosition;
                    offset.w = 0f;

                    if (verboseOutput)
                    {
                        output += GetTabs(depth + 2) + "// Optimized rotation\n";
                    }

                    output += GetTabs(depth + 2) + nodeStackPosition + " = ";

                    if (op.transform.localScale != Vector3.one)
                    {
                        Vector3 scale    = op.transform.localScale;
                        Vector4 invScale = new Vector4(1f / scale.x, 1f / scale.y, 1f / scale.z, 1f);
                        output += "(" + sourcePosition + " * " + ConstructVariable(invScale) + ")";
                    }
                    else
                    {
                        output += sourcePosition;
                    }

                    if (offset.magnitude > 0f)
                    {
                        output += " - " + ConstructVariable(offset) + ";\n";
                    }
                    else
                    {
                        output += ";\n";
                    }
                }
                else
                {
                    // Just use the matrix if there's rotation
                    string matrixVariable = "tr[" + matrices.Count + "]";
                    matrices.Add(localInverse);

                    if (transformArray)
                    {
                        output += GetTabs(depth + 2) + nodeStackPosition + " = " + MultiplyMatrixVector4(matrixVariable, sourcePosition) + ";\n";
                    }
                    else
                    {
                        output += GetTabs(depth + 2) + nodeStackPosition + " = " + MultiplyMatrixVector4(ConstructVariable(localInverse), sourcePosition) + ";\n";
                    }
                }
            }
            else
            {
                if (verboseOutput)
                {
                    output += GetTabs(depth + 2) + "// Transform optimized\n";
                }

                if (depth > 0)
                {
                    int parentStackIndex = nodeMap[go.transform.parent.gameObject.GetComponent <SDFOperation>()];
                    output += GetTabs(depth + 2) + nodeStackPosition + " = " + GetStackPositionVariableName(parentStackIndex) + ";\n";
                }
            }

            nodeStackPosition = GetStackPositionVariableName(stackIndex);

            if (op.distortionType != SDFOperation.DomainDistortion.None)
            {
                switch (op.distortionType)
                {
                case SDFOperation.DomainDistortion.Repeat3D:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xyz = domainRepeat(" + nodeStackPosition + ".xyz , " + ConstructVariable(op.domainRepeat) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatX:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".x = domainRepeat1D(" + nodeStackPosition + ".x , " + ConstructVariable(op.domainRepeat.x) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatY:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".y = domainRepeat1D(" + nodeStackPosition + ".y , " + ConstructVariable(op.domainRepeat.y) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".z = domainRepeat1D(" + nodeStackPosition + ".z , " + ConstructVariable(op.domainRepeat.z) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatPolarX:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".yz = pModPolar(" + nodeStackPosition + ".yz , " + ConstructVariable(op.domainRepeat.x) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatPolarY:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xz = pModPolar(" + nodeStackPosition + ".xz , " + ConstructVariable(op.domainRepeat.x) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.RepeatPolarZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xy = pModPolar(" + nodeStackPosition + ".xy , " + ConstructVariable(op.domainRepeat.x) + ");\n";
                    break;

                case SDFOperation.DomainDistortion.MirrorXYZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + " = abs(" + nodeStackPosition + ");\n";
                    break;

                case SDFOperation.DomainDistortion.MirrorXZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xz = abs(" + nodeStackPosition + ".xz) * " + ConstructVariable(new Vector2(-1f, 1f)) + ";\n";
                    break;

                case SDFOperation.DomainDistortion.MirrorX:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".x = abs(" + nodeStackPosition + ".x);\n";
                    break;

                case SDFOperation.DomainDistortion.MirrorY:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".y = abs(" + nodeStackPosition + ".y);\n";
                    break;

                case SDFOperation.DomainDistortion.MirrorZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".z = abs(" + nodeStackPosition + ".z);\n";
                    break;

                case SDFOperation.DomainDistortion.RotateDiscreteX:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xyz = rdX(" + nodeStackPosition + ".xyz);\n";
                    break;

                case SDFOperation.DomainDistortion.RotateDiscreteY:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xyz = rdY(" + nodeStackPosition + ".xyz);\n";
                    break;

                case SDFOperation.DomainDistortion.RotateDiscreteZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".xyz = rdZ(" + nodeStackPosition + ".xyz);\n";
                    break;

                case SDFOperation.DomainDistortion.FlipX:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".x = -" + nodeStackPosition + ".x;\n";
                    break;

                case SDFOperation.DomainDistortion.FlipY:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".y = -" + nodeStackPosition + ".y;\n";
                    break;

                case SDFOperation.DomainDistortion.FlipZ:
                    output += GetTabs(depth + 2) + nodeStackPosition + ".z = -" + nodeStackPosition + ".z;\n";
                    break;
                }
            }

            bool first               = true;
            bool carryOverFirstOp    = false;
            int  carryOverOpIndex    = -1;
            bool distanceEstablished = false;

            foreach (Transform child in go.transform)
            {
                GameObject childGO = child.gameObject;

                if (!childGO.activeInHierarchy)
                {
                    continue;
                }

                int currentIndex = stackIndex;

                if (carryOverFirstOp)
                {
                    currentIndex = carryOverOpIndex;
                }

                if (childGO.GetComponent <SDFOperation>())
                {
                    output += GenerateCodeForNode(visitMap, dVisitMap, nodeMap, childGO, depth + 1, matrices);
                    int childStackIndex = nodeMap[childGO.GetComponent <SDFOperation>()];

                    if (first)
                    {
                        carryOverFirstOp = true;
                        carryOverOpIndex = childStackIndex;

                        if (verboseOutput)
                        {
                            output += GetTabs(depth + 2) + "// Optimized first operation carry over\n";
                        }
                    }
                    else
                    {
                        output += GetTabs(depth + 2) + GetStackDistanceVariableName(stackIndex, !distanceEstablished) + " = ";
                        output += GetOperationCode((int)op.operationType, GetStackDistanceVariableName(currentIndex), GetStackDistanceVariableName(childStackIndex)) + ";\n";

                        carryOverFirstOp    = false;
                        distanceEstablished = true;
                    }
                }
                else if (childGO.GetComponent <SDFShape>())
                {
                    SDFShape shape     = childGO.GetComponent <SDFShape>();
                    string   shapeCode = GetShapeCode(shape, nodeStackPosition + ".xyz");

                    if (shape.sdfBias != 1f)
                    {
                        shapeCode = "(" + shapeCode + "*" + ConstructVariable(shape.sdfBias) + ")";
                    }

                    if (UseTransform(shape))
                    {
                        Matrix4x4 localShapeTransform = GetLocalTransform(shape);

                        if (localShapeTransform == Matrix4x4.identity)
                        {
                            if (verboseOutput)
                            {
                                output += GetTabs(depth + 2) + "// Shape transform optimized\n";
                            }

                            output += GetTabs(depth + 2) + "wsPos = " + nodeStackPosition + ".xyz;\n";
                        }
                        else
                        {
                            if (shape.transform.localRotation == Quaternion.identity)
                            {
                                Vector3 offset = shape.transform.localPosition;

                                if (verboseOutput)
                                {
                                    output += GetTabs(depth + 2) + "// Shape optimized rotation\n";
                                }

                                output += GetTabs(depth + 2) + "wsPos = ";

                                Vector3 scale = GetShapeLocalScale(shape);
                                if (scale != Vector3.one)
                                {
                                    Vector3 invScale = new Vector3(1f / scale.x, 1f / scale.y, 1f / scale.z);
                                    output += "( " + nodeStackPosition + ".xyz * " + ConstructVariable(invScale) + ")";
                                }
                                else
                                {
                                    output += nodeStackPosition + ".xyz";
                                }

                                if (offset.magnitude > 0f)
                                {
                                    output += " - " + ConstructVariable(offset) + ";\n";
                                }
                                else
                                {
                                    output += ";\n";
                                }
                            }
                            else
                            {
                                Matrix4x4 localShapeInverse = localShapeTransform.inverse;
                                string    matrixVariable    = "tr[" + matrices.Count + "]";
                                matrices.Add(localShapeInverse);

                                if (transformArray)
                                {
                                    output += GetTabs(depth + 2) + "wsPos = " + MultiplyMatrixVector4(matrixVariable, nodeStackPosition) + ".xyz;\n";
                                }
                                else
                                {
                                    output += GetTabs(depth + 2) + "wsPos = " + MultiplyMatrixVector4(ConstructVariable(localShapeInverse), nodeStackPosition) + ".xyz;\n";
                                }
                            }
                        }
                    }

                    output += GetTabs(depth + 2) + GetStackDistanceVariableName(stackIndex, !distanceEstablished) + " = ";
                    distanceEstablished = true;

                    if (first)
                    {
                        output += shapeCode + ";\n";
                    }
                    else
                    {
                        output += GetOperationCode((int)op.operationType, GetStackDistanceVariableName(currentIndex), shapeCode) + ";\n";
                    }

                    carryOverFirstOp = false;
                }
                else
                {
                    Debug.LogError("Something that is not an op or a shape is in the hierarchy! " + childGO.name, childGO);
                }

                first = false;
            }

            // If we're still carrying over, but finished this node...
            if (carryOverFirstOp)
            {
                if (verboseOutput)
                {
                    output += GetTabs(depth + 2) + "// Carrying over node with single child \n";
                }

                output += GetTabs(depth + 2) + GetStackDistanceVariableName(stackIndex, true) + " = " + GetStackDistanceVariableName(carryOverOpIndex) + ";\n";
            }

            if (verboseOutput)
            {
                output += GetTabs(depth + 1) + "}\n";
            }
        }

        return(output);
    }
Exemplo n.º 6
0
 private Matrix4x4 GetLocalTransform(SDFShape shape)
 {
     return(Matrix4x4.TRS(shape.transform.localPosition, shape.transform.localRotation, GetShapeLocalScale(shape)));
 }