|
@@ -1,10 +1,8 @@
|
|
|
|
|
|
-import * as THREE from "../../libs/three.js/build/three.module.js";
|
|
|
+//import * as THREE from "../../libs/three.js/build/three.module.js";
|
|
|
import {Version} from "../Version.js";
|
|
|
import {PointAttributes, PointAttribute, PointAttributeTypes} from "../loader/PointAttributes.js";
|
|
|
-
|
|
|
-import {Splat} from '../custom/objects/3dgs/Splat.js'
|
|
|
-
|
|
|
+
|
|
|
const typedArrayMapping = {
|
|
|
"int8": Int8Array,
|
|
|
"int16": Int16Array,
|
|
@@ -18,9 +16,6 @@ const typedArrayMapping = {
|
|
|
"double": Float64Array,
|
|
|
};
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
const gs3dProplist = [
|
|
|
'f_dc_0', //color
|
|
|
'f_dc_1',
|
|
@@ -80,10 +75,379 @@ const gs3dProplist = [
|
|
|
'rot_3'
|
|
|
]
|
|
|
|
|
|
+let clamp = function ( value, min, max ) {
|
|
|
+
|
|
|
+ return Math.max( min, Math.min( max, value ) );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+class Vector3 {
|
|
|
+
|
|
|
+ constructor( x = 0, y = 0, z = 0 ) {
|
|
|
+
|
|
|
+ Object.defineProperty( this, 'isVector3', { value: true } );
|
|
|
+
|
|
|
+ this.x = x;
|
|
|
+ this.y = y;
|
|
|
+ this.z = z;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ set( x, y, z ) {
|
|
|
+
|
|
|
+ if ( z === undefined ) z = this.z; // sprite.scale.set(x,y)
|
|
|
+
|
|
|
+ this.x = x;
|
|
|
+ this.y = y;
|
|
|
+ this.z = z;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+class Quaternion {
|
|
|
+
|
|
|
+ constructor( x = 0, y = 0, z = 0, w = 1 ) {
|
|
|
+
|
|
|
+ Object.defineProperty( this, 'isQuaternion', { value: true } );
|
|
|
+
|
|
|
+ this._x = x;
|
|
|
+ this._y = y;
|
|
|
+ this._z = z;
|
|
|
+ this._w = w;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ set( x, y, z, w ) {
|
|
|
+
|
|
|
+ this._x = x;
|
|
|
+ this._y = y;
|
|
|
+ this._z = z;
|
|
|
+ this._w = w;
|
|
|
+
|
|
|
+ //this._onChangeCallback();
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+const _zero = new Vector3( 0, 0, 0 );
|
|
|
+const _one = new Vector3( 1, 1, 1 );
|
|
|
+class Matrix4 {
|
|
|
+
|
|
|
+ constructor() {
|
|
|
+
|
|
|
+ Object.defineProperty( this, 'isMatrix4', { value: true } );
|
|
|
+
|
|
|
+ this.elements = [
|
|
|
+
|
|
|
+ 1, 0, 0, 0,
|
|
|
+ 0, 1, 0, 0,
|
|
|
+ 0, 0, 1, 0,
|
|
|
+ 0, 0, 0, 1
|
|
|
+
|
|
|
+ ];
|
|
|
+
|
|
|
+ if ( arguments.length > 0 ) {
|
|
|
+
|
|
|
+ console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ makeRotationFromQuaternion( q ) {
|
|
|
+
|
|
|
+ return this.compose( _zero, q, _one );
|
|
|
+
|
|
|
+ }
|
|
|
+ compose( position, quaternion, scale ) {
|
|
|
+
|
|
|
+ const te = this.elements;
|
|
|
+
|
|
|
+ const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;
|
|
|
+ const x2 = x + x, y2 = y + y, z2 = z + z;
|
|
|
+ const xx = x * x2, xy = x * y2, xz = x * z2;
|
|
|
+ const yy = y * y2, yz = y * z2, zz = z * z2;
|
|
|
+ const wx = w * x2, wy = w * y2, wz = w * z2;
|
|
|
+
|
|
|
+ const sx = scale.x, sy = scale.y, sz = scale.z;
|
|
|
+
|
|
|
+ te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
|
|
|
+ te[ 1 ] = ( xy + wz ) * sx;
|
|
|
+ te[ 2 ] = ( xz - wy ) * sx;
|
|
|
+ te[ 3 ] = 0;
|
|
|
+
|
|
|
+ te[ 4 ] = ( xy - wz ) * sy;
|
|
|
+ te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
|
|
|
+ te[ 6 ] = ( yz + wx ) * sy;
|
|
|
+ te[ 7 ] = 0;
|
|
|
+
|
|
|
+ te[ 8 ] = ( xz + wy ) * sz;
|
|
|
+ te[ 9 ] = ( yz - wx ) * sz;
|
|
|
+ te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
|
|
|
+ te[ 11 ] = 0;
|
|
|
+
|
|
|
+ te[ 12 ] = position.x;
|
|
|
+ te[ 13 ] = position.y;
|
|
|
+ te[ 14 ] = position.z;
|
|
|
+ te[ 15 ] = 1;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ makeScale( x, y, z ) {
|
|
|
+
|
|
|
+ this.set(
|
|
|
+
|
|
|
+ x, 0, 0, 0,
|
|
|
+ 0, y, 0, 0,
|
|
|
+ 0, 0, z, 0,
|
|
|
+ 0, 0, 0, 1
|
|
|
+
|
|
|
+ );
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
|
|
|
+
|
|
|
+ const te = this.elements;
|
|
|
+
|
|
|
+ te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;
|
|
|
+ te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;
|
|
|
+ te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;
|
|
|
+ te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class Matrix3 {
|
|
|
+
|
|
|
+ constructor() {
|
|
|
+
|
|
|
+ Object.defineProperty( this, 'isMatrix3', { value: true } );
|
|
|
+
|
|
|
+ this.elements = [
|
|
|
+
|
|
|
+ 1, 0, 0,
|
|
|
+ 0, 1, 0,
|
|
|
+ 0, 0, 1
|
|
|
+
|
|
|
+ ];
|
|
|
+
|
|
|
+ if ( arguments.length > 0 ) {
|
|
|
+
|
|
|
+ console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ copy( m ) {
|
|
|
+
|
|
|
+ const te = this.elements;
|
|
|
+ const me = m.elements;
|
|
|
+
|
|
|
+ te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];
|
|
|
+ te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];
|
|
|
+ te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ multiply( m ) {
|
|
|
+
|
|
|
+ return this.multiplyMatrices( this, m );
|
|
|
+
|
|
|
+ }
|
|
|
+ premultiply( m ) {
|
|
|
+
|
|
|
+ return this.multiplyMatrices( m, this );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ multiplyMatrices( a, b ) {
|
|
|
+
|
|
|
+ const ae = a.elements;
|
|
|
+ const be = b.elements;
|
|
|
+ const te = this.elements;
|
|
|
+
|
|
|
+ const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];
|
|
|
+ const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];
|
|
|
+ const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];
|
|
|
+
|
|
|
+ const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];
|
|
|
+ const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];
|
|
|
+ const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];
|
|
|
+
|
|
|
+ te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
|
|
|
+ te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
|
|
|
+ te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
|
|
|
+
|
|
|
+ te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
|
|
|
+ te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
|
|
|
+ te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
|
|
|
+
|
|
|
+ te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
|
|
|
+ te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
|
|
|
+ te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ setFromMatrix4( m ) {
|
|
|
+
|
|
|
+ const me = m.elements;
|
|
|
+
|
|
|
+ this.set(
|
|
|
+
|
|
|
+ me[ 0 ], me[ 4 ], me[ 8 ],
|
|
|
+ me[ 1 ], me[ 5 ], me[ 9 ],
|
|
|
+ me[ 2 ], me[ 6 ], me[ 10 ]
|
|
|
+
|
|
|
+ );
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
|
|
|
+
|
|
|
+ const te = this.elements;
|
|
|
+
|
|
|
+ te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;
|
|
|
+ te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;
|
|
|
+ te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+ transpose() {
|
|
|
+
|
|
|
+ let tmp;
|
|
|
+ const m = this.elements;
|
|
|
+
|
|
|
+ tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;
|
|
|
+ tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;
|
|
|
+ tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+let toHalfFloat = function ( val ) {
|
|
|
+
|
|
|
+ // Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
|
|
|
+
|
|
|
+ /* This method is faster than the OpenEXR implementation (very often
|
|
|
+ * used, eg. in Ogre), with the additional benefit of rounding, inspired
|
|
|
+ * by James Tursa?s half-precision code. */
|
|
|
+
|
|
|
+ _floatView[ 0 ] = val;
|
|
|
+ const x = _int32View[ 0 ];
|
|
|
+
|
|
|
+ let bits = ( x >> 16 ) & 0x8000; /* Get the sign */
|
|
|
+ let m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
|
|
|
+ const e = ( x >> 23 ) & 0xff; /* Using int is faster here */
|
|
|
+
|
|
|
+ /* If zero, or denormal, or exponent underflows too much for a denormal
|
|
|
+ * half, return signed zero. */
|
|
|
+ if ( e < 103 ) return bits;
|
|
|
+
|
|
|
+ /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
|
|
|
+ if ( e > 142 ) {
|
|
|
+
|
|
|
+ bits |= 0x7c00;
|
|
|
+ /* If exponent was 0xff and one mantissa bit was set, it means NaN,
|
|
|
+ * not Inf, so make sure we set one mantissa bit too. */
|
|
|
+ bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
|
|
|
+ return bits;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If exponent underflows but not too much, return a denorma l */
|
|
|
+ if ( e < 113 ) {
|
|
|
+
|
|
|
+ m |= 0x0800;
|
|
|
+ /* Extra rounding may overflow and set mantissa to 0 and exponent
|
|
|
+ * to 1, which is OK. */
|
|
|
+ bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
|
|
|
+ return bits;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
|
|
|
+ /* Extra rounding. An overflow will set mantissa to 0 and increment
|
|
|
+ * the exponent, which is OK. */
|
|
|
+ bits += m & 1;
|
|
|
+ return bits;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+let computeCovariance = function() {//通过旋转和缩放计算协方差(决定姿态)得到6个数
|
|
|
+
|
|
|
+ const tempMatrix4 = new Matrix4();
|
|
|
+ const scaleMatrix = new Matrix3();
|
|
|
+ const rotationMatrix = new Matrix3();
|
|
|
+ const covarianceMatrix = new Matrix3();
|
|
|
+ const transformedCovariance = new Matrix3();
|
|
|
+ const transform3x3 = new Matrix3();
|
|
|
+ const transform3x3Transpose = new Matrix3();
|
|
|
+ const thf = toHalfFloat //THREE.DataUtils.toHalfFloat.bind(THREE.DataUtils);
|
|
|
+
|
|
|
+ return function(scale, rotation, transform, outCovariance, outOffset = 0, desiredOutputCompressionLevel) {
|
|
|
+
|
|
|
+ tempMatrix4.makeScale(scale.x, scale.y, scale.z);
|
|
|
+ scaleMatrix.setFromMatrix4(tempMatrix4);
|
|
|
|
|
|
+ tempMatrix4.makeRotationFromQuaternion(rotation);
|
|
|
+ rotationMatrix.setFromMatrix4(tempMatrix4);
|
|
|
|
|
|
+ covarianceMatrix.copy(rotationMatrix).multiply(scaleMatrix);
|
|
|
+ transformedCovariance.copy(covarianceMatrix).transpose().premultiply(covarianceMatrix); //为什么要乘以自己的转置呀?
|
|
|
|
|
|
+ if (transform) {//场景的整体transform 如果可能移动就不传,在sort时直接乘
|
|
|
+ transform3x3.setFromMatrix4(transform);
|
|
|
+ transform3x3Transpose.copy(transform3x3).transpose();
|
|
|
+ transformedCovariance.multiply(transform3x3Transpose);
|
|
|
+ transformedCovariance.premultiply(transform3x3);
|
|
|
+ }
|
|
|
|
|
|
+ if (desiredOutputCompressionLevel === 1) {//压缩
|
|
|
+ outCovariance[outOffset] = thf(transformedCovariance.elements[0]);
|
|
|
+ outCovariance[outOffset + 1] = thf(transformedCovariance.elements[3]);
|
|
|
+ outCovariance[outOffset + 2] = thf(transformedCovariance.elements[6]);
|
|
|
+ outCovariance[outOffset + 3] = thf(transformedCovariance.elements[4]);
|
|
|
+ outCovariance[outOffset + 4] = thf(transformedCovariance.elements[7]);
|
|
|
+ outCovariance[outOffset + 5] = thf(transformedCovariance.elements[8]);
|
|
|
+ } else {
|
|
|
+ outCovariance[outOffset] = transformedCovariance.elements[0];
|
|
|
+ outCovariance[outOffset + 1] = transformedCovariance.elements[3];
|
|
|
+ outCovariance[outOffset + 2] = transformedCovariance.elements[6];
|
|
|
+ outCovariance[outOffset + 3] = transformedCovariance.elements[4];
|
|
|
+ outCovariance[outOffset + 4] = transformedCovariance.elements[7];
|
|
|
+ outCovariance[outOffset + 5] = transformedCovariance.elements[8];
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /*
|
|
|
+ Vrk 中的元素分别是transformedCovariance的 [
|
|
|
+ 0,3,6,
|
|
|
+ 3,4,7,
|
|
|
+ 6,7,8
|
|
|
+ ]
|
|
|
+
|
|
|
+ */
|
|
|
+ };
|
|
|
+
|
|
|
+}();
|
|
|
|
|
|
|
|
|
Potree = {};
|
|
@@ -321,11 +685,11 @@ onmessage = function (event) {
|
|
|
const offset_col = gs3dProplist.indexOf('f_dc_0')
|
|
|
let getColor = (index)=>{
|
|
|
let value = (0.5 + SH_C0 * f32[index+offset_col]) * 255;
|
|
|
- return THREE.Math.clamp(Math.floor(value), 0, 255);
|
|
|
+ return clamp(Math.floor(value), 0, 255);
|
|
|
}
|
|
|
let getOpacity = (index)=>{
|
|
|
let value = (1 / (1 + Math.exp(-f32[index+offset_opa]))) * 255;
|
|
|
- return THREE.Math.clamp(Math.floor(value), 0, 255);
|
|
|
+ return clamp(Math.floor(value), 0, 255);
|
|
|
}
|
|
|
for (let j = 0; j < numPoints; j++) {
|
|
|
colors[4 * j + 0] = getColor(j * pointAttribute.numElements + 0)
|
|
@@ -342,8 +706,8 @@ onmessage = function (event) {
|
|
|
let covs = new Float32Array(buff3);
|
|
|
const offset_scale = gs3dProplist.indexOf('scale_0') //第49个数开始是
|
|
|
const offset_rot = gs3dProplist.indexOf('rot_0')
|
|
|
- let scale = new THREE.Vector3()
|
|
|
- let quaternion = new THREE.Quaternion()
|
|
|
+ let scale = new Vector3()
|
|
|
+ let quaternion = new Quaternion()
|
|
|
|
|
|
let getScale = (index)=>{
|
|
|
let get = (offset)=>{
|
|
@@ -364,7 +728,7 @@ onmessage = function (event) {
|
|
|
for (let j = 0; j < numPoints; j++) {
|
|
|
getScale(j);
|
|
|
getQuatenion(j);
|
|
|
- Splat.computeCovariance(scale, quaternion, null, covs, 6 * j );
|
|
|
+ computeCovariance(scale, quaternion, null, covs, 6 * j );
|
|
|
}
|
|
|
|
|
|
attributeBuffers['covs'] = { buffer: buff3, attribute: pointAttribute };
|