@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 4.22 kB
JavaScript
import{RefCountedObject as t}from"../core/ref-counted-object.js";import{Vec3 as e}from"../core/math/vec3.js";import{FloatPacking as r}from"../core/math/float-packing.js";import{BoundingBox as s}from"../core/shape/bounding-box.js";import{Texture as i}from"../platform/graphics/texture.js";import{VertexBuffer as o}from"../platform/graphics/vertex-buffer.js";import{VertexFormat as h}from"../platform/graphics/vertex-format.js";import{PIXELFORMAT_RGBA16F as a,PIXELFORMAT_RGBA32F as n,PIXELFORMAT_RGB32F as l,FILTER_NEAREST as u,ADDRESS_CLAMP_TO_EDGE as p,SEMANTIC_ATTR15 as m,TYPE_UINT32 as g,TYPE_FLOAT32 as c}from"../platform/graphics/constants.js";class f extends t{constructor(t,e,{preferHighPrecision:r=!1}={}){super(),this._aabb=void 0,this.preferHighPrecision=void 0,this.device=e,this.preferHighPrecision=r,this._targets=t.slice();const s=this.device;if(s.supportsMorphTargetTexturesCore){const t=s.extTextureHalfFloat&&s.textureHalfFloatRenderable?a:void 0,e=s.extTextureFloat&&s.textureFloatRenderable?n:void 0;this._renderTextureFormat=this.preferHighPrecision?null!=e?e:t:null!=t?t:e;const r=s.extTextureHalfFloat&&s.textureHalfFloatUpdatable?a:void 0,i=s.extTextureFloat?l:void 0;this._textureFormat=this.preferHighPrecision?null!=i?i:r:null!=r?r:i,void 0!==this._renderTextureFormat&&void 0!==this._textureFormat&&(this._useTextureMorph=!0)}this._init(),this._updateMorphFlags()}get aabb(){if(!this._aabb){const t=new e,r=new e;for(let e=0;e<this._targets.length;e++){const s=this._targets[e].aabb;t.min(s.getMin()),r.max(s.getMax())}this._aabb=new s,this._aabb.setMinMax(t,r)}return this._aabb}get morphPositions(){return this._morphPositions}get morphNormals(){return this._morphNormals}get maxActiveTargets(){return this._useTextureMorph?this._targets.length:this._morphPositions&&this._morphNormals?4:8}get useTextureMorph(){return this._useTextureMorph}_init(){if(this._useTextureMorph&&(this._useTextureMorph=this._initTextureBased()),!this._useTextureMorph)for(let t=0;t<this._targets.length;t++)this._targets[t]._initVertexBuffers(this.device);for(let t=0;t<this._targets.length;t++)this._targets[t]._postInit()}_findSparseSet(t,e,r,s){let i=1;const o=t[0].length;for(let h=0;h<o;h+=3){let o=!1;for(let e=0;e<t.length;e++){const r=t[e];if(0!==r[h]||0!==r[h+1]||0!==r[h+2]){o=!0;break}}o?(e.push(i+s),r.push(h/3),i++):e.push(0+s)}return i}_initTextureBased(){const t=this.device.isWebGPU,e=t?0:.2,s=[],i=[];for(let t=0;t<this._targets.length;t++){const e=this._targets[t];e.options.deltaPositions&&(s.push(e.options.deltaPositions),i.push({target:e,name:"texturePositions"})),e.options.deltaNormals&&(s.push(e.options.deltaNormals),i.push({target:e,name:"textureNormals"}))}const n=[],l=[],u=this._findSparseSet(s,n,l,e),p=Math.min(this.device.maxTextureSize,4096);let f=Math.ceil(Math.sqrt(u));f=Math.min(f,p);const _=Math.ceil(u/f);if(_>p)return!1;this.morphTextureWidth=f,this.morphTextureHeight=_;let x=!1,d=3;const T=r.float2Half;this._textureFormat===a&&(x=!0,d=4);const b=[];for(let t=0;t<s.length;t++)b.push(this._createTexture("MorphTarget",this._textureFormat));for(let t=0;t<s.length;t++){const e=s[t],r=b[t],o=r.lock();if(x)for(let t=0;t<l.length;t++){const r=3*l[t],s=t*d+d;o[s]=T(e[r]),o[s+1]=T(e[r+1]),o[s+2]=T(e[r+2])}else for(let t=0;t<l.length;t++){const r=3*l[t],s=t*d+d;o[s]=e[r],o[s+1]=e[r+1],o[s+2]=e[r+2]}r.unlock();i[t].target._setTexture(i[t].name,r)}const v=[{semantic:m,components:1,type:t?g:c}];return this.vertexBufferIds=new o(this.device,new h(this.device,v,n.length),n.length,{data:t?new Uint32Array(n):new Float32Array(n)}),!0}destroy(){var t;null==(t=this.vertexBufferIds)||t.destroy(),this.vertexBufferIds=null;for(let t=0;t<this._targets.length;t++)this._targets[t].destroy();this._targets.length=0}get targets(){return this._targets}_updateMorphFlags(){this._morphPositions=!1,this._morphNormals=!1;for(let t=0;t<this._targets.length;t++){const e=this._targets[t];e.morphPositions&&(this._morphPositions=!0),e.morphNormals&&(this._morphNormals=!0)}}_createTexture(t,e){return new i(this.device,{width:this.morphTextureWidth,height:this.morphTextureHeight,format:e,cubemap:!1,mipmaps:!1,minFilter:u,magFilter:u,addressU:p,addressV:p,name:t})}}export{f as Morph};