Name
*
Code
{"properties":{"frame":0,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/orthographicCamera1","versions":{"polygonjs":"1.5.85"}},"root":{"type":"root","nodes":{"geo1":{"type":"geo","nodes":{"plane1":{"type":"plane","params":{"size":[10,10]}},"plane2":{"type":"plane","params":{"useSegmentsCount":true,"direction":[0,0,1]}},"copy1":{"type":"copy","params":{"copyAttributes":1,"attributesToCopy":"id"},"inputs":["transform1","attribId1"]},"MAT":{"type":"materialsNetwork","nodes":{"meshBasicBuilder_INSTANCES":{"type":"meshBasicBuilder","nodes":{"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"vec4ToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform"},"param1":{"type":"param","params":{"name":"index"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToInt1":{"type":"floatToInt","params":{"float":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"float","node":"round1","output":"val"}]},"round1":{"type":"round","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"texture1":{"type":"texture","params":{"paramName":"texture_01","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture2":{"type":"texture","params":{"paramName":"texture_02","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture3":{"type":"texture","params":{"paramName":"texture_03","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"multAdd1":{"type":"multAdd","params":{"value":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"preAdd":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"vector2","default_value":[1,1],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":[1,-1]},"postAdd":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"uv"}],"connection_points":{"in":[{"name":"value","type":"vec2"},{"name":"preAdd","type":"vec2"},{"name":"mult","type":"vec2"},{"name":"postAdd","type":"vec2"}],"out":[{"name":"val","type":"vec2"}]}},"switch1":{"type":"switch","params":{"index":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in0":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in1":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in2":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in3":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in4":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in5":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in6":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in7":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in8":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in9":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in10":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in11":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":13,"inputs":[{"index":0,"inputName":"index","node":"floatToInt1","output":"int"},{"index":1,"inputName":"in0","node":"texture_black","output":"rgba"},{"index":2,"inputName":"in1","node":"texture1","output":"rgba"},{"index":3,"inputName":"in2","node":"texture2","output":"rgba"},{"index":4,"inputName":"in3","node":"texture3","output":"rgba"},{"index":5,"inputName":"in4","node":"texture4","output":"rgba"},{"index":6,"inputName":"in5","node":"texture5","output":"rgba"},{"index":7,"inputName":"in6","node":"texture6","output":"rgba"},{"index":8,"inputName":"in7","node":"texture7","output":"rgba"},{"index":9,"inputName":"in8","node":"texture8","output":"rgba"},{"index":10,"inputName":"in9","node":"texture9","output":"rgba"},{"index":11,"inputName":"in10","node":"texture10","output":"rgba"}],"connection_points":{"in":[{"name":"index","type":"int"},{"name":"in0","type":"vec4"},{"name":"in1","type":"vec4"},{"name":"in2","type":"vec4"},{"name":"in3","type":"vec4"},{"name":"in4","type":"vec4"},{"name":"in5","type":"vec4"},{"name":"in6","type":"vec4"},{"name":"in7","type":"vec4"},{"name":"in8","type":"vec4"},{"name":"in9","type":"vec4"},{"name":"in10","type":"vec4"},{"name":"in11","type":"vec4"}],"out":[{"name":"val","type":"vec4"}]}},"vec4ToVec3_1":{"type":"vec4ToVec3","params":{"vec4":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec4","node":"switch1","output":"val"}]},"attribute1":{"type":"attribute","params":{"name":"state"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":10},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"texture_black":{"type":"texture","params":{"paramName":"texture_black"}},"texture4":{"type":"texture","params":{"paramName":"texture_04","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture5":{"type":"texture","params":{"paramName":"texture_05","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture6":{"type":"texture","params":{"paramName":"texture_06","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture7":{"type":"texture","params":{"paramName":"texture_07","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture8":{"type":"texture","params":{"paramName":"texture_08","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture9":{"type":"texture","params":{"paramName":"texture_09","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture10":{"type":"texture","params":{"paramName":"texture_10","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]}},"params":{"index":{"type":"float","default_value":0,"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":-1,"overriden_options":{"callback":"{}"}},"texture_01":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_01","overriden_options":{"callback":"{}"}},"texture_02":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_02","overriden_options":{"callback":"{}"}},"texture_03":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_03","overriden_options":{"callback":"{}"}},"texture_black":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/color_black","overriden_options":{"callback":"{}"}},"texture_04":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_04","overriden_options":{"callback":"{}"}},"texture_05":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_05","overriden_options":{"callback":"{}"}},"texture_06":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_06","overriden_options":{"callback":"{}"}},"texture_07":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_07","overriden_options":{"callback":"{}"}},"texture_08":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_08","overriden_options":{"callback":"{}"}},"texture_09":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_09","overriden_options":{"callback":"{}"}},"texture_10":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_10","overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"blendColor":0,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","blendColor":0,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","blendColor":0},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","blendColor":0,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}}}},"COP":{"type":"copNetwork","nodes":{"text_01":{"type":"text","params":{"text":"01","resolution":[128,128],"fontSize":75}},"text_02":{"type":"text","params":{"text":"02","resolution":[128,128],"fontSize":75}},"text_03":{"type":"text","params":{"text":"03","resolution":[128,128],"fontSize":75}},"text_04":{"type":"text","params":{"text":"04","resolution":[128,128],"fontSize":75}},"text_05":{"type":"text","params":{"text":"05","resolution":[128,128],"fontSize":75}},"text_06":{"type":"text","params":{"text":"06","resolution":[128,128],"fontSize":75}},"text_07":{"type":"text","params":{"text":"07","resolution":[128,128],"fontSize":75}},"text_08":{"type":"text","params":{"text":"08","resolution":[128,128],"fontSize":75}},"text_09":{"type":"text","params":{"text":"09","resolution":[128,128],"fontSize":75}},"text_10":{"type":"text","params":{"text":"10","resolution":[128,128],"fontSize":75}},"color_black":{"type":"color","params":{"resolution":[128,128],"color":[0,0,0]}}}},"transform1":{"type":"transform","inputs":["plane2"]},"instance1":{"type":"instance","params":{"material":"../MAT/meshBasicBuilder_INSTANCES"},"inputs":["transform1","attribId1"]},"actorInstance1":{"type":"actorInstance","nodes":{"onTick1":{"type":"onTick"},"param1":{"type":"param","params":{"name":"hoveredId","type":3},"connection_points":{"in":[],"out":[{"name":"val","type":"int","isArray":false}]}},"setInstanceAttribute1":{"type":"setInstanceAttribute","params":{"attribName":{"overriden_options":{}},"ptnum":{"overriden_options":{}},"lerp":{"overriden_options":{}},"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":6,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"attribName","node":"constant1","output":"val"},null,{"index":5,"inputName":"val","node":"clamp1","output":"clamped"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}]}},"getInstanceAttribute2":{"type":"getInstanceAttribute","params":{"ptnum":{"type":"integer","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"attribName":{"type":"string","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[null,null,{"index":2,"inputName":"attribName","node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false}],"out":[{"name":"ptnum","type":"int","isArray":false},{"name":"val","type":"float","isArray":false}]}},"constant1":{"type":"constant","params":{"type":4,"string":"state"},"connection_points":{"in":[],"out":[{"name":"val","type":"string","isArray":false}]}},"add2":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add3":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"add0","node":"getInstanceAttribute2","output":"val"},{"index":1,"inputName":"add1","node":"constant2","output":"val"},{"index":2,"inputName":"add2","node":"twoWaySwitch1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float","isArray":false},{"name":"add1","type":"float","isArray":false},{"name":"add2","type":"float","isArray":false},{"name":"add3","type":"float","isArray":false}],"out":[{"name":"sum","type":"float","isArray":false}]}},"constant2":{"type":"constant","params":{"float":-0.05},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"getInstanceProperty2":{"type":"getInstanceProperty"},"compare1":{"type":"compare","params":{"test":0,"value0":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"param1","output":"val"},{"index":1,"inputName":"value1","node":"getInstanceProperty2","output":"ptnum"}],"connection_points":{"in":[{"name":"value0","type":"int","isArray":false},{"name":"value1","type":"int","isArray":false}],"out":[{"name":"val","type":"boolean","isArray":false}]}},"twoWaySwitch1":{"type":"twoWaySwitch","params":{"condition":{"type":"boolean","default_value":false,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"ifTrue":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"ifFalse":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"condition","node":"compare1","output":"val"},{"index":1,"inputName":"ifTrue","node":"constant3","output":"val"},{"index":2,"inputName":"ifFalse","node":"constant4","output":"val"}],"connection_points":{"in":[{"name":"condition","type":"boolean","isArray":false},{"name":"ifTrue","type":"float","isArray":false},{"name":"ifFalse","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"constant3":{"type":"constant","params":{"float":1},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"clamp1":{"type":"clamp","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"min":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"val","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"val","type":"float","isArray":false},{"name":"min","type":"float","isArray":false},{"name":"max","type":"float","isArray":false}],"out":[{"name":"clamped","type":"float","isArray":false}]}},"constant4":{"type":"constant","connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}}},"params":{"hoveredId":{"type":"integer","default_value":0,"options":{"spare":true,"computeOnDirty":true,"cook":false},"raw_input":-1,"overriden_options":{"callback":"{}"}}},"inputs":["attribCreate1"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["getActorNodeParamValue","getPointIndex","getPointAttributeNumber","addNumber","clamp","mathFloat_3","globalsTime","globalsTimeDelta","setPointAttributeNumber","setPointIndex"],"serializedParamConfigs":[{"type":"integer","name":"hoveredId","defaultValue":0,"uniformName":"v_POLY_param1_val"}],"eventDatas":[]}},"attribId1":{"type":"attribId","params":{"idn":0},"inputs":["plane1"]},"merge1":{"type":"merge","inputs":["transform2","actorInstance1"],"flags":{"display":true}},"attribCreate1":{"type":"attribCreate","params":{"name":"state"},"inputs":["instance1"]},"transform2":{"type":"transform","params":{"applyOn":1,"t":[0,-1,0]},"inputs":["actor1"]},"actor1":{"type":"actor","nodes":{"constant1":{"type":"constant","params":{"type":4,"string":"id"},"connection_points":{"in":[],"out":[{"name":"val","type":"string","isArray":false}]}},"setParam1":{"type":"setParam","params":{"Param":{"type":"param_path","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},{"index":1,"inputName":"Param","node":"getParam1","output":"Param"},null,{"index":3,"inputName":"val","node":"getIntersectionAttribute1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"getParam1":{"type":"getParam","params":{"Param":"/geo1/actorInstance1/hoveredId"}},"getIntersectionAttribute1":{"type":"getIntersectionAttribute","params":{"attribName":{"type":"string","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"notFoundValue":{"type":"float","default_value":-1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"Intersection","node":"rayIntersectObject1","output":"Intersection"},{"index":1,"inputName":"attribName","node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"Intersection","type":"Intersection","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"notFoundValue","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectObject1":{"type":"rayIntersectObject","maxInputsCount":3,"inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"}]},"onTick1":{"type":"onTick"}},"inputs":["merge2"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["globalsRayFromCursor","rayIntersectObject3D","getIntersectionAttributeNumberInterpolated","globalsTime","globalsTimeDelta","getParam","setParamFloat"],"serializedParamConfigs":[],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}},"merge2":{"type":"merge","params":{"compact":1},"inputs":["attribPromote1"]},"attribPromote1":{"type":"attribPromote","params":{"classFrom":3,"classTo":0,"name":"id"},"inputs":["copy1"]}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}},"cameras":{"type":"geo","nodes":{"perspectiveCamera1":{"type":"perspectiveCamera","params":{"position":[3.3,3.3,3.3]}},"cameraControls1":{"type":"cameraControls","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[-0.8076651964617726,0.4281695890044879,-0.08427249496432923]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera1"]},"orthographicCamera1":{"type":"orthographicCamera","params":{"size":11}},"merge1":{"type":"merge","inputs":["cameraControls1","transform1"],"flags":{"display":true}},"transform1":{"type":"transform","params":{"applyOn":1,"t":[0,1.8,0],"r":[-90,0,0]},"inputs":["orthographicCamera1"]}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}}},"params":{"mainCameraPath":"/cameras/cameras:sopGroup/orthographicCamera1"}},"ui":{"nodes":{"geo1":{"pos":[-50,-350],"nodes":{"plane1":{"pos":[100,0]},"plane2":{"pos":[-300,0]},"copy1":{"pos":[-300,300]},"MAT":{"pos":[-550,300],"nodes":{"meshBasicBuilder_INSTANCES":{"pos":[0,-200],"nodes":{"globals1":{"pos":[-600,-50]},"output1":{"pos":[650,-100]},"instanceTransform1":{"pos":[300,-100]},"param1":{"pos":[-350,0]},"floatToInt1":{"pos":[-150,0]},"round1":{"pos":[-250,0]},"texture1":{"pos":[-150,300]},"texture2":{"pos":[-150,450]},"texture3":{"pos":[-150,600]},"multAdd1":{"pos":[-450,400]},"switch1":{"pos":[150,250]},"vec4ToVec3_1":{"pos":[300,250]},"attribute1":{"pos":[-350,-150]},"multAdd2":{"pos":[-250,-150]},"texture_black":{"pos":[-150,150]},"texture4":{"pos":[-150,750]},"texture5":{"pos":[-150,900]},"texture6":{"pos":[-150,1050]},"texture7":{"pos":[-150,1200]},"texture8":{"pos":[-150,1350]},"texture9":{"pos":[-150,1500]},"texture10":{"pos":[-150,1700]}}}}},"COP":{"pos":[-550,450],"nodes":{"text_01":{"pos":[-200,-200]},"text_02":{"pos":[-200,-100]},"text_03":{"pos":[-200,0]},"text_04":{"pos":[-200,100]},"text_05":{"pos":[-200,200]},"text_06":{"pos":[-200,300]},"text_07":{"pos":[-200,400]},"text_08":{"pos":[-200,500]},"text_09":{"pos":[-200,600]},"text_10":{"pos":[-200,700]},"color_black":{"pos":[-200,-350]}}},"transform1":{"pos":[-300,100]},"instance1":{"pos":[100,300]},"actorInstance1":{"pos":[100,800],"selection":["clamp1"],"nodes":{"onTick1":{"pos":[100,100]},"param1":{"pos":[-600,600]},"setInstanceAttribute1":{"pos":[450,150]},"getInstanceAttribute2":{"pos":[-100,300]},"constant1":{"pos":[-300,150]},"add2":{"pos":[100,300]},"constant2":{"pos":[-100,400]},"getInstanceProperty2":{"pos":[-600,750]},"compare1":{"pos":[-350,650]},"twoWaySwitch1":{"pos":[-50,650]},"constant3":{"pos":[-200,750]},"clamp1":{"pos":[250,300]},"constant4":{"pos":[-200,850]}}},"attribId1":{"pos":[100,100]},"merge1":{"pos":[-150,1050]},"attribCreate1":{"pos":[100,550]},"transform2":{"pos":[-300,850]},"actor1":{"pos":[-300,700],"nodes":{"constant1":{"pos":[-400,-100]},"setParam1":{"pos":[100,-400]},"getParam1":{"pos":[-100,-450]},"getIntersectionAttribute1":{"pos":[-200,-250]},"rayFromCursor1":{"pos":[-550,-250]},"rayIntersectObject1":{"pos":[-400,-250]},"onTick1":{"pos":[-100,-550]}}},"merge2":{"pos":[-300,550]},"attribPromote1":{"pos":[-300,400]}}},"cameras":{"pos":[-50,-150],"nodes":{"perspectiveCamera1":{"pos":[0,-50]},"cameraControls1":{"pos":[0,150],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"orthographicCamera1":{"pos":[200,-50]},"merge1":{"pos":[100,300]},"transform1":{"pos":[200,100]}}}}},"shaders":{"/geo1/MAT/meshBasicBuilder_INSTANCES":{"vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"}},"jsFunctionBodies":{"/geo1/actorInstance1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /geo1/actorInstance1/param1\n\tv_POLY_param1_val = computed(() => getActorNodeParamValue(\"hoveredId\"));\n\n\t// /geo1/actorInstance1/getInstanceProperty2\n\tv_POLY_getInstanceProperty2_ptnum = computed(() => getPointIndex(this.object3D));\n\n\t// /geo1/actorInstance1/getInstanceAttribute2\n\tv_POLY_getInstanceAttribute2_val = computed(() =>\n\t\tgetPointAttributeNumber(this.object3D, getPointIndex(this.object3D), this.v_POLY_constant1_val.value, 0.0)\n\t);\n\n\t// /geo1/actorInstance1/compare1\n\tv_POLY_compare1_val = computed(() => this.v_POLY_param1_val.value == this.v_POLY_getInstanceProperty2_ptnum.value);\n\n\t// /geo1/actorInstance1/twoWaySwitch1\n\tv_POLY_twoWaySwitch1_val = computed(() =>\n\t\tthis.v_POLY_compare1_val.value ? this.v_POLY_constant3_val.value : this.v_POLY_constant4_val.value\n\t);\n\n\t// /geo1/actorInstance1/add2\n\tv_POLY_add2_sum = computed(() =>\n\t\taddNumber(\n\t\t\tthis.v_POLY_getInstanceAttribute2_val.value,\n\t\t\tthis.v_POLY_constant2_val.value,\n\t\t\tthis.v_POLY_twoWaySwitch1_val.value,\n\t\t\t0.0\n\t\t)\n\t);\n\n\t// /geo1/actorInstance1/clamp1\n\tv_POLY_clamp1_clamped = computed(() => mathFloat_3(clamp, this.v_POLY_add2_sum.value, 0.0, 1.0));\n\n\t// /geo1/actorInstance1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /geo1/actorInstance1/constant1\n\tv_POLY_constant1_val = { value: \"state\" };\n\n\t// /geo1/actorInstance1/constant2\n\tv_POLY_constant2_val = { value: -0.05 };\n\n\t// /geo1/actorInstance1/constant3\n\tv_POLY_constant3_val = { value: 1.0 };\n\n\t// /geo1/actorInstance1/constant4\n\tv_POLY_constant4_val = { value: 0.0 };\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /geo1/actorInstance1/onTick1\n\tonTick1() {\n\t\tconst pointsCount = pointsCountFromObject(this.object3D);\n\t\tfor (let i = 0; i < pointsCount; i++) {\n\t\t\tsetPointIndex(this.object3D, i);\n\t\t\tthis.setInstanceAttribute1(0);\n\t\t}\n\t\tif (this.object3D.isMesh) {\n\t\t\tcorePrimitiveClassFactory(this.object3D).computeVertexNormalsIfAttributeVersionChanged(this.object3D.geometry);\n\t\t}\n\t}\n\n\t// /geo1/actorInstance1/setInstanceAttribute1\n\tsetInstanceAttribute1() {\n\t\tsetPointAttributeNumber(\n\t\t\tthis.object3D,\n\t\t\tthis.v_POLY_constant1_val.value,\n\t\t\tgetPointIndex(this.object3D),\n\t\t\tthis.v_POLY_clamp1_clamped.value,\n\t\t\t1.0\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n","/geo1/actor1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /geo1/actor1/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /geo1/actor1/rayIntersectObject1\n\tv_POLY_rayIntersectObject1_Intersection = computed(() =>\n\t\trayIntersectObject3D(this.v_POLY_rayFromCursor1_Ray.value, this.object3D, false)\n\t);\n\n\t// /geo1/actor1/getIntersectionAttribute1\n\tv_POLY_getIntersectionAttribute1_val = computed(() =>\n\t\tgetIntersectionAttributeNumberInterpolated(\n\t\t\tthis.v_POLY_rayIntersectObject1_Intersection.value,\n\t\t\tthis.v_POLY_constant1_val.value,\n\t\t\t-1.0\n\t\t)\n\t);\n\n\t// /geo1/actor1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /geo1/actor1/getParam1\n\tv_POLY_getParam1_Param = computed(() => getParam(\"/geo1/actorInstance1/hoveredId\"));\n\n\t// /geo1/actor1/constant1\n\tv_POLY_constant1_val = { value: \"id\" };\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /geo1/actor1/onTick1\n\tonTick1() {\n\t\tthis.setParam1(0);\n\t}\n\n\t// /geo1/actor1/setParam1\n\tsetParam1() {\n\t\tsetParamFloat(this.v_POLY_getParam1_Param.value, this.v_POLY_getIntersectionAttribute1_val.value, 1.0);\n\t}\n}\nreturn CustomActorEvaluator;\n"}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5543217692883486,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/orthographicCamera1","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false}}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":117.1621250663248,"y":-575.4470504744457},"zoom":0.6093359344859172},"history":{"2":{"position":{"x":-12.780563525646556,"y":239.7887660468523},"zoom":1.0222221069335933},"36":{"position":{"x":117.1621250663248,"y":-575.4470504744457},"zoom":0.6093359344859172},"321":{"position":{"x":5.74328178237036,"y":-457.79502309725274},"zoom":0.5353359344859171},"412":{"position":{"x":107.6996088109913,"y":189.14935283102426},"zoom":0.683335934485917},"1008":{"position":{"x":-46.95795827084893,"y":-570.3089819978406},"zoom":0.6273359344859172},"1165":{"position":{"x":-356.77193535554,"y":291.7266725012432},"zoom":0.725222106933593},"1216":{"position":{"x":36.371093771145816,"y":-155.42727161561945},"zoom":0.7852221069335931},"1702":{"position":{"x":16.527474846140308,"y":-312.3879477135959},"zoom":0.7641700061535222},"1765":{"position":{"x":-94.31726224595874,"y":85.63923750315413},"zoom":0.6462221069335929},"2827":{"position":{"x":75.37426604173098,"y":-324.07957912196724},"zoom":0.6146333401705797},"3207":{"position":{"x":-374.3653564097047,"y":-306.97185264043253},"zoom":0.6568023410373257},"3549":{"position":{"x":-116.48043097796263,"y":-421.30163545274604},"zoom":0.668222106933593},"3619":{"position":{"x":-108.02833082020646,"y":-197.1553548008036},"zoom":1.018222106933593},"3712":{"position":{"x":50,"y":-50},"zoom":0.8953359344859174},"3866":{"position":{"x":0,"y":0},"zoom":0.8953359344859174},"4196":{"position":{"x":70.37157531288841,"y":30.905426202229414},"zoom":0.8663359344859174},"4468":{"position":{"x":-11.983749257659213,"y":-3.6203398606522796},"zoom":0.7273359344859173}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/geo1","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/geo1/MAT","/geo1","/geo1/actorInstance1","/geo1","/geo1/MAT","/geo1/MAT/meshBasicBuilder_INSTANCES","/geo1/MAT","/geo1","/geo1/actorInstance1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actorInstance1","/geo1"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":19,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"checkRemoteAssetsUse":true,"minimizeFilesCount":false},"paramsModal":[]}
Used nodes
cop/color;cop/text;event/cameraOrbitControls;mat/meshBasicBuilder;obj/geo;sop/actor;sop/actorInstance;sop/attribCreate;sop/attribId;sop/attribPromote;sop/cameraControls;sop/copNetwork;sop/copy;sop/instance;sop/materialsNetwork;sop/merge;sop/orthographicCamera;sop/perspectiveCamera;sop/plane;sop/transform
Used operations
Used modules
Used assemblers
GL_MESH_BASIC;JS_ACTOR
Used integrations
[]
Used assets
Nodes map
{"/geo1":"obj/geo","/geo1/plane1":"sop/plane","/geo1/plane2":"sop/plane","/geo1/copy1":"sop/copy","/geo1/MAT":"sop/materialsNetwork","/geo1/MAT/meshBasicBuilder_INSTANCES":"mat/meshBasicBuilder","/geo1/COP":"sop/copNetwork","/geo1/COP/text_01":"cop/text","/geo1/COP/text_02":"cop/text","/geo1/COP/text_03":"cop/text","/geo1/COP/text_04":"cop/text","/geo1/COP/text_05":"cop/text","/geo1/COP/text_06":"cop/text","/geo1/COP/text_07":"cop/text","/geo1/COP/text_08":"cop/text","/geo1/COP/text_09":"cop/text","/geo1/COP/text_10":"cop/text","/geo1/COP/color_black":"cop/color","/geo1/transform1":"sop/transform","/geo1/instance1":"sop/instance","/geo1/actorInstance1":"sop/actorInstance","/geo1/attribId1":"sop/attribId","/geo1/merge1":"sop/merge","/geo1/attribCreate1":"sop/attribCreate","/geo1/transform2":"sop/transform","/geo1/actor1":"sop/actor","/geo1/merge2":"sop/merge","/geo1/attribPromote1":"sop/attribPromote","/cameras":"obj/geo","/cameras/perspectiveCamera1":"sop/perspectiveCamera","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/orthographicCamera1":"sop/orthographicCamera","/cameras/merge1":"sop/merge","/cameras/transform1":"sop/transform"}
Js version
Editor version
Engine version
Name
*
Code
{"properties":{"frame":0,"maxFrame":600,"maxFrameLocked":false,"realtimeState":true,"mainCameraPath":"/cameras/cameras:sopGroup/orthographicCamera1","versions":{"polygonjs":"1.5.85"}},"root":{"type":"root","nodes":{"geo1":{"type":"geo","nodes":{"plane1":{"type":"plane","params":{"size":[10,10]}},"plane2":{"type":"plane","params":{"useSegmentsCount":true,"direction":[0,0,1]}},"copy1":{"type":"copy","params":{"copyAttributes":1,"attributesToCopy":"id"},"inputs":["transform1","attribId1"]},"MAT":{"type":"materialsNetwork","nodes":{"meshBasicBuilder_INSTANCES":{"type":"meshBasicBuilder","nodes":{"globals1":{"type":"globals"},"output1":{"type":"output","inputs":[{"index":0,"inputName":"position","node":"instanceTransform1","output":"position"},{"index":1,"inputName":"normal","node":"instanceTransform1","output":"normal"},{"index":2,"inputName":"color","node":"vec4ToVec3_1","output":"vec3"}]},"instanceTransform1":{"type":"instanceTransform"},"param1":{"type":"param","params":{"name":"index"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"floatToInt1":{"type":"floatToInt","params":{"float":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"float","node":"round1","output":"val"}]},"round1":{"type":"round","params":{"in":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"in","node":"multAdd2","output":"val"}],"connection_points":{"in":[{"name":"in","type":"float"}],"out":[{"name":"val","type":"float"}]}},"texture1":{"type":"texture","params":{"paramName":"texture_01","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture2":{"type":"texture","params":{"paramName":"texture_02","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture3":{"type":"texture","params":{"paramName":"texture_03","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"multAdd1":{"type":"multAdd","params":{"value":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"preAdd":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"vector2","default_value":[1,1],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":[1,-1]},"postAdd":{"type":"vector2","default_value":[0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"globals1","output":"uv"}],"connection_points":{"in":[{"name":"value","type":"vec2"},{"name":"preAdd","type":"vec2"},{"name":"mult","type":"vec2"},{"name":"postAdd","type":"vec2"}],"out":[{"name":"val","type":"vec2"}]}},"switch1":{"type":"switch","params":{"index":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in0":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in1":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in2":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in3":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in4":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in5":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in6":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in7":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in8":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in9":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in10":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"in11":{"type":"vector4","default_value":[0,0,0,0],"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":13,"inputs":[{"index":0,"inputName":"index","node":"floatToInt1","output":"int"},{"index":1,"inputName":"in0","node":"texture_black","output":"rgba"},{"index":2,"inputName":"in1","node":"texture1","output":"rgba"},{"index":3,"inputName":"in2","node":"texture2","output":"rgba"},{"index":4,"inputName":"in3","node":"texture3","output":"rgba"},{"index":5,"inputName":"in4","node":"texture4","output":"rgba"},{"index":6,"inputName":"in5","node":"texture5","output":"rgba"},{"index":7,"inputName":"in6","node":"texture6","output":"rgba"},{"index":8,"inputName":"in7","node":"texture7","output":"rgba"},{"index":9,"inputName":"in8","node":"texture8","output":"rgba"},{"index":10,"inputName":"in9","node":"texture9","output":"rgba"},{"index":11,"inputName":"in10","node":"texture10","output":"rgba"}],"connection_points":{"in":[{"name":"index","type":"int"},{"name":"in0","type":"vec4"},{"name":"in1","type":"vec4"},{"name":"in2","type":"vec4"},{"name":"in3","type":"vec4"},{"name":"in4","type":"vec4"},{"name":"in5","type":"vec4"},{"name":"in6","type":"vec4"},{"name":"in7","type":"vec4"},{"name":"in8","type":"vec4"},{"name":"in9","type":"vec4"},{"name":"in10","type":"vec4"},{"name":"in11","type":"vec4"}],"out":[{"name":"val","type":"vec4"}]}},"vec4ToVec3_1":{"type":"vec4ToVec3","params":{"vec4":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"vec4","node":"switch1","output":"val"}]},"attribute1":{"type":"attribute","params":{"name":"state"},"connection_points":{"in":[],"out":[{"name":"val","type":"float"}]}},"multAdd2":{"type":"multAdd","params":{"value":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"preAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"mult":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false},"raw_input":10},"postAdd":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value","node":"attribute1","output":"val"}],"connection_points":{"in":[{"name":"value","type":"float"},{"name":"preAdd","type":"float"},{"name":"mult","type":"float"},{"name":"postAdd","type":"float"}],"out":[{"name":"val","type":"float"}]}},"texture_black":{"type":"texture","params":{"paramName":"texture_black"}},"texture4":{"type":"texture","params":{"paramName":"texture_04","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture5":{"type":"texture","params":{"paramName":"texture_05","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture6":{"type":"texture","params":{"paramName":"texture_06","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture7":{"type":"texture","params":{"paramName":"texture_07","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture8":{"type":"texture","params":{"paramName":"texture_08","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture9":{"type":"texture","params":{"paramName":"texture_09","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]},"texture10":{"type":"texture","params":{"paramName":"texture_10","uv":{"overriden_options":{}},"blurPixelsCountX":{"overriden_options":{}},"blurPixelsCountY":{"overriden_options":{}}},"inputs":[{"index":0,"inputName":"uv","node":"multAdd1","output":"val"}]}},"params":{"index":{"type":"float","default_value":0,"options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true},"raw_input":-1,"overriden_options":{"callback":"{}"}},"texture_01":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_01","overriden_options":{"callback":"{}"}},"texture_02":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_02","overriden_options":{"callback":"{}"}},"texture_03":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_03","overriden_options":{"callback":"{}"}},"texture_black":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/color_black","overriden_options":{"callback":"{}"}},"texture_04":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_04","overriden_options":{"callback":"{}"}},"texture_05":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_05","overriden_options":{"callback":"{}"}},"texture_06":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_06","overriden_options":{"callback":"{}"}},"texture_07":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_07","overriden_options":{"callback":"{}"}},"texture_08":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_08","overriden_options":{"callback":"{}"}},"texture_09":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_09","overriden_options":{"callback":"{}"}},"texture_10":{"type":"node_path","default_value":"","options":{"spare":true,"computeOnDirty":true,"cook":false,"dependentOnFoundNode":true,"nodeSelection":{"context":"cop"}},"raw_input":"../../COP/text_10","overriden_options":{"callback":"{}"}}},"persisted_config":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-main","type":"MeshBasicMaterial","color":16777215,"reflectivity":1,"refractionRatio":0.98,"blendColor":0,"fog":false},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false},"customMaterials":{"customDepthMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDepthMaterial","type":"MeshDepthMaterial","name":"customDepthMaterial","blendColor":0,"depthPacking":3201},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDistanceMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDistanceMaterial","type":"MeshDistanceMaterial","name":"customDistanceMaterial","blendColor":0},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}},"customDepthDOFMaterial":{"material":{"metadata":{"version":4.6,"type":"Material","generator":"Material.toJSON"},"uuid":"/geo1/MAT/meshBasicBuilder_INSTANCES-customDepthDOFMaterial","type":"MeshDepthMaterial","name":"customDepthDOFMaterial","blendColor":0,"depthPacking":3200},"onBeforeCompileDataJSONWithoutShaders":{"paramConfigs":[{"type":"float","name":"index","defaultValue":0,"uniformName":"v_POLY_param_index"},{"type":"node_path","name":"texture_01","defaultValue":"","uniformName":"v_POLY_texture_texture_01"},{"type":"node_path","name":"texture_02","defaultValue":"","uniformName":"v_POLY_texture_texture_02"},{"type":"node_path","name":"texture_03","defaultValue":"","uniformName":"v_POLY_texture_texture_03"},{"type":"node_path","name":"texture_black","defaultValue":"","uniformName":"v_POLY_texture_texture_black"},{"type":"node_path","name":"texture_04","defaultValue":"","uniformName":"v_POLY_texture_texture_04"},{"type":"node_path","name":"texture_05","defaultValue":"","uniformName":"v_POLY_texture_texture_05"},{"type":"node_path","name":"texture_06","defaultValue":"","uniformName":"v_POLY_texture_texture_06"},{"type":"node_path","name":"texture_07","defaultValue":"","uniformName":"v_POLY_texture_texture_07"},{"type":"node_path","name":"texture_08","defaultValue":"","uniformName":"v_POLY_texture_texture_08"},{"type":"node_path","name":"texture_09","defaultValue":"","uniformName":"v_POLY_texture_texture_09"},{"type":"node_path","name":"texture_10","defaultValue":"","uniformName":"v_POLY_texture_texture_10"}],"timeDependent":false,"resolutionDependent":false,"raymarchingLightsWorldCoordsDependent":false}}}}}}},"COP":{"type":"copNetwork","nodes":{"text_01":{"type":"text","params":{"text":"01","resolution":[128,128],"fontSize":75}},"text_02":{"type":"text","params":{"text":"02","resolution":[128,128],"fontSize":75}},"text_03":{"type":"text","params":{"text":"03","resolution":[128,128],"fontSize":75}},"text_04":{"type":"text","params":{"text":"04","resolution":[128,128],"fontSize":75}},"text_05":{"type":"text","params":{"text":"05","resolution":[128,128],"fontSize":75}},"text_06":{"type":"text","params":{"text":"06","resolution":[128,128],"fontSize":75}},"text_07":{"type":"text","params":{"text":"07","resolution":[128,128],"fontSize":75}},"text_08":{"type":"text","params":{"text":"08","resolution":[128,128],"fontSize":75}},"text_09":{"type":"text","params":{"text":"09","resolution":[128,128],"fontSize":75}},"text_10":{"type":"text","params":{"text":"10","resolution":[128,128],"fontSize":75}},"color_black":{"type":"color","params":{"resolution":[128,128],"color":[0,0,0]}}}},"transform1":{"type":"transform","inputs":["plane2"]},"instance1":{"type":"instance","params":{"material":"../MAT/meshBasicBuilder_INSTANCES"},"inputs":["transform1","attribId1"]},"actorInstance1":{"type":"actorInstance","nodes":{"onTick1":{"type":"onTick"},"param1":{"type":"param","params":{"name":"hoveredId","type":3},"connection_points":{"in":[],"out":[{"name":"val","type":"int","isArray":false}]}},"setInstanceAttribute1":{"type":"setInstanceAttribute","params":{"attribName":{"overriden_options":{}},"ptnum":{"overriden_options":{}},"lerp":{"overriden_options":{}},"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":6,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},null,null,{"index":3,"inputName":"attribName","node":"constant1","output":"val"},null,{"index":5,"inputName":"val","node":"clamp1","output":"clamped"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}]}},"getInstanceAttribute2":{"type":"getInstanceAttribute","params":{"ptnum":{"type":"integer","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"attribName":{"type":"string","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[null,null,{"index":2,"inputName":"attribName","node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"Object3D","type":"Object3D","isArray":false},{"name":"ptnum","type":"int","isArray":false},{"name":"attribName","type":"string","isArray":false}],"out":[{"name":"ptnum","type":"int","isArray":false},{"name":"val","type":"float","isArray":false}]}},"constant1":{"type":"constant","params":{"type":4,"string":"state"},"connection_points":{"in":[],"out":[{"name":"val","type":"string","isArray":false}]}},"add2":{"type":"add","params":{"add0":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add1":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add2":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"add3":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"add0","node":"getInstanceAttribute2","output":"val"},{"index":1,"inputName":"add1","node":"constant2","output":"val"},{"index":2,"inputName":"add2","node":"twoWaySwitch1","output":"val"}],"connection_points":{"in":[{"name":"add0","type":"float","isArray":false},{"name":"add1","type":"float","isArray":false},{"name":"add2","type":"float","isArray":false},{"name":"add3","type":"float","isArray":false}],"out":[{"name":"sum","type":"float","isArray":false}]}},"constant2":{"type":"constant","params":{"float":-0.05},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"getInstanceProperty2":{"type":"getInstanceProperty"},"compare1":{"type":"compare","params":{"test":0,"value0":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"value1":{"type":"integer","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"value0","node":"param1","output":"val"},{"index":1,"inputName":"value1","node":"getInstanceProperty2","output":"ptnum"}],"connection_points":{"in":[{"name":"value0","type":"int","isArray":false},{"name":"value1","type":"int","isArray":false}],"out":[{"name":"val","type":"boolean","isArray":false}]}},"twoWaySwitch1":{"type":"twoWaySwitch","params":{"condition":{"type":"boolean","default_value":false,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"ifTrue":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"ifFalse":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"condition","node":"compare1","output":"val"},{"index":1,"inputName":"ifTrue","node":"constant3","output":"val"},{"index":2,"inputName":"ifFalse","node":"constant4","output":"val"}],"connection_points":{"in":[{"name":"condition","type":"boolean","isArray":false},{"name":"ifTrue","type":"float","isArray":false},{"name":"ifFalse","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"constant3":{"type":"constant","params":{"float":1},"connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}},"clamp1":{"type":"clamp","params":{"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}},"min":{"type":"float","default_value":0,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"max":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"inputs":[{"index":0,"inputName":"val","node":"add2","output":"sum"}],"connection_points":{"in":[{"name":"val","type":"float","isArray":false},{"name":"min","type":"float","isArray":false},{"name":"max","type":"float","isArray":false}],"out":[{"name":"clamped","type":"float","isArray":false}]}},"constant4":{"type":"constant","connection_points":{"in":[],"out":[{"name":"val","type":"float","isArray":false}]}}},"params":{"hoveredId":{"type":"integer","default_value":0,"options":{"spare":true,"computeOnDirty":true,"cook":false},"raw_input":-1,"overriden_options":{"callback":"{}"}}},"inputs":["attribCreate1"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["getActorNodeParamValue","getPointIndex","getPointAttributeNumber","addNumber","clamp","mathFloat_3","globalsTime","globalsTimeDelta","setPointAttributeNumber","setPointIndex"],"serializedParamConfigs":[{"type":"integer","name":"hoveredId","defaultValue":0,"uniformName":"v_POLY_param1_val"}],"eventDatas":[]}},"attribId1":{"type":"attribId","params":{"idn":0},"inputs":["plane1"]},"merge1":{"type":"merge","inputs":["transform2","actorInstance1"],"flags":{"display":true}},"attribCreate1":{"type":"attribCreate","params":{"name":"state"},"inputs":["instance1"]},"transform2":{"type":"transform","params":{"applyOn":1,"t":[0,-1,0]},"inputs":["actor1"]},"actor1":{"type":"actor","nodes":{"constant1":{"type":"constant","params":{"type":4,"string":"id"},"connection_points":{"in":[],"out":[{"name":"val","type":"string","isArray":false}]}},"setParam1":{"type":"setParam","params":{"Param":{"type":"param_path","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":false,"dependentOnFoundParam":false}},"lerp":{"type":"float","default_value":1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}},"val":{"type":"float","default_value":0,"options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":4,"inputs":[{"index":0,"inputName":"trigger","node":"onTick1","output":"trigger"},{"index":1,"inputName":"Param","node":"getParam1","output":"Param"},null,{"index":3,"inputName":"val","node":"getIntersectionAttribute1","output":"val"}],"connection_points":{"in":[{"name":"trigger","type":"trigger","isArray":false},{"name":"Param","type":"Param","isArray":false},{"name":"lerp","type":"float","isArray":false},{"name":"val","type":"float","isArray":false}],"out":[{"name":"trigger","type":"trigger","isArray":false}]}},"getParam1":{"type":"getParam","params":{"Param":"/geo1/actorInstance1/hoveredId"}},"getIntersectionAttribute1":{"type":"getIntersectionAttribute","params":{"attribName":{"type":"string","default_value":"","options":{"spare":true,"editable":false,"computeOnDirty":true,"dependentOnFoundParam":false},"overriden_options":{}},"notFoundValue":{"type":"float","default_value":-1,"options":{"spare":true,"editable":true,"computeOnDirty":true,"dependentOnFoundParam":false}}},"maxInputsCount":3,"inputs":[{"index":0,"inputName":"Intersection","node":"rayIntersectObject1","output":"Intersection"},{"index":1,"inputName":"attribName","node":"constant1","output":"val"}],"connection_points":{"in":[{"name":"Intersection","type":"Intersection","isArray":false},{"name":"attribName","type":"string","isArray":false},{"name":"notFoundValue","type":"float","isArray":false}],"out":[{"name":"val","type":"float","isArray":false}]}},"rayFromCursor1":{"type":"rayFromCursor"},"rayIntersectObject1":{"type":"rayIntersectObject","maxInputsCount":3,"inputs":[{"index":0,"inputName":"Ray","node":"rayFromCursor1","output":"Ray"}]},"onTick1":{"type":"onTick"}},"inputs":["merge2"],"persisted_config":{"variableNames":[],"variables":[],"functionNames":["globalsRayFromCursor","rayIntersectObject3D","getIntersectionAttributeNumberInterpolated","globalsTime","globalsTimeDelta","getParam","setParamFloat"],"serializedParamConfigs":[],"eventDatas":[{"type":"pointermove","emitter":"canvas","jsType":"rayFromCursor"},{"type":"touchmove","emitter":"canvas","jsType":"rayFromCursor"}]}},"merge2":{"type":"merge","params":{"compact":1},"inputs":["attribPromote1"]},"attribPromote1":{"type":"attribPromote","params":{"classFrom":3,"classTo":0,"name":"id"},"inputs":["copy1"]}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}},"cameras":{"type":"geo","nodes":{"perspectiveCamera1":{"type":"perspectiveCamera","params":{"position":[3.3,3.3,3.3]}},"cameraControls1":{"type":"cameraControls","nodes":{"cameraOrbitControls1":{"type":"cameraOrbitControls","params":{"target":[-0.8076651964617726,0.4281695890044879,-0.08427249496432923]}}},"params":{"node":"cameraOrbitControls1"},"inputs":["perspectiveCamera1"]},"orthographicCamera1":{"type":"orthographicCamera","params":{"size":11}},"merge1":{"type":"merge","inputs":["cameraControls1","transform1"],"flags":{"display":true}},"transform1":{"type":"transform","params":{"applyOn":1,"t":[0,1.8,0],"r":[-90,0,0]},"inputs":["orthographicCamera1"]}},"params":{"CADLinearTolerance":{"overriden_options":{"callback":"{}"}},"CADAngularTolerance":{"overriden_options":{"callback":"{}"}},"CADCurveAbscissa":{"overriden_options":{"callback":"{}"}},"CADCurveTolerance":{"overriden_options":{"callback":"{}"}},"CADDisplayEdges":{"overriden_options":{"callback":"{}"}},"CADEdgesColor":{"overriden_options":{"callback":"{}"}},"CADDisplayMeshes":{"overriden_options":{"callback":"{}"}},"CADMeshesColor":{"overriden_options":{"callback":"{}"}},"CADWireframe":{"overriden_options":{"callback":"{}"}},"CSGFacetAngle":{"overriden_options":{"callback":"{}"}},"CSGLinesColor":{"overriden_options":{"callback":"{}"}},"CSGMeshesColor":{"overriden_options":{"callback":"{}"}},"CSGWireframe":{"overriden_options":{"callback":"{}"}},"QUADTriangles":{"overriden_options":{"callback":"{}"}},"QUADWireframe":{"overriden_options":{"callback":"{}"}},"TetScale":{"overriden_options":{"callback":"{}"}},"TetDisplayLines":{"overriden_options":{"callback":"{}"}},"TetDisplaySharedFaces":{"overriden_options":{"callback":"{}"}},"TetDisplayPoints":{"overriden_options":{"callback":"{}"}},"TetDisplayCenter":{"overriden_options":{"callback":"{}"}},"TetDisplaySphere":{"overriden_options":{"callback":"{}"}}},"flags":{"display":true}}},"params":{"mainCameraPath":"/cameras/cameras:sopGroup/orthographicCamera1"}},"ui":{"nodes":{"geo1":{"pos":[-50,-350],"nodes":{"plane1":{"pos":[100,0]},"plane2":{"pos":[-300,0]},"copy1":{"pos":[-300,300]},"MAT":{"pos":[-550,300],"nodes":{"meshBasicBuilder_INSTANCES":{"pos":[0,-200],"nodes":{"globals1":{"pos":[-600,-50]},"output1":{"pos":[650,-100]},"instanceTransform1":{"pos":[300,-100]},"param1":{"pos":[-350,0]},"floatToInt1":{"pos":[-150,0]},"round1":{"pos":[-250,0]},"texture1":{"pos":[-150,300]},"texture2":{"pos":[-150,450]},"texture3":{"pos":[-150,600]},"multAdd1":{"pos":[-450,400]},"switch1":{"pos":[150,250]},"vec4ToVec3_1":{"pos":[300,250]},"attribute1":{"pos":[-350,-150]},"multAdd2":{"pos":[-250,-150]},"texture_black":{"pos":[-150,150]},"texture4":{"pos":[-150,750]},"texture5":{"pos":[-150,900]},"texture6":{"pos":[-150,1050]},"texture7":{"pos":[-150,1200]},"texture8":{"pos":[-150,1350]},"texture9":{"pos":[-150,1500]},"texture10":{"pos":[-150,1700]}}}}},"COP":{"pos":[-550,450],"nodes":{"text_01":{"pos":[-200,-200]},"text_02":{"pos":[-200,-100]},"text_03":{"pos":[-200,0]},"text_04":{"pos":[-200,100]},"text_05":{"pos":[-200,200]},"text_06":{"pos":[-200,300]},"text_07":{"pos":[-200,400]},"text_08":{"pos":[-200,500]},"text_09":{"pos":[-200,600]},"text_10":{"pos":[-200,700]},"color_black":{"pos":[-200,-350]}}},"transform1":{"pos":[-300,100]},"instance1":{"pos":[100,300]},"actorInstance1":{"pos":[100,800],"selection":["clamp1"],"nodes":{"onTick1":{"pos":[100,100]},"param1":{"pos":[-600,600]},"setInstanceAttribute1":{"pos":[450,150]},"getInstanceAttribute2":{"pos":[-100,300]},"constant1":{"pos":[-300,150]},"add2":{"pos":[100,300]},"constant2":{"pos":[-100,400]},"getInstanceProperty2":{"pos":[-600,750]},"compare1":{"pos":[-350,650]},"twoWaySwitch1":{"pos":[-50,650]},"constant3":{"pos":[-200,750]},"clamp1":{"pos":[250,300]},"constant4":{"pos":[-200,850]}}},"attribId1":{"pos":[100,100]},"merge1":{"pos":[-150,1050]},"attribCreate1":{"pos":[100,550]},"transform2":{"pos":[-300,850]},"actor1":{"pos":[-300,700],"nodes":{"constant1":{"pos":[-400,-100]},"setParam1":{"pos":[100,-400]},"getParam1":{"pos":[-100,-450]},"getIntersectionAttribute1":{"pos":[-200,-250]},"rayFromCursor1":{"pos":[-550,-250]},"rayIntersectObject1":{"pos":[-400,-250]},"onTick1":{"pos":[-100,-550]}}},"merge2":{"pos":[-300,550]},"attribPromote1":{"pos":[-300,400]}}},"cameras":{"pos":[-50,-150],"nodes":{"perspectiveCamera1":{"pos":[0,-50]},"cameraControls1":{"pos":[0,150],"nodes":{"cameraOrbitControls1":{"pos":[0,0]}}},"orthographicCamera1":{"pos":[200,-50]},"merge1":{"pos":[100,300]},"transform1":{"pos":[200,100]}}}}},"shaders":{"/geo1/MAT/meshBasicBuilder_INSTANCES":{"vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}","fragment":"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}","customDepthMaterial.vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n","customDistanceMaterial.vertex":"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}","customDistanceMaterial.fragment":"\n// INSERT DEFINES\n\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvoid main () {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\n\t#include <alphatest_fragment>\n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n","customDepthDOFMaterial.vertex":"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\n\n// https://stackoverflow.com/questions/23793698/how-to-implement-slerp-in-glsl-hlsl\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t)\n// {\n// \tfloat dotp = dot(normalize(p0), normalize(p1));\n// \tif ((dotp > 0.9999) || (dotp < -0.9999))\n// \t{\n// \t\tif (t<=0.5)\n// \t\t\treturn p0;\n// \t\treturn p1;\n// \t}\n// \tfloat theta = acos(dotp);\n// \tvec4 P = ((p0*sin((1.0-t)*theta) + p1*sin(t*theta)) / sin(theta));\n// \tP.w = 1.0;\n// \treturn P;\n// }\n\n// https://devcry.heiho.net/html/2017/20170521-slerp.html\n// float lerp(float a, float b, float t) {\n// \treturn (1.0 - t) * a + t * b;\n// }\n// vec4 quatSlerp(vec4 p0, vec4 p1, float t){\n// \tvec4 qb = p1;\n\n// \t// cos(a) = dot product\n// \tfloat cos_a = p0.x * qb.x + p0.y * qb.y + p0.z * qb.z + p0.w * qb.w;\n// \tif (cos_a < 0.0f) {\n// \t\tcos_a = -cos_a;\n// \t\tqb = -qb;\n// \t}\n\n// \t// close to zero, cos(a) ~= 1\n// \t// do linear interpolation\n// \tif (cos_a > 0.999) {\n// \t\treturn vec4(\n// \t\t\tlerp(p0.x, qb.x, t),\n// \t\t\tlerp(p0.y, qb.y, t),\n// \t\t\tlerp(p0.z, qb.z, t),\n// \t\t\tlerp(p0.w, qb.w, t)\n// \t\t);\n// \t}\n\n// \tfloat alpha = acos(cos_a);\n// \treturn (p0 * sin(1.0 - t) + p1 * sin(t * alpha)) / sin(alpha);\n// }\n\n// https://stackoverflow.com/questions/62943083/interpolate-between-two-quaternions-the-long-way\nvec4 quatSlerp(vec4 q1, vec4 q2, float t){\n\tfloat angle = acos(dot(q1, q2));\n\tfloat denom = sin(angle);\n\t//check if denom is zero\n\treturn (q1*sin((1.0-t)*angle)+q2*sin(t*angle))/denom;\n}\n// TO CHECK:\n// this page https://www.reddit.com/r/opengl/comments/704la7/glsl_quaternion_library/\n// has a link to a potentially nice pdf:\n// http://web.mit.edu/2.998/www/QuaternionReport1.pdf\n\n// https://github.com/mattatz/ShibuyaCrowd/blob/master/source/shaders/common/quaternion.glsl\nvec4 quatMult(vec4 q1, vec4 q2)\n{\n\treturn vec4(\n\tq1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,\n\tq1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,\n\tq1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,\n\tq1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z\n\t);\n}\n// http://glmatrix.net/docs/quat.js.html#line97\n// let ax = a[0], ay = a[1], az = a[2], aw = a[3];\n\n// let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n\n// out[0] = ax * bw + aw * bx + ay * bz - az * by;\n\n// out[1] = ay * bw + aw * by + az * bx - ax * bz;\n\n// out[2] = az * bw + aw * bz + ax * by - ay * bx;\n\n// out[3] = aw * bw - ax * bx - ay * by - az * bz;\n\n// return out\n\n\n\n// http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/\nmat4 rotationMatrix(vec3 axis, float angle)\n{\n\taxis = normalize(axis);\n\tfloat s = sin(angle);\n\tfloat c = cos(angle);\n\tfloat oc = 1.0 - c;\n\n \treturn mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0.0, oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0.0, oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0.0, 0.0, 0.0, 0.0, 1.0);\n}\n\n// https://www.geeks3d.com/20141201/how-to-rotate-a-vertex-by-a-quaternion-in-glsl/\nvec4 quatFromAxisAngle(vec3 axis, float angle)\n{\n\tvec4 qr;\n\tfloat half_angle = (angle * 0.5); // * 3.14159 / 180.0;\n\tfloat sin_half_angle = sin(half_angle);\n\tqr.x = axis.x * sin_half_angle;\n\tqr.y = axis.y * sin_half_angle;\n\tqr.z = axis.z * sin_half_angle;\n\tqr.w = cos(half_angle);\n\treturn qr;\n}\nvec3 rotateWithAxisAngle(vec3 position, vec3 axis, float angle)\n{\n\tvec4 q = quatFromAxisAngle(axis, angle);\n\tvec3 v = position.xyz;\n\treturn v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\n}\n// vec3 applyQuaternionToVector( vec4 q, vec3 v ){\n// \treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n// }\nvec3 rotateWithQuat( vec3 v, vec4 q )\n{\n\t// vec4 qv = multQuat( quat, vec4(vec, 0.0) );\n\t// return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;\n\treturn v + 2.0 * cross( q.xyz, cross( q.xyz, v ) + q.w * v );\n}\n// https://github.com/glslify/glsl-look-at/blob/gh-pages/index.glsl\n// mat3 rotation_matrix(vec3 origin, vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target - origin);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n// mat3 rotation_matrix(vec3 target, float roll) {\n// \tvec3 rr = vec3(sin(roll), cos(roll), 0.0);\n// \tvec3 ww = normalize(target);\n// \tvec3 uu = normalize(cross(ww, rr));\n// \tvec3 vv = normalize(cross(uu, ww));\n\n// \treturn mat3(uu, vv, ww);\n// }\n\nfloat vectorAngle(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 c1 = cross(start, dest);\n\t// We use the dot product of the cross with the Y axis.\n\t// This is a little arbitrary, but can still give a good sense of direction\n\tvec3 y_axis = vec3(0.0, 1.0, 0.0);\n\tfloat d1 = dot(c1, y_axis);\n\tfloat angle = acos(cosTheta) * sign(d1);\n\treturn angle;\n}\n\n// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#i-need-an-equivalent-of-glulookat-how-do-i-orient-an-object-towards-a-point-\nvec4 vectorAlign(vec3 start, vec3 dest){\n\tstart = normalize(start);\n\tdest = normalize(dest);\n\n\tfloat cosTheta = dot(start, dest);\n\tvec3 axis;\n\n\t// if (cosTheta < -1 + 0.001f){\n\t// \t// special case when vectors in opposite directions:\n\t// \t// there is no ideal rotation axis\n\t// \t// So guess one; any will do as long as it's perpendicular to start\n\t// \taxis = cross(vec3(0.0f, 0.0f, 1.0f), start);\n\t// \tif (length2(axis) < 0.01 ) // bad luck, they were parallel, try again!\n\t// \t\taxis = cross(vec3(1.0f, 0.0f, 0.0f), start);\n\n\t// \taxis = normalize(axis);\n\t// \treturn gtx::quaternion::angleAxis(glm::radians(180.0f), axis);\n\t// }\n\tif(cosTheta > (1.0 - 0.0001) || cosTheta < (-1.0 + 0.0001) ){\n\t\taxis = normalize(cross(start, vec3(0.0, 1.0, 0.0)));\n\t\tif (length(axis) < 0.001 ){ // bad luck, they were parallel, try again!\n\t\t\taxis = normalize(cross(start, vec3(1.0, 0.0, 0.0)));\n\t\t}\n\t} else {\n\t\taxis = normalize(cross(start, dest));\n\t}\n\n\tfloat angle = acos(cosTheta);\n\n\treturn quatFromAxisAngle(axis, angle);\n}\nvec4 vectorAlignWithUp(vec3 start, vec3 dest, vec3 up){\n\tvec4 rot1 = vectorAlign(start, dest);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\t// vec3 right = normalize(cross(dest, up));\n\t// up = normalize(cross(right, dest));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(vec3(0.0, 1.0, 0.0), rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(up, newUp);\n\n\t// return rot1;\n\treturn rot2;\n\t// return multQuat(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n// https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\nfloat quatToAngle(vec4 q){\n\treturn 2.0 * acos(q.w);\n}\nvec3 quatToAxis(vec4 q){\n\treturn vec3(\n\t\tq.x / sqrt(1.0-q.w*q.w),\n\t\tq.y / sqrt(1.0-q.w*q.w),\n\t\tq.z / sqrt(1.0-q.w*q.w)\n\t);\n}\n\nvec4 align(vec3 dir, vec3 up){\n\tvec3 start_dir = vec3(0.0, 0.0, 1.0);\n\tvec3 start_up = vec3(0.0, 1.0, 0.0);\n\tvec4 rot1 = vectorAlign(start_dir, dir);\n\tup = normalize(up);\n\n\t// Recompute desiredUp so that it's perpendicular to the direction\n\t// You can skip that part if you really want to force desiredUp\n\tvec3 right = normalize(cross(dir, up));\n\tif(length(right)<0.001){\n\t\tright = vec3(1.0, 0.0, 0.0);\n\t}\n\tup = normalize(cross(right, dir));\n\n\t// Because of the 1rst rotation, the up is probably completely screwed up.\n\t// Find the rotation between the up of the rotated object, and the desired up\n\tvec3 newUp = rotateWithQuat(start_up, rot1);//rot1 * vec3(0.0, 1.0, 0.0);\n\tvec4 rot2 = vectorAlign(normalize(newUp), up);\n\n\t// return rot1;\n\treturn quatMult(rot1, rot2);\n\t// return rot2 * rot1;\n\n}\n\n\n\n\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\nattribute vec3 instancePosition;\nattribute vec4 instanceQuaternion;\nattribute vec3 instanceScale;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nattribute float state;\n\n\n\n\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n// removed:\n//\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n// removed:\n//\t#include <begin_vertex>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/instanceTransform1\n\tvec3 v_POLY_instanceTransform1_position = vec3(position);\n\tv_POLY_instanceTransform1_position *= instanceScale;\n\tv_POLY_instanceTransform1_position = rotateWithQuat( v_POLY_instanceTransform1_position, instanceQuaternion );\n\tv_POLY_instanceTransform1_position += instancePosition;\n\tvec3 v_POLY_instanceTransform1_normal = vec3(normal);\n\tv_POLY_instanceTransform1_normal = rotateWithQuat( v_POLY_instanceTransform1_normal, instanceQuaternion );\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tv_POLY_attribute_state = float(state);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\n\tv_POLY_globals1_uv = vec2(uv);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tvec3 transformed = v_POLY_instanceTransform1_position;\n\tvec3 objectNormal = v_POLY_instanceTransform1_normal;\n\t#ifdef USE_TANGENT\n\t\tvec3 objectTangent = vec3( tangent.xyz );\n\t#endif\n\n\n\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}","customDepthDOFMaterial.fragment":"\n// INSERT DEFINES\n\n\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include <common>\n\n\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\nuniform sampler2D v_POLY_texture_texture_black;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\nuniform sampler2D v_POLY_texture_texture_01;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\nuniform sampler2D v_POLY_texture_texture_02;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\nuniform sampler2D v_POLY_texture_texture_03;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\nuniform sampler2D v_POLY_texture_texture_04;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\nuniform sampler2D v_POLY_texture_texture_05;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\nuniform sampler2D v_POLY_texture_texture_06;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\nuniform sampler2D v_POLY_texture_texture_07;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\nuniform sampler2D v_POLY_texture_texture_08;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\nuniform sampler2D v_POLY_texture_texture_09;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\nuniform sampler2D v_POLY_texture_texture_10;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\nvarying float v_POLY_attribute_state;\n\n// /geo1/MAT/meshBasicBuilder_INSTANCES/globals1\nvarying vec2 v_POLY_globals1_uv;\n\n\n\n\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include <clipping_planes_fragment>\n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\n\n\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/attribute1\n\tfloat v_POLY_attribute1_val = v_POLY_attribute_state;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture_black\n\tvec4 v_POLY_texture_black_rgba = texture2D(v_POLY_texture_texture_black, vec2(0.0, 0.0));\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd2\n\tfloat v_POLY_multAdd2_val = (10.0*(v_POLY_attribute1_val + 0.0)) + 0.0;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/multAdd1\n\tvec2 v_POLY_multAdd1_val = (vec2(1.0, -1.0)*(v_POLY_globals1_uv + vec2(0.0, 0.0))) + vec2(0.0, 0.0);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/round1\n\tfloat v_POLY_round1_val = sign(v_POLY_multAdd2_val)*floor(abs(v_POLY_multAdd2_val)+0.5);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture1\n\tvec4 v_POLY_texture1_rgba = texture2D(v_POLY_texture_texture_01, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture2\n\tvec4 v_POLY_texture2_rgba = texture2D(v_POLY_texture_texture_02, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture3\n\tvec4 v_POLY_texture3_rgba = texture2D(v_POLY_texture_texture_03, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture4\n\tvec4 v_POLY_texture4_rgba = texture2D(v_POLY_texture_texture_04, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture5\n\tvec4 v_POLY_texture5_rgba = texture2D(v_POLY_texture_texture_05, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture6\n\tvec4 v_POLY_texture6_rgba = texture2D(v_POLY_texture_texture_06, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture7\n\tvec4 v_POLY_texture7_rgba = texture2D(v_POLY_texture_texture_07, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture8\n\tvec4 v_POLY_texture8_rgba = texture2D(v_POLY_texture_texture_08, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture9\n\tvec4 v_POLY_texture9_rgba = texture2D(v_POLY_texture_texture_09, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/texture10\n\tvec4 v_POLY_texture10_rgba = texture2D(v_POLY_texture_texture_10, v_POLY_multAdd1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/floatToInt1\n\tint v_POLY_floatToInt1_int = int(v_POLY_round1_val);\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/switch1\n\tvec4 v_POLY_switch1_val;\n\tint v_POLY_switch1_index = v_POLY_floatToInt1_int;\n\tif(v_POLY_switch1_index == 0){v_POLY_switch1_val = v_POLY_texture_black_rgba;}\n\telse if(v_POLY_switch1_index == 1){v_POLY_switch1_val = v_POLY_texture1_rgba;}\n\telse if(v_POLY_switch1_index == 2){v_POLY_switch1_val = v_POLY_texture2_rgba;}\n\telse if(v_POLY_switch1_index == 3){v_POLY_switch1_val = v_POLY_texture3_rgba;}\n\telse if(v_POLY_switch1_index == 4){v_POLY_switch1_val = v_POLY_texture4_rgba;}\n\telse if(v_POLY_switch1_index == 5){v_POLY_switch1_val = v_POLY_texture5_rgba;}\n\telse if(v_POLY_switch1_index == 6){v_POLY_switch1_val = v_POLY_texture6_rgba;}\n\telse if(v_POLY_switch1_index == 7){v_POLY_switch1_val = v_POLY_texture7_rgba;}\n\telse if(v_POLY_switch1_index == 8){v_POLY_switch1_val = v_POLY_texture8_rgba;}\n\telse if(v_POLY_switch1_index == 9){v_POLY_switch1_val = v_POLY_texture9_rgba;}\n\telse if(v_POLY_switch1_index == 10){v_POLY_switch1_val = v_POLY_texture10_rgba;}\n\telse if(v_POLY_switch1_index == 11){v_POLY_switch1_val = vec4(0.0, 0.0, 0.0, 0.0);}\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/vec4ToVec3_1\n\tvec3 v_POLY_vec4ToVec3_1_vec3 = v_POLY_switch1_val.xyz;\n\t\n\t// /geo1/MAT/meshBasicBuilder_INSTANCES/output1\n\tdiffuseColor.xyz = v_POLY_vec4ToVec3_1_vec3;\n\n\n\n\n\t// INSERT BODY\n\t// the new body lines should be added before the alphatest_fragment\n\t// so that alpha is set before (which is really how it would be set if the alphamap_fragment above was used by the material node parameters)\n\n\t#include <alphatest_fragment>\n\n\t#include <logdepthbuf_fragment>\n\n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), diffuseColor.a );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n"}},"jsFunctionBodies":{"/geo1/actorInstance1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /geo1/actorInstance1/param1\n\tv_POLY_param1_val = computed(() => getActorNodeParamValue(\"hoveredId\"));\n\n\t// /geo1/actorInstance1/getInstanceProperty2\n\tv_POLY_getInstanceProperty2_ptnum = computed(() => getPointIndex(this.object3D));\n\n\t// /geo1/actorInstance1/getInstanceAttribute2\n\tv_POLY_getInstanceAttribute2_val = computed(() =>\n\t\tgetPointAttributeNumber(this.object3D, getPointIndex(this.object3D), this.v_POLY_constant1_val.value, 0.0)\n\t);\n\n\t// /geo1/actorInstance1/compare1\n\tv_POLY_compare1_val = computed(() => this.v_POLY_param1_val.value == this.v_POLY_getInstanceProperty2_ptnum.value);\n\n\t// /geo1/actorInstance1/twoWaySwitch1\n\tv_POLY_twoWaySwitch1_val = computed(() =>\n\t\tthis.v_POLY_compare1_val.value ? this.v_POLY_constant3_val.value : this.v_POLY_constant4_val.value\n\t);\n\n\t// /geo1/actorInstance1/add2\n\tv_POLY_add2_sum = computed(() =>\n\t\taddNumber(\n\t\t\tthis.v_POLY_getInstanceAttribute2_val.value,\n\t\t\tthis.v_POLY_constant2_val.value,\n\t\t\tthis.v_POLY_twoWaySwitch1_val.value,\n\t\t\t0.0\n\t\t)\n\t);\n\n\t// /geo1/actorInstance1/clamp1\n\tv_POLY_clamp1_clamped = computed(() => mathFloat_3(clamp, this.v_POLY_add2_sum.value, 0.0, 1.0));\n\n\t// /geo1/actorInstance1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /geo1/actorInstance1/constant1\n\tv_POLY_constant1_val = { value: \"state\" };\n\n\t// /geo1/actorInstance1/constant2\n\tv_POLY_constant2_val = { value: -0.05 };\n\n\t// /geo1/actorInstance1/constant3\n\tv_POLY_constant3_val = { value: 1.0 };\n\n\t// /geo1/actorInstance1/constant4\n\tv_POLY_constant4_val = { value: 0.0 };\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /geo1/actorInstance1/onTick1\n\tonTick1() {\n\t\tconst pointsCount = pointsCountFromObject(this.object3D);\n\t\tfor (let i = 0; i < pointsCount; i++) {\n\t\t\tsetPointIndex(this.object3D, i);\n\t\t\tthis.setInstanceAttribute1(0);\n\t\t}\n\t\tif (this.object3D.isMesh) {\n\t\t\tcorePrimitiveClassFactory(this.object3D).computeVertexNormalsIfAttributeVersionChanged(this.object3D.geometry);\n\t\t}\n\t}\n\n\t// /geo1/actorInstance1/setInstanceAttribute1\n\tsetInstanceAttribute1() {\n\t\tsetPointAttributeNumber(\n\t\t\tthis.object3D,\n\t\t\tthis.v_POLY_constant1_val.value,\n\t\t\tgetPointIndex(this.object3D),\n\t\t\tthis.v_POLY_clamp1_clamped.value,\n\t\t\t1.0\n\t\t);\n\t}\n}\nreturn CustomActorEvaluator;\n","/geo1/actor1":"// insert defines\nclass CustomActorEvaluator extends ActorEvaluator {\n\t// insert members\n\n\t// /geo1/actor1/rayFromCursor1\n\tv_POLY_rayFromCursor1_Ray = computed(() => globalsRayFromCursor());\n\n\t// /geo1/actor1/rayIntersectObject1\n\tv_POLY_rayIntersectObject1_Intersection = computed(() =>\n\t\trayIntersectObject3D(this.v_POLY_rayFromCursor1_Ray.value, this.object3D, false)\n\t);\n\n\t// /geo1/actor1/getIntersectionAttribute1\n\tv_POLY_getIntersectionAttribute1_val = computed(() =>\n\t\tgetIntersectionAttributeNumberInterpolated(\n\t\t\tthis.v_POLY_rayIntersectObject1_Intersection.value,\n\t\t\tthis.v_POLY_constant1_val.value,\n\t\t\t-1.0\n\t\t)\n\t);\n\n\t// /geo1/actor1/onTick1\n\tv_POLY_onTick1_time = computed(() => globalsTime());\n\tv_POLY_onTick1_delta = computed(() => globalsTimeDelta());\n\n\t// /geo1/actor1/getParam1\n\tv_POLY_getParam1_Param = computed(() => getParam(\"/geo1/actorInstance1/hoveredId\"));\n\n\t// /geo1/actor1/constant1\n\tv_POLY_constant1_val = { value: \"id\" };\n\n\tconstructor(node, object3D) {\n\t\tsuper(node, object3D);\n\t\t// insert after constructor\n\t}\n\t// insert body\n\n\tonTick() {\n\t\tthis.onTick1();\n\t}\n\t// /geo1/actor1/onTick1\n\tonTick1() {\n\t\tthis.setParam1(0);\n\t}\n\n\t// /geo1/actor1/setParam1\n\tsetParam1() {\n\t\tsetParamFloat(this.v_POLY_getParam1_Param.value, this.v_POLY_getIntersectionAttribute1_val.value, 1.0);\n\t}\n}\nreturn CustomActorEvaluator;\n"}}
Code editor
{"multiple_panel":{"split_ratio":0.5,"split_panel0":{"split_ratio":0.5543217692883486,"split_panel0":{"panelTypes":["viewer"],"currentPanelIndex":0,"panel_data":{"camera":"/cameras/cameras:sopGroup/orthographicCamera1","isViewerInitLayoutData":true,"linkIndex":1,"overlayedNetwork":{"allowed":false,"displayed":false}}},"split_panel1":{"panelTypes":["params"],"currentPanelIndex":0,"panel_data":{"active_folder":null,"linkIndex":1}},"split_mode":"vertical"},"split_panel1":{"panelTypes":["network","params","viewer"],"currentPanelIndex":0,"panel_data":{"camera":{"position":{"x":117.1621250663248,"y":-575.4470504744457},"zoom":0.6093359344859172},"history":{"2":{"position":{"x":-12.780563525646556,"y":239.7887660468523},"zoom":1.0222221069335933},"36":{"position":{"x":117.1621250663248,"y":-575.4470504744457},"zoom":0.6093359344859172},"321":{"position":{"x":5.74328178237036,"y":-457.79502309725274},"zoom":0.5353359344859171},"412":{"position":{"x":107.6996088109913,"y":189.14935283102426},"zoom":0.683335934485917},"1008":{"position":{"x":-46.95795827084893,"y":-570.3089819978406},"zoom":0.6273359344859172},"1165":{"position":{"x":-356.77193535554,"y":291.7266725012432},"zoom":0.725222106933593},"1216":{"position":{"x":36.371093771145816,"y":-155.42727161561945},"zoom":0.7852221069335931},"1702":{"position":{"x":16.527474846140308,"y":-312.3879477135959},"zoom":0.7641700061535222},"1765":{"position":{"x":-94.31726224595874,"y":85.63923750315413},"zoom":0.6462221069335929},"2827":{"position":{"x":75.37426604173098,"y":-324.07957912196724},"zoom":0.6146333401705797},"3207":{"position":{"x":-374.3653564097047,"y":-306.97185264043253},"zoom":0.6568023410373257},"3549":{"position":{"x":-116.48043097796263,"y":-421.30163545274604},"zoom":0.668222106933593},"3619":{"position":{"x":-108.02833082020646,"y":-197.1553548008036},"zoom":1.018222106933593},"3712":{"position":{"x":50,"y":-50},"zoom":0.8953359344859174},"3866":{"position":{"x":0,"y":0},"zoom":0.8953359344859174},"4196":{"position":{"x":70.37157531288841,"y":30.905426202229414},"zoom":0.8663359344859174},"4468":{"position":{"x":-11.983749257659213,"y":-3.6203398606522796},"zoom":0.7273359344859173}},"paramsDisplayed":false,"linkIndex":1}},"split_mode":"horizontal"},"currentNodes":["/geo1","/","/","/","/","/","/","/"],"navigationHistory":{"nodePaths":{"1":["/geo1/MAT","/geo1","/geo1/actorInstance1","/geo1","/geo1/MAT","/geo1/MAT/meshBasicBuilder_INSTANCES","/geo1/MAT","/geo1","/geo1/actorInstance1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actor1","/geo1","/geo1/actorInstance1","/geo1"],"2":["/"],"3":["/"],"4":["/"],"5":["/"],"6":["/"],"7":["/"],"8":["/"]},"index":{"1":19,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0}},"fullscreenPanelId":null,"saveOptions":{"checkRemoteAssetsUse":true,"minimizeFilesCount":false},"paramsModal":[]}
Used nodes
cop/color;cop/text;event/cameraOrbitControls;mat/meshBasicBuilder;obj/geo;sop/actor;sop/actorInstance;sop/attribCreate;sop/attribId;sop/attribPromote;sop/cameraControls;sop/copNetwork;sop/copy;sop/instance;sop/materialsNetwork;sop/merge;sop/orthographicCamera;sop/perspectiveCamera;sop/plane;sop/transform
Used operations
Used modules
Used assemblers
GL_MESH_BASIC;JS_ACTOR
Used integrations
[]
Used assets
Nodes map
{"/geo1":"obj/geo","/geo1/plane1":"sop/plane","/geo1/plane2":"sop/plane","/geo1/copy1":"sop/copy","/geo1/MAT":"sop/materialsNetwork","/geo1/MAT/meshBasicBuilder_INSTANCES":"mat/meshBasicBuilder","/geo1/COP":"sop/copNetwork","/geo1/COP/text_01":"cop/text","/geo1/COP/text_02":"cop/text","/geo1/COP/text_03":"cop/text","/geo1/COP/text_04":"cop/text","/geo1/COP/text_05":"cop/text","/geo1/COP/text_06":"cop/text","/geo1/COP/text_07":"cop/text","/geo1/COP/text_08":"cop/text","/geo1/COP/text_09":"cop/text","/geo1/COP/text_10":"cop/text","/geo1/COP/color_black":"cop/color","/geo1/transform1":"sop/transform","/geo1/instance1":"sop/instance","/geo1/actorInstance1":"sop/actorInstance","/geo1/attribId1":"sop/attribId","/geo1/merge1":"sop/merge","/geo1/attribCreate1":"sop/attribCreate","/geo1/transform2":"sop/transform","/geo1/actor1":"sop/actor","/geo1/merge2":"sop/merge","/geo1/attribPromote1":"sop/attribPromote","/cameras":"obj/geo","/cameras/perspectiveCamera1":"sop/perspectiveCamera","/cameras/cameraControls1":"sop/cameraControls","/cameras/cameraControls1/cameraOrbitControls1":"event/cameraOrbitControls","/cameras/orthographicCamera1":"sop/orthographicCamera","/cameras/merge1":"sop/merge","/cameras/transform1":"sop/transform"}
Js version
Editor version
Engine version
Logout
0%
There was a problem displaying your scene:
view scene source