| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #include <common/math/transform>
- #include <common/texture/texture-misc>
- // Vertex Animation Texture (VAT), baked physically simulation result for rigid-body, soft-body and fluid
- // Houdini VAT Plugin Version:
- // 1. Soft-body and fluids use 3.0, Select Unity mode, otherwise animation will become crack
- // 2. Rigid-body use 2.0, Select UE mode with initialize settings, needs export json for numOfFrames(frameCount) and max/min values
- // Houdini misc export settings:
- // 1. Select LDR
- // 2. Do not check paddle, two-position textures and pack normals
- // Cocos import settings:
- // 1. LUT texture should set filter to "nearest" and uncheck "fix alpha transparency"
- // 2. Rigid-body select import normal and tangent
- // 3. Rigid-body and soft-body need check HAS_SECOND_UV
- // 4. If no sign texture with exr image, use white texture instead
- // For resources exported by UE mode, invoke functions like:
- // 1. VATFunction(inout_pos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE, inout_vector.xzy);
- // 2. out_pos.xyz = inout_pos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- // 2. out_vector.xyz = inout_vector.xzy;
- #define VAT_FBX_TO_COCOS_COORDINATE_SCALE 0.01
- #define VAT_LUT_PRECISION_VALUE_LDR 255.0
- #define VAT_LUT_PRECISION_VALUE_HDR 2048.0
- float CalculateVATAnimationUV(out vec2 deltaV, float frameCount, float animSpeed, float elapseTime)
- {
- float thisFrame = fract(animSpeed * elapseTime);
- thisFrame = floor(thisFrame * frameCount);
- float thisFrameDeltaV = thisFrame / frameCount;
- float nextFrameDeltaV = (thisFrame + 1.0) / frameCount;
- deltaV = vec2(thisFrameDeltaV, nextFrameDeltaV);
- float frameLerp = fract(thisFrame * frameCount);
- return frameLerp;
- }
- ///////////////////////////////////////////// public functions
- // auto calculation frame count for fluid
- float VATCalculateFrameCount(vec2 lutTexResolution, float meshVertexCount)
- {
- float lineCountPerFrame = ceil(meshVertexCount / lutTexResolution.x);
- return floor(lutTexResolution.y / lineCountPerFrame);
- }
- // meshUV use texCoord0 for fluid
- // meshUV use texCoord1 for rigid-body and soft-body
- float VATGetAnimUV(out vec2 thisFrameUV, out vec2 nextFrameUV, vec2 meshUV, float frameCount, float animSpeed, float elapseTime)
- {
- vec2 frameDeltaV;
- float frameLerp = CalculateVATAnimationUV(frameDeltaV, frameCount, animSpeed, elapseTime);
- thisFrameUV = meshUV + vec2(0.0, frameDeltaV.x);
- nextFrameUV = meshUV + vec2(0.0, frameDeltaV.y);
- return frameLerp;
- }
- // VAT with LUT, fluid only
- float VATGetAnimUV(out vec2 thisFrameUV, out vec2 nextFrameUV, vec2 meshUV, float frameCount, float animSpeed, float elapseTime, sampler2D lutTexture)
- {
- vec2 frameDeltaV;
- float frameLerp = CalculateVATAnimationUV(frameDeltaV, frameCount, animSpeed, elapseTime);
- vec4 thisFramelookUpValue = texture(lutTexture, meshUV + vec2(0.0, frameDeltaV.x));
- thisFrameUV = thisFramelookUpValue.xz + thisFramelookUpValue.yw / VAT_LUT_PRECISION_VALUE_LDR;
- vec4 nextFramelookUpValue = texture(lutTexture, meshUV + vec2(0.0, frameDeltaV.y));
- nextFrameUV = nextFramelookUpValue.xz + nextFramelookUpValue.yw / VAT_LUT_PRECISION_VALUE_LDR;
- return frameLerp;
- }
- // return absolute position for fluid
- // return position offset for soft-body
- vec3 VATGetLocalPosition(vec2 thisFrameUV, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture)
- {
- vec3 thisFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
- return thisFramePos * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- }
- // meshNormal is up-axis for fluid
- vec3 VATGetLocalNormal(vec3 meshNormal, vec2 thisFrameUV, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
- {
- vec4 thisFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
- rotateVecFromQuat(meshNormal, thisFrameData);
- return meshNormal;
- }
- // for smooth animation
- vec3 VATGetLocalPosition(vec2 thisFrameUV, vec2 nextFrameUV, float frameLerp, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture)
- {
- vec3 thisFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
- vec3 nextFramePos = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, nextFrameUV);
- return mix(thisFramePos, nextFramePos, frameLerp) * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- }
- vec3 VATGetLocalNormal(vec3 meshNormal, vec2 thisFrameUV, vec2 nextFrameUV, float frameLerp, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture)
- {
- vec4 thisFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
- vec4 nextFrameData = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, nextFrameUV);
- vec4 data = mix(thisFrameData, nextFrameData, frameLerp);
- rotateVecFromQuat(meshNormal, data);
- return meshNormal;
- }
- // calculate simulation voxel coordinates
- vec3 VATCalculateFluidVoxelUV(vec3 vatBoundingBoxMin, vec3 vatBoundingBoxMax, vec3 localPos)
- {
- // bounding box in exported json is unscaled
- vatBoundingBoxMin *= VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vatBoundingBoxMax *= VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vec3 size = vatBoundingBoxMax - vatBoundingBoxMin;
- vec3 coef = (localPos - vatBoundingBoxMin) / size;
- return coef;
- }
- ////////////////////////////////////////////////////////////////Rigid-body
- 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)
- {
- // pivot
- float pivExpand = pivMax - pivMin;
- float posExpand = posMax - posMin;
- vec3 pivot = meshVertexColor.xyz;
- pivot.xyz *= pivExpand;
- pivot.xyz += vec3(pivMin);
- // anim pos
- vec3 posData = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV);
- vec3 texturePos = posData;
- texturePos.xyz *= posExpand;
- texturePos.xyz += posMin;
- // rotate pos
- vec4 quat = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
- quat = quat * 2.0 - vec4(1.0);
- vec3 originPos = meshLocalPos - pivot;
- vec3 rotatedPos;
- rotatedPos = 2.0 * cross(quat.xyz, cross(quat.xyz, originPos.xyz) + quat.w * originPos.xyz);
- // result
- meshLocalPos = meshLocalPos + rotatedPos + texturePos;
- rotateVecFromQuat(meshLocalNormal, quat);
- rotateVecFromQuat(meshLocalTangent, quat);
- }
- 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)
- {
- // input
- vec3 preSkinnedPos = meshLocalPos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vec3 preSkinnedNorm = meshLocalNormal.xzy;
- vec3 preSkinnedTangent = meshLocalTangent.xzy;
- VATGetLocalPositionRigidBody20(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshVertexColor, thisFrameUV, pivMax, pivMin, posMax, posMin, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture);
- // output
- meshLocalPos.xyz = preSkinnedPos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- meshLocalNormal.xyz = preSkinnedNorm.xzy;
- meshLocalTangent.xyz = preSkinnedTangent.xzy;
- }
- // Experimental
- float CalculateVATDecodeUV(float A, float B)
- {
- #if __VERSION__ >= 110
- uint a = floatBitsToUint(A); //asuint(A)
- uint b = floatBitsToUint(B);
- a = ((a >> 16u) & 0x8000u) |
- ((((a >> 23u) & 0xFFu) - 112u) << 10u) |
- ((a >> 13u) & 0x3FFu);
- b = ((b >> 16u) & 0x8000u) |
- ((((b >> 23u) & 0xFFu) - 112u) << 10u) |
- ((b >> 13u) & 0x3FFu);
- a = (a & 0x8000u) | ((a << 2u) & 0x7FF8u);
- b = (b & 0x8000u) | ((b << 2u) & 0x7FF8u);
- a = (a << 16u) | (b << 3u);
- return uintBitsToFloat(a); //asfloat(a);
- #endif
- return 0.0;
- }
- 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)
- {
- // pivot offset
- vec3 direction;
- direction.x = meshUV2.x;
- direction.y = sqrt(1.0 - (meshUV2.x*meshUV2.x + meshUV3.x*meshUV3.x));
- direction.z = meshUV3.x;
- float Magnitude = CalculateVATDecodeUV(meshUV2.y, meshUV3.y);
- float Up = Magnitude;
- vec3 org, pivot;
- org = vec3(meshUV2.x, Up, meshUV3.x);
- if(abs(meshUV3.y) > 2.0)
- pivot = direction.xyz * Magnitude;
- else
- pivot = org.xyz;
- if(isZUp)
- pivot.xyz = pivot.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vec3 originPos = meshLocalPos - pivot;
- // rotation offset
- vec4 posData = SampleTextureExrWithAlpha(vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, thisFrameUV);
- vec4 XYZW = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV);
- 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
- // restore origin quaternion for slerp between frames
- // float cycle_count = XYZW.w; // rotation cycle count for slerp between frames
- // float rot_angle = cycle_count * PI2 + acos(w);
- // w = cos(rot_angle);
- vec4 quat = vec4(0.0, 0.0, 0.0, 1.0);
- // upper is UE, lower is Houdini
- float maxComponent = floor(posData.a * 4.0);
- if(equalf_epsilon(maxComponent, 1.0, 0.01)) {
- quat = vec4(-w, XYZW.yzx);
- quat = vec4(w, XYZW.yzx);
- }
- else if(equalf_epsilon(maxComponent, 2.0, 0.01)) {
- quat = vec4(XYZW.xy, -w, -XYZW.z);
- quat = vec4(XYZW.x, w, XYZW.zy);
- }
- else if(equalf_epsilon(maxComponent, 3.0, 0.01)) {
- quat = vec4(XYZW.x, -w, -XYZW.zy);
- quat = vec4(XYZW.xy, w, XYZW.z);
- }
- else
- quat = vec4(XYZW.xyz, w);
- // quat = quat.xzyw;
- vec3 rotatedPos;
- rotatedPos = 2.0 * cross(quat.xyz, cross(quat.xyz, originPos.xyz) + quat.w * originPos.xyz);
- // result
- meshLocalPos = originPos + rotatedPos + posData.xyz;
- meshLocalNormal = 2.0 * cross(quat.xyz, cross(quat.xyz, meshLocalNormal.xyz)+ quat.w * meshLocalNormal.xyz);
- meshLocalTangent = 2.0 * cross(quat.xyz, cross(quat.xyz, meshLocalTangent.xyz)+ quat.w * meshLocalTangent.xyz);
- }
- 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)
- {
- // input
- vec3 preSkinnedPos = meshLocalPos.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vec3 preSkinnedNorm = meshLocalNormal.xzy;
- vec3 preSkinnedTangent = meshLocalTangent.xzy;
- VATGetLocalPositionRigidBody30(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshUV2, meshUV3, thisFrameUV, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, true);
- // output
- meshLocalPos = preSkinnedPos.xzy * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- meshLocalNormal = preSkinnedNorm.xzy;
- meshLocalTangent = preSkinnedTangent.xzy;
- }
- 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)
- {
- // input
- vec3 preSkinnedPos = meshLocalPos.xyz / VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- vec3 preSkinnedNorm = meshLocalNormal.xyz;
- vec3 preSkinnedTangent = meshLocalTangent.xyz;
- VATGetLocalPositionRigidBody30(preSkinnedPos, preSkinnedNorm, preSkinnedTangent, meshUV2, meshUV3, thisFrameUV, vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, false);
- // output
- meshLocalPos = preSkinnedPos.xyz * VAT_FBX_TO_COCOS_COORDINATE_SCALE;
- meshLocalNormal = preSkinnedNorm.xyz;
- meshLocalTangent = preSkinnedTangent.xyz;
- }
|