vat-animation.chunk 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include <common/math/transform>
  2. #include <common/texture/texture-misc>
  3. // Vertex Animation Texture (VAT), baked physically simulation result for rigid-body, soft-body and fluid
  4. // Houdini VAT Plugin Version:
  5. // 1. Soft-body and fluids use 3.0, Select Unity mode, otherwise animation will become crack
  6. // 2. Rigid-body use 2.0, Select UE mode with initialize settings, needs export json for numOfFrames(frameCount) and max/min values
  7. // Houdini misc export settings:
  8. // 1. Select LDR
  9. // 2. Do not check paddle, two-position textures and pack normals
  10. // Cocos import settings:
  11. // 1. LUT texture should set filter to "nearest" and uncheck "fix alpha transparency"
  12. // 2. Rigid-body select import normal and tangent
  13. // 3. Rigid-body and soft-body need check HAS_SECOND_UV
  14. // 4. If no sign texture with exr image, use white texture instead
  15. // For resources exported by UE mode, invoke functions like:
  16. // 1. VATFunction(inout_pos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE, inout_vector.xzy);
  17. // 2. out_pos.xyz = inout_pos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  18. // 2. out_vector.xyz = inout_vector.xzy;
  19. #define VAT_FBX_TO_COCOS_COORDINATE_SCALE 0.01
  20. #define VAT_LUT_PRECISION_VALUE_LDR 255.0
  21. #define VAT_LUT_PRECISION_VALUE_HDR 2048.0
  22. float CalculateVATAnimationUV(out vec2 deltaV, float frameCount, float animSpeed, float elapseTime)
  23. {
  24. float thisFrame = fract(animSpeed * elapseTime);
  25. thisFrame = floor(thisFrame * frameCount);
  26. float thisFrameDeltaV = thisFrame / frameCount;
  27. float nextFrameDeltaV = (thisFrame + 1.0) / frameCount;
  28. deltaV = vec2(thisFrameDeltaV, nextFrameDeltaV);
  29. float frameLerp = fract(thisFrame * frameCount);
  30. return frameLerp;
  31. }
  32. ///////////////////////////////////////////// public functions
  33. // auto calculation frame count for fluid
  34. float VATCalculateFrameCount(vec2 lutTexResolution, float meshVertexCount)
  35. {
  36. float lineCountPerFrame = ceil(meshVertexCount / lutTexResolution.x);
  37. return floor(lutTexResolution.y / lineCountPerFrame);
  38. }
  39. // meshUV use texCoord0 for fluid
  40. // meshUV use texCoord1 for rigid-body and soft-body
  41. float VATGetAnimUV(out vec2 thisFrameUV, out vec2 nextFrameUV, vec2 meshUV, float frameCount, float animSpeed, float elapseTime)
  42. {
  43. vec2 frameDeltaV;
  44. float frameLerp = CalculateVATAnimationUV(frameDeltaV, frameCount, animSpeed, elapseTime);
  45. thisFrameUV = meshUV + vec2(0.0, frameDeltaV.x);
  46. nextFrameUV = meshUV + vec2(0.0, frameDeltaV.y);
  47. return frameLerp;
  48. }
  49. // VAT with LUT, fluid only
  50. float VATGetAnimUV(out vec2 thisFrameUV, out vec2 nextFrameUV, vec2 meshUV, float frameCount, float animSpeed, float elapseTime, sampler2D lutTexture)
  51. {
  52. vec2 frameDeltaV;
  53. float frameLerp = CalculateVATAnimationUV(frameDeltaV, frameCount, animSpeed, elapseTime);
  54. vec4 thisFramelookUpValue = texture(lutTexture, meshUV + vec2(0.0, frameDeltaV.x));
  55. thisFrameUV = thisFramelookUpValue.xz + thisFramelookUpValue.yw / VAT_LUT_PRECISION_VALUE_LDR;
  56. vec4 nextFramelookUpValue = texture(lutTexture, meshUV + vec2(0.0, frameDeltaV.y));
  57. nextFrameUV = nextFramelookUpValue.xz + nextFramelookUpValue.yw / VAT_LUT_PRECISION_VALUE_LDR;
  58. return frameLerp;
  59. }
  60. // return absolute position for fluid
  61. // return position offset for soft-body
  62. vec3 VATGetLocalPosition(vec2 thisFrameUV, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture)
  63. {
  64. vec3 thisFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
  65. return thisFramePos * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  66. }
  67. // meshNormal is up-axis for fluid
  68. vec3 VATGetLocalNormal(vec3 meshNormal, vec2 thisFrameUV, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  69. {
  70. vec4 thisFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
  71. rotateVecFromQuat(meshNormal, thisFrameData);
  72. return meshNormal;
  73. }
  74. // for smooth animation
  75. vec3 VATGetLocalPosition(vec2 thisFrameUV, vec2 nextFrameUV, float frameLerp, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture)
  76. {
  77. vec3 thisFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
  78. vec3 nextFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, nextFrameUV);
  79. return mix(thisFramePos, nextFramePos, frameLerp) * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  80. }
  81. vec3 VATGetLocalNormal(vec3 meshNormal, vec2 thisFrameUV, vec2 nextFrameUV, float frameLerp, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  82. {
  83. vec4 thisFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
  84. vec4 nextFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, nextFrameUV);
  85. vec4 data = mix(thisFrameData, nextFrameData, frameLerp);
  86. rotateVecFromQuat(meshNormal, data);
  87. return meshNormal;
  88. }
  89. // calculate simulation voxel coordinates
  90. vec3 VATCalculateFluidVoxelUV(vec3 vatBoundingBoxMin, vec3 vatBoundingBoxMax, vec3 localPos)
  91. {
  92. // bounding box in exported json is unscaled
  93. vatBoundingBoxMin *= VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  94. vatBoundingBoxMax *= VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  95. vec3 size = vatBoundingBoxMax - vatBoundingBoxMin;
  96. vec3 coef = (localPos - vatBoundingBoxMin) / size;
  97. return coef;
  98. }
  99. ////////////////////////////////////////////////////////////////Rigid-body
  100. void VATGetLocalPositionRigidBody20(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec4 meshVertexColor, vec2 thisFrameUV, float pivMax, float pivMin, float posMax, float posMin, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  101. {
  102. // pivot
  103. float pivExpand = pivMax - pivMin;
  104. float posExpand = posMax - posMin;
  105. vec3 pivot = meshVertexColor.xyz;
  106. pivot.xyz *= pivExpand;
  107. pivot.xyz += vec3(pivMin);
  108. // anim pos
  109. vec3 posData = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
  110. vec3 texturePos = posData;
  111. texturePos.xyz *= posExpand;
  112. texturePos.xyz += posMin;
  113. // rotate pos
  114. vec4 quat = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
  115. quat = quat * 2.0 - vec4(1.0);
  116. vec3 originPos = meshLocalPos - pivot;
  117. vec3 rotatedPos;
  118. rotatedPos = 2.0 * cross(quat.xyz, cross(quat.xyz, originPos.xyz) + quat.w * originPos.xyz);
  119. // result
  120. meshLocalPos = meshLocalPos + rotatedPos + texturePos;
  121. rotateVecFromQuat(meshLocalNormal, quat);
  122. rotateVecFromQuat(meshLocalTangent, quat);
  123. }
  124. void VATGetLocalPositionRigidBody20_UE(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec4 meshVertexColor, vec2 thisFrameUV, float pivMax, float pivMin, float posMax, float posMin, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  125. {
  126. // input
  127. vec3 preSkinnedPos = meshLocalPos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  128. vec3 preSkinnedNorm = meshLocalNormal.xzy;
  129. vec3 preSkinnedTangent = meshLocalTangent.xzy;
  130. VATGetLocalPositionRigidBody20(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshVertexColor, thisFrameUV, pivMax, pivMin, posMax, posMin, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture);
  131. // output
  132. meshLocalPos.xyz = preSkinnedPos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  133. meshLocalNormal.xyz = preSkinnedNorm.xzy;
  134. meshLocalTangent.xyz = preSkinnedTangent.xzy;
  135. }
  136. // Experimental
  137. float CalculateVATDecodeUV(float A, float B)
  138. {
  139. #if __VERSION__ >= 110
  140. uint a = floatBitsToUint(A); //asuint(A)
  141. uint b = floatBitsToUint(B);
  142. a = ((a >> 16u) & 0x8000u) |
  143. ((((a >> 23u) & 0xFFu) - 112u) << 10u) |
  144. ((a >> 13u) & 0x3FFu);
  145. b = ((b >> 16u) & 0x8000u) |
  146. ((((b >> 23u) & 0xFFu) - 112u) << 10u) |
  147. ((b >> 13u) & 0x3FFu);
  148. a = (a & 0x8000u) | ((a << 2u) & 0x7FF8u);
  149. b = (b & 0x8000u) | ((b << 2u) & 0x7FF8u);
  150. a = (a << 16u) | (b << 3u);
  151. return uintBitsToFloat(a); //asfloat(a);
  152. #endif
  153. return 0.0;
  154. }
  155. void VATGetLocalPositionRigidBody30(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec2 meshUV2, in vec2 meshUV3, vec2 thisFrameUV, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture, bool isZUp)
  156. {
  157. // pivot offset
  158. vec3 direction;
  159. direction.x = meshUV2.x;
  160. direction.y = sqrt(1.0 - (meshUV2.x*meshUV2.x + meshUV3.x*meshUV3.x));
  161. direction.z = meshUV3.x;
  162. float Magnitude = CalculateVATDecodeUV(meshUV2.y, meshUV3.y);
  163. float Up = Magnitude;
  164. vec3 org, pivot;
  165. org = vec3(meshUV2.x, Up, meshUV3.x);
  166. if(abs(meshUV3.y) > 2.0)
  167. pivot = direction.xyz * Magnitude;
  168. else
  169. pivot = org.xyz;
  170. if(isZUp)
  171. pivot.xyz = pivot.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  172. vec3 originPos = meshLocalPos - pivot;
  173. // rotation offset
  174. vec4 posData = SampleTextureExrWithAlpha(vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, thisFrameUV);
  175. vec4 XYZW = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
  176. float w = sqrt(1.0 - dot(XYZW.xyz, XYZW.xyz)); //sqrt(1.0 - quat.x*quat.x - quat.y*quat.y - quat.z*quat.z); //r
  177. // restore origin quaternion for slerp between frames
  178. // float cycle_count = XYZW.w; // rotation cycle count for slerp between frames
  179. // float rot_angle = cycle_count * PI2 + acos(w);
  180. // w = cos(rot_angle);
  181. vec4 quat = vec4(0.0, 0.0, 0.0, 1.0);
  182. // upper is UE, lower is Houdini
  183. float maxComponent = floor(posData.a * 4.0);
  184. if(equalf_epsilon(maxComponent, 1.0, 0.01)) {
  185. quat = vec4(-w, XYZW.yzx);
  186. quat = vec4(w, XYZW.yzx);
  187. }
  188. else if(equalf_epsilon(maxComponent, 2.0, 0.01)) {
  189. quat = vec4(XYZW.xy, -w, -XYZW.z);
  190. quat = vec4(XYZW.x, w, XYZW.zy);
  191. }
  192. else if(equalf_epsilon(maxComponent, 3.0, 0.01)) {
  193. quat = vec4(XYZW.x, -w, -XYZW.zy);
  194. quat = vec4(XYZW.xy, w, XYZW.z);
  195. }
  196. else
  197. quat = vec4(XYZW.xyz, w);
  198. // quat = quat.xzyw;
  199. vec3 rotatedPos;
  200. rotatedPos = 2.0 * cross(quat.xyz, cross(quat.xyz, originPos.xyz) + quat.w * originPos.xyz);
  201. // result
  202. meshLocalPos = originPos + rotatedPos + posData.xyz;
  203. meshLocalNormal = 2.0 * cross(quat.xyz, cross(quat.xyz, meshLocalNormal.xyz)+ quat.w * meshLocalNormal.xyz);
  204. meshLocalTangent = 2.0 * cross(quat.xyz, cross(quat.xyz, meshLocalTangent.xyz)+ quat.w * meshLocalTangent.xyz);
  205. }
  206. void VATGetLocalPositionRigidBody30_UE(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec2 meshUV2, in vec2 meshUV3, vec2 thisFrameUV, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  207. {
  208. // input
  209. vec3 preSkinnedPos = meshLocalPos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  210. vec3 preSkinnedNorm = meshLocalNormal.xzy;
  211. vec3 preSkinnedTangent = meshLocalTangent.xzy;
  212. VATGetLocalPositionRigidBody30(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshUV2, meshUV3, thisFrameUV, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, true);
  213. // output
  214. meshLocalPos = preSkinnedPos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  215. meshLocalNormal = preSkinnedNorm.xzy;
  216. meshLocalTangent = preSkinnedTangent.xzy;
  217. }
  218. void VATGetLocalPositionRigidBody30_Cocos(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec2 meshUV2, in vec2 meshUV3, vec2 thisFrameUV, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
  219. {
  220. // input
  221. vec3 preSkinnedPos = meshLocalPos.xyz / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  222. vec3 preSkinnedNorm = meshLocalNormal.xyz;
  223. vec3 preSkinnedTangent = meshLocalTangent.xyz;
  224. VATGetLocalPositionRigidBody30(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshUV2, meshUV3, thisFrameUV, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, false);
  225. // output
  226. meshLocalPos = preSkinnedPos.xyz * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
  227. meshLocalNormal = preSkinnedNorm.xyz;
  228. meshLocalTangent = preSkinnedTangent.xyz;
  229. }