{
  "Name": "PerformanceCurve",
  "_id": "4014f606-0556-4e61-9bf2-9d4f99bbfab0",
  "Namespace": "lib.3d.modify._",
  "Description": "Visualizes the incoming value with a curve\r\n",
  "Inputs": [
    {
      "Name": "Code",
      "MetaInstanceID": "41e26e3c-ad56-4656-b434-273e201cd29e",
      "DefaultValue": {
        "Type": "Text",
        "Value": [
          "float4x4 objectToWorldMatrix;\r",
          "float4x4 worldToCameraMatrix;\r",
          "float4x4 cameraToObjectMatrix; // modelview inverse\r",
          "float4x4 projMatrix;\r",
          "float4x4 textureMatrix;\r",
          "\r",
          "\r",
          "struct PointLight\r",
          "{\r",
          "    float4 position;\r",
          "    float4 ambient;\r",
          "    float4 diffuse;\r",
          "    float4 specular;\r",
          "    float4 attenuation;\r",
          "};\r",
          "\r",
          "struct SpotLight\r",
          "{\r",
          "    float4 ambient;\r",
          "    float4 diffuse;\r",
          "    float4 specular;\r",
          "    float constantAttenuation;\r",
          "    float linearAttenuation;\r",
          "    float quadraticAttenuation;\r",
          "    float spotCutoff;\r",
          "    float spotCosCutoff;\r",
          "    float spotExponent;\r",
          "};\r",
          "\r",
          "cbuffer FogSettings\r",
          "{\r",
          "    float4 fogColor;\r",
          "    float fogStart;\r",
          "    float fogEnd;\r",
          "    float fogScale;\r",
          "}\r",
          "\r",
          "cbuffer MaterialBuffer\r",
          "{\r",
          "    float4 materialAmbient;\r",
          "    float4 materialDiffuse;\r",
          "    float4 materialSpecular;\r",
          "    float4 materialEmission;\r",
          "    float materialShininess;\r",
          "};\r",
          "\r",
          "\r",
          "cbuffer PointLightsBuffer\r",
          "{\r",
          "    int numPointLights;\r",
          "    PointLight pointLights[3];\r",
          "};\r",
          "\r",
          "\r",
          "Texture2D txDiffuse;\r",
          "\r",
          "SamplerState samLinear\r",
          "{\r",
          "    Filter = MIN_MAG_MIP_LINEAR;\r",
          "    AddressU = Wrap;\r",
          "    AddressV = Wrap;\r",
          "};\r",
          "\r",
          "\r",
          "struct VS_IN\r",
          "{\r",
          "    float4 pos : POSITION;\r",
          "    float3 normal : NORMAL;\r",
          "    float4 col : COLOR;\r",
          "    float2 texCoord : TEXCOORD0;\r",
          "    float3 tangent : TANGENT0;\r",
          "    float3 binormal : BINORMAL0;\r",
          "    float4 objToWorldRow0 : INSTANCE_OBJ_TO_WORLD_ROW0;\r",
          "    float4 objToWorldRow1 : INSTANCE_OBJ_TO_WORLD_ROW1;\r",
          "    float4 objToWorldRow2 : INSTANCE_OBJ_TO_WORLD_ROW2;\r",
          "    float4 objToWorldRow3 : INSTANCE_OBJ_TO_WORLD_ROW3;\r",
          "};\r",
          "\r",
          "\r",
          "struct PS_IN\r",
          "{\r",
          "    float4 pos : SV_POSITION;\r",
          "    float4 posInWorld  : WORLD_POS;\r",
          "    float3 normal : NORMAL;   \r",
          "    float2 texCoord : TEXCOORD0;\r",
          "    float4 vertexColor : COLOR;\r",
          "    float3 fragPosToCamPos : POS;\r",
          "    float fogFragCoord : FALLO;\r",
          "};\r",
          "\r",
          "\r",
          "float mod(float a, float b)\r",
          "{\r",
          "    return a - b*floor(a/b);\r",
          "}\r",
          "\r",
          "float3 mod(float3 a, float b)\r",
          "{\r",
          "    return a - b*floor(a/b);\r",
          "}\r",
          "\r",
          "\r",
          "\r",
          "//>>>> VS2\r",
          "PS_IN VS( VS_IN input )\r",
          "{\r",
          "    PS_IN output = (PS_IN)0;\r",
          "\r",
          "//    float4x4 objToWorldMatrix = objectToWorldMatrix;\r",
          "//    objToWorldMatrix[3] = input.objToWorldRow3;\r",
          "    float4x4 instanceToWorldMatrix = float4x4(input.objToWorldRow0,\r",
          "                                              input.objToWorldRow1,\r",
          "                                              input.objToWorldRow2,\r",
          "                                              input.objToWorldRow3);\r",
          "    output.posInWorld = mul(input.pos, instanceToWorldMatrix);\r",
          "    output.pos = mul(output.posInWorld, worldToCameraMatrix);\r",
          "    output.normal = mul(input.normal, (float3x3)instanceToWorldMatrix);\r",
          "    output.fogFragCoord = abs(output.pos.z / input.pos.w);\r",
          "    output.pos = mul(output.pos, projMatrix);\r",
          "    output.texCoord = mul(float4(input.texCoord, 0, 1), textureMatrix).xy;\r",
          "    output.fragPosToCamPos = normalize(mul(cameraToObjectMatrix[3], objectToWorldMatrix) - output.posInWorld);\r",
          "    output.vertexColor = input.col;\r",
          "      \r",
          "    return output;\r",
          "}\r",
          "//<<< VS\r",
          "\r",
          "float4 calcLightSource(float3 fragPosInWorld, int lightIdx, float3 cameraVector, float3 norm, float4 baseColor)\r",
          "{\r",
          "    float3 lightVector = pointLights[lightIdx].position - fragPosInWorld;\r",
          "    float dist = length(lightVector);\r",
          "    lightVector = normalize(lightVector);\r",
          "    float nxDir = max(0.0, dot(norm, lightVector));\r",
          "    float4 diffuse = pointLights[lightIdx].diffuse * nxDir;\r",
          "    float specularPower = 0.0;\r",
          "    if (nxDir > 0.0)\r",
          "    {\r",
          "        float3 r = reflect(-lightVector, norm);\r",
          "        float rl = max(0.0, dot(r, cameraVector));\r",
          "        specularPower = pow(rl, materialShininess);\r",
          "    }\r",
          "\r",
          "    float attenuation = 1.0 / (pointLights[lightIdx].attenuation.x +\r",
          "                               pointLights[lightIdx].attenuation.y * dist +\r",
          "                               pointLights[lightIdx].attenuation.z * dist * dist);\r",
          "    float4 color = materialAmbient * pointLights[lightIdx].ambient * attenuation +\r",
          "                   materialDiffuse * (diffuse * baseColor * attenuation) +\r",
          "                   materialSpecular * pointLights[lightIdx].specular * specularPower * attenuation * baseColor;\r",
          "\r",
          "    return color;\r",
          "}\r",
          "\r",
          "\r",
          "\r",
          "//>>>> PS\r",
          "float4 PS( PS_IN input ) : SV_Target\r",
          "{\r",
          "    float2 newTexCoords = input.texCoord;\r",
          "    float3 norm = normalize(input.normal);\r",
          "    float4 baseColor = txDiffuse.Sample(samLinear, newTexCoords);\r",
          "\r",
          "    float4 color = float4(0, 0, 0, 1);\r",
          "    for (int lightIdx = 0; lightIdx < numPointLights; ++lightIdx)\r",
          "    {\r",
          "        color += calcLightSource(input.posInWorld, lightIdx, input.fragPosToCamPos, norm, baseColor);\r",
          "    }\r",
          "    color += materialEmission*baseColor;\r",
          "\r",
          "    float fog = (fogEnd - input.fogFragCoord) * fogScale;\r",
          "    fog = clamp(fog, 0.0, 1.0);\r",
          "    return float4(lerp(fogColor.rgb, color.rgb, fog), materialDiffuse.a * baseColor.a);\r",
          "}\r",
          "//<<< PS\r",
          "\r",
          "technique10 Render\r",
          "{\r",
          "    pass P0\r",
          "    {\r",
          "        SetGeometryShader( 0 );\r",
          "        SetVertexShader( CompileShader( vs_4_0, VS() ) );\r",
          "        SetPixelShader( CompileShader( ps_4_0, PS() ) );\r",
          "    }\r",
          "} "
        ]
      },
      "MetaID": "c522a66e-3260-4692-b3e3-79fd0361fa3d",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "SceneInput",
      "MetaInstanceID": "82b325ac-aa6f-4cc8-b118-feb77d0be1d3",
      "DefaultValue": {
        "Type": "Scene",
        "Value": "Framefield.Core.Scene"
      },
      "MetaID": "79122951-7bc4-4c68-b085-866eab828248",
      "IsMultiInput": "True",
      "Relevance": "Required",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Count",
      "MetaInstanceID": "69e0e642-bf0c-4988-94a0-fdfc2685f45c",
      "DefaultValue": {
        "Type": "Float",
        "Value": "100"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Optional",
      "Description": "",
      "Min": "1",
      "Max": "100000",
      "Scale": "1",
      "ScaleType": "Linear",
      "EnumValues": []
    },
    {
      "Name": "Value",
      "MetaInstanceID": "5ac54356-84d2-4902-b7f2-58093965b039",
      "DefaultValue": {
        "Type": "Float",
        "Value": "10"
      },
      "MetaID": "3f76dee3-3897-44ac-82d6-25ce9f53a506",
      "IsMultiInput": "False",
      "Relevance": "Relevant",
      "Description": "",
      "Min": "-100000",
      "Max": "100000",
      "Scale": "0.1",
      "ScaleType": "Linear",
      "EnumValues": []
    }
  ],
  "Outputs": [
    {
      "Name": "SceneTransformOut",
      "MetaInstanceID": "8d8e468c-73e4-4821-bad6-c0cc54dc37f9",
      "MetaID": "79122951-7bc4-4c68-b085-866eab828248"
    }
  ],
  "OperatorParts": [
    {
      "MetaInstanceID": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea",
      "MetaID": "94a7e91f-48c8-41c1-bb95-e177c409f7ab",
      "Name": "PerformanceCurveFunc",
      "Version": "2b308a7a-3565-42be-a68d-5852b38bad09",
      "Type": "Scene",
      "IsMultiInput": "True",
      "Script": [
        "using System;",
        "using System.Collections.Generic;",
        "using System.Linq;",
        "using SharpDX;",
        "using SharpDX.Direct3D;",
        "using SharpDX.Direct3D11;",
        "using Framefield.Core.Rendering;",
        "using Buffer = SharpDX.Direct3D11.Buffer;",
        "",
        "namespace Framefield.Core.ID94a7e91f_48c8_41c1_bb95_e177c409f7ab",
        "{",
        "    public class Class_PerformanceCurve : FXSourceCodeFunction",
        "    {",
        "        #region Renderer",
        "        public class Renderer : BaseRenderer",
        "        {",
        "            public override void SetupEffect(OperatorPartContext context)",
        "            {",
        "                base.SetupEffect(context);",
        "                try",
        "                {",
        "                    SetupMaterialConstBuffer(context);",
        "                    SetupFogSettingsConstBuffer(context);",
        "                    SetupPointLightsConstBuffer(context);",
        "                }",
        "                catch (Exception e)",
        "                {",
        "                    Logger.Error(ParentFunc, \"Error building constant buffer: {0} - Source: {1}\", e.Message, e.Source);",
        "                }",
        "            }",
        "            public OperatorPart.Function ParentFunc {get;set;}            ",
        "        }",
        "        #endregion",
        "",
        "        public Class_PerformanceCurve()",
        "        {",
        "            _renderer = new Renderer(){ParentFunc = this};",
        "        }",
        "",
        "        public override void Dispose()",
        "        {",
        "            Utilities.DisposeObj(ref _renderer);",
        "            base.Dispose();",
        "        }",
        "",
        "        //>>> _inputids",
        "        private enum InputId",
        "        {",
        "            Code = 0,",
        "            SceneInput = 1,",
        "            Count = 2,",
        "            Value = 3",
        "        }",
        "        //<<< _inputids",
        "",
        "",
        "        private bool _firstEval = true;",
        "        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx)",
        "        {",
        "            //>>> _params",
        "            var Code = inputs[(int)InputId.Code].Eval(context).Text;",
        "            var SceneInput = inputs[(int)InputId.SceneInput];",
        "            var Count = inputs[(int)InputId.Count].Eval(context).Value;",
        "            var Value = inputs[(int)InputId.Value].Eval(context).Value;",
        "            //<<< _params        ",
        "            ",
        "            // Update Value List",
        "            var count = (int)Count;",
        "            ",
        "            if( count != _lastCount) {",
        "                _lastCount = count;",
        "                _values = new float[count];",
        "                _index= 0;",
        "            }",
        "            ",
        "            _values[_index] = Value;",
        "            _index = (_index + 1) % count;",
        "            ",
        "            if (SceneInput.Connections.Count == 0)",
        "            {",
        "                return context;",
        "            }",
        "",
        "            if (_firstEval)",
        "            {",
        "                for (int i = 0; i < NumCodes(); ++i)",
        "                    Compile(i);",
        "                _firstEval = false;",
        "                Changed = true;",
        "            }",
        "",
        "            var prevTransform = context.ObjectTWorld;",
        "",
        "            _meshCollector.Clear();",
        "            SceneInput.TraverseWithFunction(_meshCollector, null);",
        "            var meshSupplier = _meshCollector.CollectedOpPartFunctions.FirstOrDefault();",
        "            if (meshSupplier == null)",
        "            {",
        "                Logger.Error(this,\"Found no mesh supplier, have you forgotten to add an input?\");",
        "                return context;",
        "            }",
        "            var meshes = new List<Mesh>();",
        "            meshSupplier.AddMeshesTo(meshes);",
        "            if (meshes.Count != 1)",
        "            {",
        "                Logger.Error(this,\"Found more or less than 1 mesh\");",
        "                return context;",
        "            }",
        "            var instancedMesh = meshes[0];",
        "",
        "            // instance data buffer",
        "            const int instanceDataSize = 4*16; // float4x4",
        "            var numInstances = (int) Count;",
        "            var streamSize = numInstances * instanceDataSize;",
        "            if (_instanceDataBuffer == null || _instanceDataBuffer.Description.SizeInBytes != streamSize)",
        "            {",
        "                Utilities.DisposeObj(ref _instanceDataBuffer);",
        "                _instanceDataBuffer = new Buffer(context.D3DDevice, streamSize, ResourceUsage.Dynamic, BindFlags.VertexBuffer,",
        "                                                 CpuAccessFlags.Write, ResourceOptionFlags.None, instanceDataSize);",
        "            }",
        "",
        "            DataStream instanceDataStream;",
        "            context.D3DDevice.ImmediateContext.MapSubresource(_instanceDataBuffer, MapMode.WriteDiscard, MapFlags.None, out instanceDataStream);",
        "            using (instanceDataStream)",
        "            {",
        "                instanceDataStream.Position = 0;",
        "",
        "                for (var i = 0; i < numInstances; ++i)",
        "                {",
        "                    var v = _values[(_index + i) % count];",
        "                    ",
        "                    Vector3 t = new Vector3(i, 0.5f, 0);",
        "",
        "                    var scale = new Vector3(1, v, 1);",
        "                    ",
        "                    //Matrix rotation;",
        "                    Matrix transform = Matrix.Identity;",
        "                    ",
        "                                                                    ",
        "                    var tScale = Matrix.Scaling( scale.X, scale.Y, scale.Z);",
        "",
        "",
        "",
        "                    transform *= Matrix.Transformation(new Vector3(), new Quaternion(), new Vector3(1,1,1), new Vector3(), new Quaternion(), t);",
        "                    transform *= prevTransform; ",
        "                    transform= transform * tScale;",
        "",
        "                    instanceDataStream.Write(transform);",
        "                }",
        "            }",
        "            context.D3DDevice.ImmediateContext.UnmapSubresource(_instanceDataBuffer, 0);",
        "",
        "            var prevEffect = context.Effect;",
        "            var prevRenderer = context.Renderer;",
        "            context.Effect = _effect;",
        "            context.Renderer = _renderer;",
        "",
        "            try",
        "            {",
        "                _renderer.SetupEffect(context);",
        "",
        "                if (context.DepthStencilView != null)",
        "                    context.D3DDevice.ImmediateContext.OutputMerger.SetTargets(context.DepthStencilView, context.RenderTargetView);",
        "                else",
        "                    context.D3DDevice.ImmediateContext.OutputMerger.SetTargets(context.RenderTargetView);",
        "",
        "                if (context.BlendState != null)",
        "                {",
        "                    context.D3DDevice.ImmediateContext.OutputMerger.BlendState = context.BlendState;",
        "                }",
        "",
        "                if (context.DepthStencilState != null)",
        "                {",
        "                    context.D3DDevice.ImmediateContext.OutputMerger.DepthStencilState = context.DepthStencilState;",
        "                }",
        "",
        "                if (context.RasterizerState != null)",
        "                {",
        "                    context.D3DDevice.ImmediateContext.Rasterizer.State = context.RasterizerState;",
        "                }",
        "",
        "                var technique = _effect.GetTechniqueByIndex(0);",
        "                var pass = technique.GetPassByIndex(0);",
        "",
        "                context.D3DDevice.ImmediateContext.Rasterizer.SetViewport(context.Viewport);",
        "                context.D3DDevice.ImmediateContext.InputAssembler.InputLayout = new InputLayout(context.D3DDevice, pass.Description.Signature, _instanceDataInputElements);",
        "                context.D3DDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;",
        "                context.D3DDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new [] { instancedMesh.Vertices, _instanceDataBuffer}, new [] {76, instanceDataSize}, new [] {0,0} );",
        "",
        "                pass.Apply(context.D3DDevice.ImmediateContext);",
        "                context.D3DDevice.ImmediateContext.DrawInstanced(instancedMesh.NumTriangles*3, numInstances, 0, 0);",
        "            }",
        "            catch (Exception exception)",
        "            {",
        "                Logger.Error(this,\"Replicate2 - An error occured during evaluation: {0}\", exception.Message);",
        "            }",
        "",
        "            context.Effect = prevEffect;",
        "            context.Renderer = prevRenderer;",
        "",
        "            return context;",
        "        }",
        "",
        "",
        "        private float[] _values;",
        "        private int _lastCount = -1;",
        "        private int _index = 0;",
        "",
        "        private OperatorPart.CollectOpPartFunctionsOfType<Framefield.Core.OperatorPartTraits.IMeshSupplier> _meshCollector = new OperatorPart.CollectOpPartFunctionsOfType<Framefield.Core.OperatorPartTraits.IMeshSupplier>();",
        "        private Renderer _renderer;",
        "        private Buffer _instanceDataBuffer;",
        "        private InputElement[] _instanceDataInputElements = new []",
        "                                                                {",
        "                                                                    new InputElement(\"POSITION\", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 0, 0),",
        "                                                                    new InputElement(\"NORMAL\", 0, SharpDX.DXGI.Format.R32G32B32_Float, 16, 0),",
        "                                                                    new InputElement(\"COLOR\", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 28, 0),",
        "                                                                    new InputElement(\"TEXCOORD\", 0, SharpDX.DXGI.Format.R32G32_Float, 44, 0),",
        "                                                                    new InputElement(\"TANGENT\", 0, SharpDX.DXGI.Format.R32G32B32_Float, 52, 0),",
        "                                                                    new InputElement(\"BINORMAL\", 0, SharpDX.DXGI.Format.R32G32B32_Float, 64, 0),",
        "                                                                    new InputElement(\"INSTANCE_OBJ_TO_WORLD_ROW\", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 0,",
        "                                                                                     1, InputClassification.PerInstanceData, 1),",
        "                                                                    new InputElement(\"INSTANCE_OBJ_TO_WORLD_ROW\", 1, SharpDX.DXGI.Format.R32G32B32A32_Float, 16,",
        "                                                                                     1, InputClassification.PerInstanceData, 1),",
        "                                                                    new InputElement(\"INSTANCE_OBJ_TO_WORLD_ROW\", 2, SharpDX.DXGI.Format.R32G32B32A32_Float, 32,",
        "                                                                                     1, InputClassification.PerInstanceData, 1),",
        "                                                                    new InputElement(\"INSTANCE_OBJ_TO_WORLD_ROW\", 3, SharpDX.DXGI.Format.R32G32B32A32_Float, 48,",
        "                                                                                     1, InputClassification.PerInstanceData, 1),",
        "                                                                };",
        "    }",
        "}",
        "",
        ""
      ],
      "AdditionalAssemblies": []
    }
  ],
  "Operators": [],
  "Connections": [
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "41e26e3c-ad56-4656-b434-273e201cd29e",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "82b325ac-aa6f-4cc8-b118-feb77d0be1d3",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "69e0e642-bf0c-4988-94a0-fdfc2685f45c",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "5ac54356-84d2-4902-b7f2-58093965b039",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea"
    },
    {
      "SourceOp": "00000000-0000-0000-0000-000000000000",
      "SourceOpPart": "8f8a937e-0be6-40c2-b2a1-ce7831e7aaea",
      "TargetOp": "00000000-0000-0000-0000-000000000000",
      "TargetOpPart": "8d8e468c-73e4-4821-bad6-c0cc54dc37f9"
    }
  ]
}