Moved marching cubes to GPU and cleaned code

This commit is contained in:
Dario Zubovic
2016-09-19 00:19:46 +02:00
parent cbbf8e2bee
commit e7d063480c
21 changed files with 1219 additions and 471 deletions

567
Assets/Example1.unity Normal file
View File

@@ -0,0 +1,567 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
SceneSettings:
m_ObjectHideFlags: 0
m_PVSData:
m_PVSObjectsArray: []
m_PVSPortalsArray: []
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 0.48
m_AmbientMode: 0
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 3
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 177398482}
m_IndirectSpecularColor: {r: 0.21340781, g: 0.23696244, b: 0.27416193, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_GIWorkflowMode: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1.7
m_AlbedoBoost: 2.56
m_TemporalCoherenceThreshold: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 4
m_Resolution: 2
m_BakeResolution: 40
m_TextureWidth: 1024
m_TextureHeight: 1024
m_AO: 1
m_AOMaxDistance: 1
m_CompAOExponent: 0.38
m_CompAOExponentDirect: 0.12
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_DirectLightInLightProbes: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 1024
m_ReflectionCompression: 2
m_LightingDataAsset: {fileID: 112000001, guid: afcba2d9ee035de4eb2520df6f790ed5,
type: 2}
m_RuntimeCPUUsage: 50
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
accuratePlacement: 0
minRegionArea: 2
cellSize: 0.16666667
manualCellSize: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &177398481
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 177398483}
- 108: {fileID: 177398482}
m_Layer: 0
m_Name: Directional light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!108 &177398482
Light:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 177398481}
m_Enabled: 1
serializedVersion: 7
m_Type: 1
m_Color: {r: 1, g: 0.94421905, b: 0.63235295, a: 1}
m_Intensity: 0.72
m_Range: 10
m_SpotAngle: 30
m_CookieSize: 10
m_Shadows:
m_Type: 0
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &177398483
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 177398481}
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: -14.59, y: 8.4, z: 3.14}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
--- !u!1 &522512120
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 522512122}
- 114: {fileID: 522512121}
- 23: {fileID: 522512123}
- 33: {fileID: 522512124}
m_Layer: 0
m_Name: Metaballs
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &522512121
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 522512120}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 19661b331d4afbb4b88ebebaed28c66b, type: 3}
m_Name:
m_EditorClassIdentifier:
safeZone: 0.1
resolution: 0.02
threshold: 1
computeShader: {fileID: 7200000, guid: 9bcc9560470e2b4439e048851b4c0470, type: 3}
calculateNormals: 1
--- !u!4 &522512122
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 522512120}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 2.2, z: 0}
m_LocalScale: {x: 0.8, y: 0.8, z: 0.8}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 1269549329}
- {fileID: 811246673}
- {fileID: 1427553064}
m_Father: {fileID: 0}
m_RootOrder: 1
--- !u!23 &522512123
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 522512120}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: fc349da3bdf30e4469786e146c823cc1, type: 2}
m_SubsetIndices:
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedWireframeHidden: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!33 &522512124
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 522512120}
m_Mesh: {fileID: 0}
--- !u!1 &811246672
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 811246673}
- 114: {fileID: 811246674}
m_Layer: 0
m_Name: Ball (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &811246673
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 811246672}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 522512122}
m_RootOrder: 1
--- !u!114 &811246674
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 811246672}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7d48da6326ea96f42bdc7e5971aca19a, type: 3}
m_Name:
m_EditorClassIdentifier:
radius: 0.1
negativeBall: 0
factor: 0
speed: 0.3
--- !u!1 &909959525
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 909959530}
- 20: {fileID: 909959529}
- 92: {fileID: 909959528}
- 124: {fileID: 909959527}
- 81: {fileID: 909959526}
- 114: {fileID: 909959531}
- 114: {fileID: 909959532}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &909959526
AudioListener:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
--- !u!124 &909959527
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
--- !u!92 &909959528
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
--- !u!20 &909959529
Camera:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 70
orthographic: 0
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
m_StereoMirrorMode: 0
--- !u!4 &909959530
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_LocalRotation: {x: 0.07143279, y: -0.7034894, z: 0.071432784, w: 0.7034895}
m_LocalPosition: {x: 2.751, y: 2.561, z: -0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 11.540001, y: -90.00001, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!114 &909959531
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 646b5bc27a658f447b1d929fd5ffbd70, type: 3}
m_Name:
m_EditorClassIdentifier:
mode: 1
showGeneratedNormals: 0
offsetScale: 0.2
blurRadius: 18
edgeThresholdMin: 0.05
edgeThreshold: 0.2
edgeSharpness: 4
dlaaSharp: 0
ssaaShader: {fileID: 4800000, guid: b3728d1488b02490cbd196c7941bf1f8, type: 3}
dlaaShader: {fileID: 4800000, guid: 017ca72b9e8a749058d13ebd527e98fa, type: 3}
nfaaShader: {fileID: 4800000, guid: ce0cb2621f6d84e21a87414e471a3cce, type: 3}
shaderFXAAPreset2: {fileID: 4800000, guid: 6f1418cffd12146f2a83be795f6fa5a7, type: 3}
shaderFXAAPreset3: {fileID: 4800000, guid: c182fa94a5a0a4c02870641efcd38cd5, type: 3}
shaderFXAAII: {fileID: 4800000, guid: cd5b323dcc592457790ff18b528f5e67, type: 3}
shaderFXAAIII: {fileID: 4800000, guid: c547503fff0e8482ea5793727057041c, type: 3}
--- !u!114 &909959532
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4975a6e437fc3b149a8cd508ce5bdd69, type: 3}
m_Name:
m_EditorClassIdentifier:
threshold: 0.25
intensity: 0.6
blurSize: 1.5
blurIterations: 2
blurType: 1
fastBloomShader: {fileID: 4800000, guid: 68a00c837b82e4c6d92e7da765dc5f1d, type: 3}
--- !u!1 &1269549328
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1269549329}
- 114: {fileID: 1269549330}
m_Layer: 0
m_Name: Ball
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1269549329
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1269549328}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 522512122}
m_RootOrder: 0
--- !u!114 &1269549330
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1269549328}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7d48da6326ea96f42bdc7e5971aca19a, type: 3}
m_Name:
m_EditorClassIdentifier:
radius: 0.1
negativeBall: 0
factor: 0
speed: 0.35
--- !u!1 &1427553063
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1427553064}
- 114: {fileID: 1427553065}
m_Layer: 0
m_Name: Ball (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1427553064
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1427553063}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.1, y: 0.1, z: 0.1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 522512122}
m_RootOrder: 2
--- !u!114 &1427553065
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1427553063}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7d48da6326ea96f42bdc7e5971aca19a, type: 3}
m_Name:
m_EditorClassIdentifier:
radius: 0.2
negativeBall: 0
factor: 0
speed: 0.2
--- !u!1 &1748234346
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1748234348}
- 215: {fileID: 1748234347}
m_Layer: 0
m_Name: Reflection Probe
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!215 &1748234347
ReflectionProbe:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1748234346}
m_Enabled: 1
serializedVersion: 2
m_Type: 0
m_Mode: 1
m_RefreshMode: 1
m_TimeSlicingMode: 0
m_Resolution: 128
m_UpdateFrequency: 0
m_BoxSize: {x: 10, y: 10, z: 10}
m_BoxOffset: {x: 0, y: 0, z: 0}
m_NearClip: 0.3
m_FarClip: 1000
m_ShadowDistance: 100
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_IntensityMultiplier: 1
m_BlendDistance: 1
m_HDR: 1
m_BoxProjection: 0
m_RenderDynamicObjects: 0
m_UseOcclusionCulling: 1
m_Importance: 1
m_CustomBakedTexture: {fileID: 0}
--- !u!4 &1748234348
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1748234346}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 5, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 62cd08e0062aa9a4c95bf5c0ca5b846b
timeCreated: 1474114109
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -277,7 +277,8 @@ MonoBehaviour:
safeZone: 0.2
resolution: 0.04
threshold: 1
computeShader: {fileID: 7200000, guid: bd5d7027d3c30804a9dd9ea57ed5f351, type: 3}
computeShader: {fileID: 7200000, guid: 9bcc9560470e2b4439e048851b4c0470, type: 3}
calculateNormals: 0
--- !u!4 &522512122
Transform:
m_ObjectHideFlags: 0
@@ -299,7 +300,7 @@ Transform:
- {fileID: 405009158}
- {fileID: 1520449894}
m_Father: {fileID: 0}
m_RootOrder: 3
m_RootOrder: 2
--- !u!23 &522512123
MeshRenderer:
m_ObjectHideFlags: 0
@@ -336,75 +337,6 @@ MeshFilter:
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 522512120}
m_Mesh: {fileID: 0}
--- !u!1 &644361509
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 100000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
m_PrefabInternal: {fileID: 1088192932}
serializedVersion: 4
m_Component:
- 4: {fileID: 644361512}
- 33: {fileID: 644361511}
- 23: {fileID: 644361510}
m_Layer: 0
m_Name: 3
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!23 &644361510
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 2300000, guid: 1c5bba6be1fcdea4495ee17c17a605b2,
type: 3}
m_PrefabInternal: {fileID: 1088192932}
m_GameObject: {fileID: 644361509}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: f6e29a58e1dd5a04fa36b5391e1e08ce, type: 2}
- {fileID: 2100000, guid: 3df128a00cd60034a84abd4af03493ea, type: 2}
m_SubsetIndices:
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedWireframeHidden: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!33 &644361511
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 3300000, guid: 1c5bba6be1fcdea4495ee17c17a605b2,
type: 3}
m_PrefabInternal: {fileID: 1088192932}
m_GameObject: {fileID: 644361509}
m_Mesh: {fileID: 4300000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
--- !u!4 &644361512
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 400000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
m_PrefabInternal: {fileID: 1088192932}
m_GameObject: {fileID: 644361509}
m_LocalRotation: {x: 0, y: -0.7071068, z: 0, w: 0.7071068}
m_LocalPosition: {x: 5.43, y: 0, z: -5.1}
m_LocalScale: {x: 1.3, y: 1.3, z: 1.3}
m_LocalEulerAnglesHint: {x: 0, y: -90, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
--- !u!1 &811246672
GameObject:
m_ObjectHideFlags: 0
@@ -447,7 +379,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
radius: 0.1
negativeBall: 0
radiusSq: 0
factor: 0
speed: 0.3
--- !u!1 &909959525
GameObject:
@@ -532,11 +464,11 @@ Transform:
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 909959525}
m_LocalRotation: {x: 0.07143279, y: -0.7034894, z: 0.071432784, w: 0.7034895}
m_LocalPosition: {x: 2.751, y: 2.561, z: -0}
m_LocalPosition: {x: 2.751, y: 0.36100006, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 11.540001, y: -90.00001, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_Father: {fileID: 2089509240}
m_RootOrder: 0
--- !u!114 &909959531
MonoBehaviour:
@@ -576,7 +508,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
threshold: 0.25
intensity: 0.6
intensity: 0.75
blurSize: 1.5
blurIterations: 2
blurType: 1
@@ -618,7 +550,7 @@ Prefab:
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
propertyPath: m_RootOrder
value: 2
value: 1
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
propertyPath: m_LocalScale.x
@@ -642,7 +574,6 @@ Prefab:
objectReference: {fileID: 2100000, guid: a27f6a86443ed324b9b2b33f454362d5, type: 2}
m_RemovedComponents: []
m_ParentPrefab: {fileID: 100100000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
m_RootGameObject: {fileID: 1911580615}
m_IsPrefabParent: 0
--- !u!1001 &1088192932
Prefab:
@@ -681,7 +612,7 @@ Prefab:
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
propertyPath: m_RootOrder
value: 1
value: 0
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
@@ -689,7 +620,7 @@ Prefab:
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
propertyPath: m_LocalScale.y
value: 1.3
value: 1.46
objectReference: {fileID: 0}
- target: {fileID: 400000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
propertyPath: m_LocalScale.x
@@ -705,7 +636,6 @@ Prefab:
objectReference: {fileID: 0}
m_RemovedComponents: []
m_ParentPrefab: {fileID: 100100000, guid: 1c5bba6be1fcdea4495ee17c17a605b2, type: 3}
m_RootGameObject: {fileID: 644361509}
m_IsPrefabParent: 0
--- !u!1 &1222475224
GameObject:
@@ -826,7 +756,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
radius: 0.1
negativeBall: 0
radiusSq: 0
factor: 0
speed: 0.35
--- !u!1 &1328914960
GameObject:
@@ -890,7 +820,7 @@ Transform:
m_LocalEulerAnglesHint: {x: 62.472004, y: -51.281002, z: -0.003}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 5
m_RootOrder: 4
--- !u!1 &1427553063
GameObject:
m_ObjectHideFlags: 0
@@ -933,7 +863,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
radius: 0.2
negativeBall: 0
radiusSq: 0
factor: 0
speed: 0.2
--- !u!1 &1476788083
GameObject:
@@ -1226,76 +1156,11 @@ Transform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
--- !u!1 &1911580615
m_RootOrder: 3
--- !u!1 &1911580615 stripped
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 100000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
m_PrefabInternal: {fileID: 918589879}
serializedVersion: 4
m_Component:
- 4: {fileID: 1911580618}
- 33: {fileID: 1911580617}
- 23: {fileID: 1911580616}
- 64: {fileID: 1911580619}
m_Layer: 0
m_Name: Oltar
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!23 &1911580616
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 2300000, guid: 383074ff06605fc4fb7a07e2ab971c02,
type: 3}
m_PrefabInternal: {fileID: 918589879}
m_GameObject: {fileID: 1911580615}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: a27f6a86443ed324b9b2b33f454362d5, type: 2}
m_SubsetIndices:
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedWireframeHidden: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingOrder: 0
--- !u!33 &1911580617
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 3300000, guid: 383074ff06605fc4fb7a07e2ab971c02,
type: 3}
m_PrefabInternal: {fileID: 918589879}
m_GameObject: {fileID: 1911580615}
m_Mesh: {fileID: 4300000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
--- !u!4 &1911580618
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 400000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
m_PrefabInternal: {fileID: 918589879}
m_GameObject: {fileID: 1911580615}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 2, y: 2, z: 2}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
--- !u!64 &1911580619
MeshCollider:
m_ObjectHideFlags: 0
@@ -1308,3 +1173,45 @@ MeshCollider:
serializedVersion: 2
m_Convex: 0
m_Mesh: {fileID: 4300000, guid: 383074ff06605fc4fb7a07e2ab971c02, type: 3}
--- !u!1 &2089509238
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 2089509240}
- 114: {fileID: 2089509239}
m_Layer: 0
m_Name: LookingAt
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &2089509239
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2089509238}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 24cb69fe161959e4482830da76a519d1, type: 3}
m_Name:
m_EditorClassIdentifier:
speed: 8
--- !u!4 &2089509240
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2089509238}
m_LocalRotation: {x: 0, y: -0.5, z: 0, w: 0.8660254}
m_LocalPosition: {x: 0, y: 2.2, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: -60, z: 0}
m_Children:
- {fileID: 909959530}
m_Father: {fileID: 0}
m_RootOrder: 5

View File

@@ -69,6 +69,12 @@ Material:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _SpecGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
@@ -87,13 +93,13 @@ Material:
second: 1
- first:
name: _Glossiness
second: 0
second: 0.826
- first:
name: _GlossyReflections
second: 1
- first:
name: _Metallic
second: 0
second: 0.27
- first:
name: _Mode
second: 0
@@ -121,7 +127,10 @@ Material:
m_Colors:
- first:
name: _Color
second: {r: 0.14987026, g: 0.9705882, b: 0.25741273, a: 0}
second: {r: 0.12867649, g: 0.875, b: 0.31911755, a: 1}
- first:
name: _EmissionColor
second: {r: 0.13516438, g: 0.9191176, b: 0.2378894, a: 1}
second: {r: 0.13788973, g: 0.893, b: 0.36181897, a: 1}
- first:
name: _SpecColor
second: {r: 0.2, g: 0.2, b: 0.2, a: 1}

View File

@@ -0,0 +1,136 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: StandardMetaballMaterial
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
m_LightmapFlags: 0
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
- first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- first:
name: _SpecGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- first:
name: _BumpScale
second: 1
- first:
name: _Cutoff
second: 0.5
- first:
name: _DetailNormalMapScale
second: 1
- first:
name: _DstBlend
second: 0
- first:
name: _GlossMapScale
second: 0.528
- first:
name: _Glossiness
second: 0.807
- first:
name: _GlossyReflections
second: 1
- first:
name: _Metallic
second: 0.553
- first:
name: _Mode
second: 0
- first:
name: _OcclusionStrength
second: 1
- first:
name: _Parallax
second: 0.02
- first:
name: _SmoothnessTextureChannel
second: 1
- first:
name: _SpecularHighlights
second: 1
- first:
name: _SrcBlend
second: 1
- first:
name: _UVSec
second: 0
- first:
name: _ZWrite
second: 1
m_Colors:
- first:
name: _Color
second: {r: 0.3455882, g: 0.6208924, b: 1, a: 1}
- first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}
- first:
name: _SpecColor
second: {r: 0.012651396, g: 0.4744704, b: 0.8602941, a: 1}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fc349da3bdf30e4469786e146c823cc1
timeCreated: 1474114151
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,7 +1,7 @@
using UnityEngine;
using System.Collections;
public class BouncingBall : Ball {
public class BouncingBall : MetaBall {
public float speed;
private Container container;

View File

@@ -7,21 +7,24 @@ public class Container : MonoBehaviour {
public float resolution;
public float threshold;
public ComputeShader computeShader;
public bool calculateNormals;
private CubeGrid grid;
public void Start() {
Ball[] metaballs = this.GetComponentsInChildren<Ball>();
this.grid = new CubeGrid(this, this.resolution, this.threshold, this.computeShader, metaballs);
this.grid = new CubeGrid(this, this.computeShader);
}
public void Update() {
this.grid.evaluateAll();
this.grid.evaluateAll(this.GetComponentsInChildren<MetaBall>());
Mesh mesh = this.GetComponent<MeshFilter>().mesh;
mesh.Clear();
mesh.vertices = this.grid.vertices.ToArray();
mesh.triangles = this.grid.getTriangles();
if(this.calculateNormals) {
mesh.RecalculateNormals();
}
}
}

View File

@@ -7,81 +7,83 @@ struct GPUEdgeValues {
}
struct GPUPositions {
public Vector3 centerPos;
public Vector3 edge0Pos, edge1Pos, edge2Pos, edge3Pos, edge4Pos, edge5Pos, edge6Pos, edge7Pos;
}
struct GPUBall {
public float radiusSq;
public float factor;
public Vector3 position;
}
struct GPUEdgeVertices {
public int index;
public Vector3 edge0, edge1, edge2, edge3, edge4, edge5, edge6, edge7, edge8, edge9, edge10, edge11;
};
public class CubeGrid {
public List<Vector3> vertices;
public int width, height, depth;
public float resolution;
private Container container;
private Ball[] metaballs;
private float threshold;
private ComputeShader shader;
private int shaderKernel;
private GPUPositions[] precomputedPositions;
private ComputeBuffer positionsBuffer;
private ComputeBuffer outputBuffer;
private ComputeBuffer valuesBuffer;
private ComputeBuffer metaballsBuffer;
private ComputeBuffer edgeMapBuffer;
private ComputeBuffer verticesBuffer;
public const bool useGPU = true;
private GPUPositions[] precomputedPositions;
public CubeGrid(Container container, float resolution, float threshold, ComputeShader shader, Ball[] metaballs) {
this.width = Mathf.RoundToInt(container.transform.localScale.x / resolution);
this.height = Mathf.RoundToInt(container.transform.localScale.y / resolution);
this.depth = Mathf.RoundToInt(container.transform.localScale.z / resolution);
private bool initized;
//
// Constructor
//
public CubeGrid(Container container, ComputeShader shader) {
this.container = container;
this.shader = shader;
this.width = Mathf.RoundToInt(container.transform.localScale.x / this.container.resolution);
this.height = Mathf.RoundToInt(container.transform.localScale.y / this.container.resolution);
this.depth = Mathf.RoundToInt(container.transform.localScale.z / this.container.resolution);
this.vertices = new List<Vector3>();
this.container = container;
this.resolution = resolution;
this.threshold = threshold;
this.shader = shader;
this.metaballs = metaballs;
this.init();
this.initized = false;
}
public void evaluateAll() {
//
// Public methods
//
public void evaluateAll(MetaBall[] metaballs) {
if(!this.initized) {
this.init();
}
this.vertices.Clear();
// write info about metaballs in format readable by compute shaders
GPUBall[] gpuBalls = new GPUBall[metaballs.Length];
for(int i = 0; i < metaballs.Length; i++) {
MetaBall metaball = metaballs[i];
gpuBalls[i].position = metaball.transform.localPosition;
gpuBalls[i].factor = metaball.factor;
}
// magic happens here
GPUEdgeVertices[] edgeVertices = this.runComputeShader(gpuBalls);
if(CubeGrid.useGPU) {
GPUBall[] gpuBalls = new GPUBall[this.metaballs.Length];
for(int i = 0; i < this.metaballs.Length; i++) {
Ball metaball = this.metaballs[i];
gpuBalls[i].position = metaball.transform.localPosition;
gpuBalls[i].radiusSq = metaball.radiusSq;
}
GPUEdgeValues[] edgeValues = this.runComputeShader(gpuBalls);
for(int x = 0; x < this.width; x++) {
for(int y = 0; y < this.height; y++) {
for(int z = 0; z < this.depth; z++) {
GPUEdgeValues edgeVal = edgeValues[x + this.width * (y + this.height * z)];
float[] edges = { edgeVal.edge0Val, edgeVal.edge1Val, edgeVal.edge2Val, edgeVal.edge3Val,
edgeVal.edge4Val, edgeVal.edge5Val, edgeVal.edge6Val, edgeVal.edge7Val};
this.updateVertices(edges, this.positionMap[x, y, z]);
}
}
}
} else {
for(int x = 0; x < this.width; x++) {
for(int y = 0; y < this.height; y++) {
for(int z = 0; z < this.depth; z++) {
Vector3 relativePosition = this.positionMap[x, y, z];
float[] edges = this.evaluateCube(relativePosition);
this.updateVertices(edges, relativePosition);
}
// perform rest of the marching cubes algorithm
for(int x = 0; x < this.width; x++) {
for(int y = 0; y < this.height; y++) {
for(int z = 0; z < this.depth; z++) {
this.updateVertices2(edgeVertices[x + this.width * (y + this.height * z)]);
}
}
}
@@ -118,8 +120,10 @@ public class CubeGrid {
public void destroy() {
this.positionsBuffer.Release();
this.outputBuffer.Release();
this.valuesBuffer.Release();
this.metaballsBuffer.Release();
this.edgeMapBuffer.Release();
this.verticesBuffer.Release();
this.triangleBuffer = null;
}
@@ -130,11 +134,10 @@ public class CubeGrid {
private void init() {
this.instantiateEdgeMap();
this.instantiatePositionMap();
this.instantiateGPUPositions();
this.instantiateComputeShader();
if(CubeGrid.useGPU) {
this.instantiateGPUPositions();
this.instantiateComputeShader();
}
this.initized = true;
}
private void instantiateEdgeMap() {
@@ -149,6 +152,7 @@ public class CubeGrid {
new Vector3(-1, 1, 1)
};
// scale edge map
for(int i = 0; i < 8; i++) {
this.edgeMap[i] /= 2;
this.edgeMap[i] = new Vector3(this.edgeMap[i].x / ((float) this.width),
@@ -181,6 +185,7 @@ public class CubeGrid {
for(int y = 0; y < this.height; y++) {
for(int z = 0; z < this.depth; z++) {
Vector3 centerPoint = this.positionMap[x, y, z];
this.precomputedPositions[x + this.width * (y + this.height * z)].centerPos = centerPoint;
this.precomputedPositions[x + this.width * (y + this.height * z)].edge0Pos = centerPoint + this.edgeMap[0];
this.precomputedPositions[x + this.width * (y + this.height * z)].edge1Pos = centerPoint + this.edgeMap[1];
@@ -196,131 +201,86 @@ public class CubeGrid {
}
private void instantiateComputeShader() {
this.positionsBuffer = new ComputeBuffer(this.precomputedPositions.Length, 96);
// setup buffers
this.positionsBuffer = new ComputeBuffer(this.precomputedPositions.Length, 108);
this.positionsBuffer.SetData(this.precomputedPositions);
this.outputBuffer = new ComputeBuffer(this.precomputedPositions.Length, 32);
this.edgeMapBuffer = new ComputeBuffer(8, 12);
this.edgeMapBuffer.SetData(this.edgeMap);
this.verticesBuffer = new ComputeBuffer(this.precomputedPositions.Length, 148);
this.metaballsBuffer = new ComputeBuffer(this.precomputedPositions.Length, 16);
this.shaderKernel = shader.FindKernel("Calculate");
this.shader.SetBuffer(this.shaderKernel, "positions", this.positionsBuffer);
this.shader.SetBuffer(this.shaderKernel, "outputBuffer", this.outputBuffer);
// and assign them to compute shader buffer
this.shaderKernel = this.shader.FindKernel("Calculate");
this.shader.SetInt("width", this.width);
this.shader.SetInt("height", this.height);
this.shader.SetBuffer(this.shaderKernel, "positions", this.positionsBuffer);
this.shader.SetBuffer(this.shaderKernel, "metaballs", this.metaballsBuffer);
this.shader.SetBuffer(this.shaderKernel, "edgeMap", this.edgeMapBuffer);
this.shader.SetBuffer(this.shaderKernel, "edgeVertices", this.verticesBuffer);
}
//
// GPU metaball falloff function summator
// GPU metaball falloff function summator & part of marching cubes algorithm
//
private GPUEdgeValues[] runComputeShader(GPUBall[] gpuBalls) {
private GPUEdgeVertices[] runComputeShader(GPUBall[] gpuBalls) {
// pass data to the compute shader
this.metaballsBuffer.SetData(gpuBalls);
this.shader.SetBuffer(this.shaderKernel, "metaballs", this.metaballsBuffer);
this.shader.SetInt("numMetaballs", this.metaballs.Length);
this.shader.SetInt("numMetaballs", gpuBalls.Length);
this.shader.SetInt("width", this.width);
this.shader.SetInt("height", this.height);
this.shader.SetFloat("threshold", this.container.threshold);
// Run, Forrest, run!
this.shader.Dispatch(this.shaderKernel, this.width / 8, this.height / 8, this.depth / 8);
GPUEdgeValues[] output = new GPUEdgeValues[this.precomputedPositions.Length];
this.outputBuffer.GetData(output);
// parse returned vertex data and return it
GPUEdgeVertices[] output = new GPUEdgeVertices[this.verticesBuffer.count];
this.verticesBuffer.GetData(output);
return output;
}
//
// CPU metaball falloff function summator
// Rest of marching cubes algorithm (on CPU)
//
private float[] evaluateCube(Vector3 centerPoint) {
float[] edges = new float[8];
for(int i = 0; i < 8; i++) {
edges[i] = this.evaluatePoint(centerPoint + this.edgeMap[i]);
}
return edges;
}
private float evaluatePoint(Vector3 point) {
float value = 0;
foreach(Ball ball in this.metaballs) {
Vector3 ballPosition = ball.transform.localPosition;
float distX = point.x - ballPosition.x,
distY = point.y - ballPosition.y,
distZ = point.z - ballPosition.z;
value += ball.radiusSq / (distX * distX + distY * distY + distZ * distZ);
}
return value;
}
//
// Marching cubes algorithm
//
private void updateVertices(float[] edges, Vector3 relativePosition) {
int cubeIndex = this.findIndex(edges);
int pattern = this.edgeTable[cubeIndex];
Vector3[] edgeVertices = new Vector3[12];
for(int edge = 0; edge < 12; edge++) {
if((pattern & 1 << edge) != 0) {
int vertIndex0 = this.verticesAtEndsOfEdges[edge * 2];
int vertIndex1 = this.verticesAtEndsOfEdges[edge * 2 + 1];
float vertValue0 = edges[vertIndex0];
float vertValue1 = edges[vertIndex1];
Vector3 vertPosition0 = relativePosition + this.edgeMap[vertIndex0];
Vector3 vertPosition1 = relativePosition + this.edgeMap[vertIndex1];
float delta = (threshold - vertValue0) / (vertValue1 - vertValue0);
// lineary interpolate positions
edgeVertices[edge] = vertPosition0 + delta * (vertPosition1 - vertPosition0);
}
}
private void updateVertices2(GPUEdgeVertices vert) {
int cubeIndex = vert.index;
for(int k = 0; triTable[cubeIndex][k] != -1; k += 3) {
this.vertices.Add(edgeVertices[this.triTable[cubeIndex][k]]);
this.vertices.Add(edgeVertices[this.triTable[cubeIndex][k + 2]]);
this.vertices.Add(edgeVertices[this.triTable[cubeIndex][k + 1]]);
this.vertices.Add(this.findVertex(vert, this.triTable[cubeIndex][k]));
this.vertices.Add(this.findVertex(vert, this.triTable[cubeIndex][k + 2]));
this.vertices.Add(this.findVertex(vert, this.triTable[cubeIndex][k + 1]));
}
}
private int findIndex(float[] edges) {
byte cubeIndex = 0;
if(edges[0] > this.threshold) {
cubeIndex |= 1;
private Vector3 findVertex(GPUEdgeVertices vert, int i) {
if(i == 0) {
return vert.edge0;
} else if(i == 1) {
return vert.edge1;
} else if(i == 2) {
return vert.edge2;
} else if(i == 3) {
return vert.edge3;
} else if(i == 4) {
return vert.edge4;
} else if(i == 5) {
return vert.edge5;
} else if(i == 6) {
return vert.edge6;
} else if(i == 7) {
return vert.edge7;
} else if(i == 8) {
return vert.edge8;
} else if(i == 9) {
return vert.edge9;
} else if(i == 10) {
return vert.edge10;
} else {
return vert.edge11;
}
if(edges[1] > this.threshold) {
cubeIndex |= 2;
}
if(edges[2] > this.threshold) {
cubeIndex |= 4;
}
if(edges[3] > this.threshold) {
cubeIndex |= 8;
}
if(edges[4] > this.threshold) {
cubeIndex |= 16;
}
if(edges[5] > this.threshold) {
cubeIndex |= 32;
}
if(edges[6] > this.threshold) {
cubeIndex |= 64;
}
if(edges[7] > this.threshold) {
cubeIndex |= 128;
}
// return index
return cubeIndex;
}
//
@@ -332,56 +292,6 @@ public class CubeGrid {
private Vector3[,,] positionMap;
private Vector3[] edgeMap;
private int[] edgeTable = {
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
};
private int[] verticesAtEndsOfEdges = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
private int[][] triTable = {
new int[] {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},

View File

@@ -1,32 +0,0 @@
using UnityEngine;
using System.Collections;
public class Draggable : MonoBehaviour {
private Rigidbody rigid;
private float zDist;
void Start () {
this.rigid = this.GetComponent<Rigidbody>();
}
void Update () {
}
void OnMouseDown() {
this.rigid.useGravity = false;
this.zDist = Vector3.Distance(Camera.main.transform.position, this.transform.position);
}
void OnMouseDrag() {
Vector3 mousePos = Input.mousePosition;
mousePos.z = zDist;
this.transform.position = Camera.main.ScreenToWorldPoint(mousePos);
}
void OnMouseUp() {
this.rigid.useGravity = true;
this.rigid.velocity = Vector3.zero;
this.rigid.angularVelocity = Vector3.zero;
}
}

View File

@@ -1,14 +1,14 @@
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
public class MetaBall : MonoBehaviour {
public float radius;
public bool negativeBall;
[HideInInspector]
public float radiusSq;
public float factor;
public virtual void Start() {
this.radiusSq = (this.negativeBall ? -1 : 1) * this.radius * this.radius;
this.factor = (this.negativeBall ? -1 : 1) * this.radius * this.radius;
}
}

View File

@@ -3,7 +3,7 @@ using System.Collections;
[RequireComponent(typeof(Light))]
public class MetaLight : MonoBehaviour {
public Ball linkedMetaball;
public MetaBall linkedMetaball;
public float intensity;
private float phaseShift;

View File

@@ -0,0 +1,14 @@
using UnityEngine;
using System.Collections;
public class RotateCamera : MonoBehaviour {
public float speed;
void Start () {
}
void Update () {
this.transform.Rotate(Vector3.up, this.speed * Time.deltaTime);
}
}

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: 8a2531f70d23d81468bd48d3d7bee962
timeCreated: 1472299829
guid: 24cb69fe161959e4482830da76a519d1
timeCreated: 1474113420
licenseType: Free
MonoImporter:
serializedVersion: 2

View File

@@ -1,64 +0,0 @@
#pragma kernel Calculate
struct Values {
float edge0Val, edge1Val, edge2Val, edge3Val, edge4Val, edge5Val, edge6Val, edge7Val;
};
struct Positions {
float3 edge0Pos, edge1Pos, edge2Pos, edge3Pos, edge4Pos, edge5Pos, edge6Pos, edge7Pos;
};
struct Ball {
float radiusSq;
float3 position;
};
StructuredBuffer<Positions> positions;
StructuredBuffer<Ball> metaballs;
RWStructuredBuffer<Values> outputBuffer;
int width;
int height;
int numMetaballs;
[numthreads(8,8,8)]
void Calculate(uint3 id : SV_DispatchThreadID)
{
int pos = id.x + width * (id.y + height * id.z);
outputBuffer[pos].edge0Val = 0;
outputBuffer[pos].edge1Val = 0;
outputBuffer[pos].edge2Val = 0;
outputBuffer[pos].edge3Val = 0;
outputBuffer[pos].edge4Val = 0;
outputBuffer[pos].edge5Val = 0;
outputBuffer[pos].edge6Val = 0;
outputBuffer[pos].edge7Val = 0;
for (int i = 0; i < numMetaballs; i++) {
float3 dist = positions[pos].edge0Pos - metaballs[i].position;
outputBuffer[pos].edge0Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge1Pos - metaballs[i].position;
outputBuffer[pos].edge1Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge2Pos - metaballs[i].position;
outputBuffer[pos].edge2Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge3Pos - metaballs[i].position;
outputBuffer[pos].edge3Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge4Pos - metaballs[i].position;
outputBuffer[pos].edge4Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge5Pos - metaballs[i].position;
outputBuffer[pos].edge5Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge6Pos - metaballs[i].position;
outputBuffer[pos].edge6Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
dist = positions[pos].edge7Pos - metaballs[i].position;
outputBuffer[pos].edge7Val += metaballs[i].radiusSq / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
}
}

View File

@@ -0,0 +1,283 @@
#pragma kernel Calculate
// Define fallof function to be used. Options: GENERIC_METABALL_FUNCTION, ELECTRIC_POTENTIAL_FUNCTION
#define GENERIC_METABALL_FUNCTION
//
// structs and buffers associated with them
//
struct Values {
float edge0Val, edge1Val, edge2Val, edge3Val, edge4Val, edge5Val, edge6Val, edge7Val;
};
struct Positions {
float3 centerPos;
float3 edge0Pos, edge1Pos, edge2Pos, edge3Pos, edge4Pos, edge5Pos, edge6Pos, edge7Pos;
};
struct Vertices {
int index;
float3 edge0, edge1, edge2, edge3, edge4, edge5, edge6, edge7, edge8, edge9, edge10, edge11;
};
struct Ball {
float factor;
float3 position;
};
StructuredBuffer<Positions> positions;
StructuredBuffer<Ball> metaballs;
StructuredBuffer<float3> edgeMap;
RWStructuredBuffer<Vertices> edgeVertices;
//
// misc variables
//
int width;
int height;
int numMetaballs;
float threshold;
//
// lookup tables
//
static uint edgeTable[256] = {
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0
};
static int verticesAtEndsOfEdges[24] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
//
// helper functions
//
int findIndex(Values edgeValue) {
int cubeIndex = 0;
if (edgeValue.edge0Val > threshold) {
cubeIndex += 1;
}
if (edgeValue.edge1Val > threshold) {
cubeIndex += 2;
}
if (edgeValue.edge2Val > threshold) {
cubeIndex += 4;
}
if (edgeValue.edge3Val > threshold) {
cubeIndex += 8;
}
if (edgeValue.edge4Val > threshold) {
cubeIndex += 16;
}
if (edgeValue.edge5Val > threshold) {
cubeIndex += 32;
}
if (edgeValue.edge6Val > threshold) {
cubeIndex += 64;
}
if (edgeValue.edge7Val > threshold) {
cubeIndex += 128;
}
return cubeIndex;
}
float getValueAtEdge(Values val, int i) {
if (i == 0) {
return val.edge0Val;
}
else if (i == 1) {
return val.edge1Val;
}
else if (i == 2) {
return val.edge2Val;
}
else if (i == 3) {
return val.edge3Val;
}
else if (i == 4) {
return val.edge4Val;
}
else if (i == 5) {
return val.edge5Val;
}
else if (i == 6) {
return val.edge6Val;
}
else {
return val.edge7Val;
}
}
Values zeroValuesStruct() {
Values val;
val.edge0Val = 0;
val.edge1Val = 0;
val.edge2Val = 0;
val.edge3Val = 0;
val.edge4Val = 0;
val.edge5Val = 0;
val.edge6Val = 0;
val.edge7Val = 0;
return val;
}
//
// field function evaluation
//
float metaballFalloffFunction(float factor, float3 dist) {
#ifdef GENERIC_METABALL_FUNCTION
return factor / (dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
#endif
#ifdef ELECTRIC_POTENTIAL_FUNCTION
return 8.987551788e9 * factor / sqrt(dist.x * dist.x + dist.y * dist.y + dist.z * dist.z);
#endif
}
Values evaluateFieldFunction(int pos) {
Values edgeValues = zeroValuesStruct();
for (int i = 0; i < numMetaballs; i++) {
float3 dist = positions[pos].edge0Pos - metaballs[i].position;
edgeValues.edge0Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge1Pos - metaballs[i].position;
edgeValues.edge1Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge2Pos - metaballs[i].position;
edgeValues.edge2Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge3Pos - metaballs[i].position;
edgeValues.edge3Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge4Pos - metaballs[i].position;
edgeValues.edge4Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge5Pos - metaballs[i].position;
edgeValues.edge5Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge6Pos - metaballs[i].position;
edgeValues.edge6Val += metaballFalloffFunction(metaballs[i].factor, dist);
dist = positions[pos].edge7Pos - metaballs[i].position;
edgeValues.edge7Val += metaballFalloffFunction(metaballs[i].factor, dist);
}
return edgeValues;
}
//
// computer shader kernel
//
[numthreads(8,8,8)]
void Calculate(uint3 id : SV_DispatchThreadID) {
int pos = id.x + width * (id.y + height * id.z);
// find scalar values of a field on this position
Values edgeValues = evaluateFieldFunction(pos);
// partial marching cubes algorithm
int cubeIndex = findIndex(edgeValues);
int pattern = edgeTable[cubeIndex];
float3 verticesArr[12] = {
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0),
float3(0, 0, 0)
};
for (int edge = 0; edge < 12; edge++) {
if ((pattern & 1 << edge) != 0) {
int vertIndex0 = verticesAtEndsOfEdges[(int)(edge * 2)];
int vertIndex1 = verticesAtEndsOfEdges[(int)(edge * 2 + 1)];
float vertValue0 = getValueAtEdge(edgeValues, vertIndex0);
float vertValue1 = getValueAtEdge(edgeValues, vertIndex1);
float3 vertPosition0 = positions[pos].centerPos + edgeMap[vertIndex0];
float3 vertPosition1 = positions[pos].centerPos + edgeMap[vertIndex1];
float delta = (threshold - vertValue0) / (vertValue1 - vertValue0);
// lineary interpolate positions for smooth surface
verticesArr[edge] = vertPosition0 + delta * (vertPosition1 - vertPosition0);
}
}
// save processed data to edgeVertices buffer
edgeVertices[pos].index = cubeIndex;
edgeVertices[pos].edge0 = verticesArr[0];
edgeVertices[pos].edge1 = verticesArr[1];
edgeVertices[pos].edge2 = verticesArr[2];
edgeVertices[pos].edge3 = verticesArr[3];
edgeVertices[pos].edge4 = verticesArr[4];
edgeVertices[pos].edge5 = verticesArr[5];
edgeVertices[pos].edge6 = verticesArr[6];
edgeVertices[pos].edge7 = verticesArr[7];
edgeVertices[pos].edge8 = verticesArr[8];
edgeVertices[pos].edge9 = verticesArr[9];
edgeVertices[pos].edge10 = verticesArr[10];
edgeVertices[pos].edge11 = verticesArr[11];
}

View File

@@ -1,6 +1,6 @@
fileFormatVersion: 2
guid: bd5d7027d3c30804a9dd9ea57ed5f351
timeCreated: 1474039237
guid: 9bcc9560470e2b4439e048851b4c0470
timeCreated: 1474220478
licenseType: Free
ComputeShaderImporter:
currentAPIMask: 4

View File

@@ -4,16 +4,15 @@ Unity 3D implementation of marching cubes algorithm for rendering metaballs. Met
![](https://github.com/dario-zubovic/metaballs/raw/master/gif1.gif)
![](https://github.com/dario-zubovic/metaballs/raw/master/gif2.gif)
Metaball functions are envaluated on either GPU or CPU. GPU mode performs about 10x faster than CPU. Currently there is only one falloff functions available:
Metaball functions are evaluated on GPU. Falloff functions can be chosen in the compute shader with a define statements. Marching cubes algorithm partially executes on GPU and partially on CPU.
```f(d) = r^2 / d^2```
Where *r* is radius of the metaball, and *d* is distance from metaball's center to current point. Additional functions can be quickly added as a new compute shader.
Thanks to Filip Ugrin for providing 3d models for example scene!
## TODO list:
* add more falloff functions
* move marching cubes algorithm to GPU
* ~~move marching cubes algorithm to GPU~~ partially moved marching cubes to compute shader, but there is still room for improvement
* implement some kind of subdivision smoothing algorithm
* create example scene with rigidbody metaballs
* create example scene with electric potential visualization
## References:
* William E. Lorensen and Harvey E. Cline. 1987. Marching cubes: A high resolution 3D surface construction algorithm. In Proceedings of the 14th annual conference on Computer graphics and interactive techniques (SIGGRAPH '87), Maureen C. Stone (Ed.). ACM, New York, NY, USA, 163-169.

BIN
gif.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 MiB