@tresjs/cientos 5.1.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * name: @tresjs/cientos
3
- * version: v5.1.2
3
+ * version: v5.2.0
4
4
  * (c) 2025
5
5
  * description: Collection of useful helpers and fully functional, ready-made abstractions for Tres
6
6
  * author: Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)
@@ -6728,7 +6728,11 @@ var fragment_default = "void main() {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0)
6728
6728
 
6729
6729
  //#endregion
6730
6730
  //#region src/core/misc/html/shaders/vertex.glsl
6731
- var vertex_default = "#include <common>\n\nvoid main() {\n vec2 center = vec2(0., 1.);\n float rotation = 0.0;\n\n \n \n float size = 0.03;\n\n vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n vec2 scale;\n scale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n scale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\n bool isPerspective = isPerspectiveMatrix( projectionMatrix );\n if ( isPerspective ) scale *= - mvPosition.z;\n\n vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale * size;\n vec2 rotatedPosition;\n rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n mvPosition.xy += rotatedPosition;\n\n gl_Position = projectionMatrix * mvPosition;\n}";
6731
+ var vertex_default = "#include <common>\n\nuniform float uWidth;\nuniform float uHeight;\n\nvoid main() {\n\n vec4 mvPosition = modelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0);\n\n vec2 quad = position.xy;\n\n vec2 alignedPosition = quad * vec2(uWidth, uHeight);\n\n mvPosition.xy += alignedPosition;\n\n gl_Position = projectionMatrix * mvPosition;\n}";
6732
+
6733
+ //#endregion
6734
+ //#region src/core/misc/html/shaders/passthrough-vertex.glsl
6735
+ var passthrough_vertex_default = "#include <common>\n\nvoid main() {\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}";
6732
6736
 
6733
6737
  //#endregion
6734
6738
  //#region src/core/misc/html/utils.ts
@@ -6765,6 +6769,17 @@ function isObjectVisible(el, camera, raycaster, occlude) {
6765
6769
  }
6766
6770
  return true;
6767
6771
  }
6772
+ function getViewportFactor(camera, target = new Vector3(0, 0, 0), size) {
6773
+ const { width, height } = size;
6774
+ const aspect = width / height;
6775
+ const position = v1;
6776
+ const tempTarget = v2;
6777
+ tempTarget.copy(target);
6778
+ const distance = camera.getWorldPosition(position).distanceTo(tempTarget);
6779
+ if (camera instanceof OrthographicCamera) return 1;
6780
+ const fov = camera.fov * Math.PI / 180;
6781
+ return width / (2 * Math.tan(fov / 2) * distance * aspect);
6782
+ }
6768
6783
  function objectScale(el, camera) {
6769
6784
  if (camera instanceof OrthographicCamera) return camera.zoom;
6770
6785
  else if (camera instanceof PerspectiveCamera) {
@@ -6809,35 +6824,41 @@ const getCameraCSSMatrix = ((multipliers) => (matrix) => getCSSMatrix(matrix, mu
6809
6824
  1,
6810
6825
  1
6811
6826
  ]);
6812
- const getObjectCSSMatrix = ((scaleMultipliers) => (matrix, factor) => getCSSMatrix(matrix, scaleMultipliers(factor), "translate(-50%,-50%)"))((f) => [
6813
- 1 / f,
6814
- 1 / f,
6815
- 1 / f,
6816
- 1,
6817
- -1 / f,
6818
- -1 / f,
6819
- -1 / f,
6820
- -1,
6821
- 1 / f,
6822
- 1 / f,
6823
- 1 / f,
6824
- 1,
6825
- 1,
6826
- 1,
6827
- 1,
6828
- 1
6829
- ]);
6827
+ const getObjectCSSMatrix = (matrix, factor) => {
6828
+ return getCSSMatrix(matrix, [
6829
+ 1 / factor,
6830
+ 1 / factor,
6831
+ 1 / factor,
6832
+ 1,
6833
+ -1 / factor,
6834
+ -1 / factor,
6835
+ -1 / factor,
6836
+ -1,
6837
+ 1 / factor,
6838
+ 1 / factor,
6839
+ 1 / factor,
6840
+ 1,
6841
+ 1,
6842
+ 1,
6843
+ 1,
6844
+ 1
6845
+ ], "translate(-50%,-50%)");
6846
+ };
6830
6847
 
6831
6848
  //#endregion
6832
6849
  //#region src/core/misc/html/HTML.vue?vue&type=script&setup=true&lang.ts
6833
- const _hoisted_1$33 = ["geometry", "material"];
6850
+ const _hoisted_1$33 = [
6851
+ "material",
6852
+ "cast-shadow",
6853
+ "receive-shadow",
6854
+ "geometry"
6855
+ ];
6834
6856
  var HTML_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
6835
6857
  __name: "HTML",
6836
6858
  props: {
6837
6859
  geometry: {
6838
6860
  type: null,
6839
- required: false,
6840
- default: new PlaneGeometry()
6861
+ required: false
6841
6862
  },
6842
6863
  material: {
6843
6864
  type: null,
@@ -6853,6 +6874,11 @@ var HTML_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
6853
6874
  required: false,
6854
6875
  default: false
6855
6876
  },
6877
+ prepend: {
6878
+ type: Boolean,
6879
+ required: false,
6880
+ default: false
6881
+ },
6856
6882
  portal: {
6857
6883
  type: null,
6858
6884
  required: false
@@ -6888,11 +6914,21 @@ var HTML_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
6888
6914
  required: false,
6889
6915
  default: false
6890
6916
  },
6917
+ transparentMaterial: {
6918
+ type: Boolean,
6919
+ required: false,
6920
+ default: false
6921
+ },
6891
6922
  zIndexRange: {
6892
6923
  type: Array,
6893
6924
  required: false,
6894
6925
  default: () => [16777271, 0]
6895
6926
  },
6927
+ calculatePosition: {
6928
+ type: null,
6929
+ required: false,
6930
+ default: () => calculatePosition
6931
+ },
6896
6932
  occlude: {
6897
6933
  type: [
6898
6934
  Object,
@@ -6902,6 +6938,16 @@ var HTML_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
6902
6938
  String
6903
6939
  ],
6904
6940
  required: false
6941
+ },
6942
+ castShadow: {
6943
+ type: Boolean,
6944
+ required: false,
6945
+ default: false
6946
+ },
6947
+ receiveShadow: {
6948
+ type: Boolean,
6949
+ required: false,
6950
+ default: false
6905
6951
  }
6906
6952
  },
6907
6953
  emits: ["onOcclude"],
@@ -6909,217 +6955,267 @@ var HTML_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
6909
6955
  const props = __props;
6910
6956
  const emits = __emit;
6911
6957
  const slots = useSlots();
6958
+ const { geometry, material, as, transform, portal, wrapperClass, eps, distanceFactor, fullscreen, center, pointerEvents, sprite, prepend, occlude, zIndexRange, castShadow, receiveShadow, transparentMaterial, calculatePosition: calculatePosition$1 } = toRefs(props);
6912
6959
  const attrs = useAttrs();
6913
- const groupRef = ref();
6914
- const meshRef = ref();
6915
- const { geometry, material, as, transform, portal, wrapperClass, eps, distanceFactor, fullscreen, center, pointerEvents, sprite, occlude, zIndexRange } = toRefs(props);
6960
+ const groupRef = shallowRef(null);
6961
+ const occlusionMeshRef = shallowRef(null);
6962
+ const defaultPlaneGeometry = new PlaneGeometry();
6916
6963
  const { renderer, scene, camera, sizes } = useTresContext();
6917
6964
  const el = computed(() => document.createElement(as.value));
6965
+ const raycaster = new Raycaster();
6966
+ const tmpVec = new Vector3();
6967
+ const tmpMatrix = new Matrix4();
6968
+ const tmpQuat = new Quaternion();
6918
6969
  const previousPosition = ref([
6919
6970
  0,
6920
6971
  0,
6921
6972
  0
6922
6973
  ]);
6923
6974
  const previousZoom = ref(0);
6924
- const vnode = ref();
6925
- const raycaster = ref(new Raycaster());
6975
+ const vnode = ref(null);
6976
+ const isVisible = ref(true);
6977
+ const isMeshSizeSet = ref(false);
6978
+ const baseStyle = computed(() => ({
6979
+ position: "absolute",
6980
+ top: "0",
6981
+ left: "0",
6982
+ willChange: "transform",
6983
+ pointerEvents: pointerEvents.value,
6984
+ ...typeof attrs.style === "object" ? attrs.style : {}
6985
+ }));
6926
6986
  const styles = computed(() => {
6987
+ const w = sizes.width.value;
6988
+ const h = sizes.height.value;
6927
6989
  if (transform.value) return {
6928
- position: "absolute",
6929
- top: 0,
6930
- left: 0,
6931
- width: `${sizes.width.value}px`,
6932
- height: `${sizes.height.value}px`,
6990
+ ...baseStyle.value,
6933
6991
  transformStyle: "preserve-3d",
6934
6992
  pointerEvents: "none",
6935
- zIndex: 2
6993
+ width: `${w}px`,
6994
+ height: `${h}px`
6936
6995
  };
6937
- else return {
6938
- position: "absolute",
6996
+ return {
6997
+ ...baseStyle.value,
6939
6998
  transform: center.value ? "translate3d(-50%,-50%,0)" : "none",
6940
6999
  ...fullscreen.value && {
6941
- top: -sizes.height.value / 2,
6942
- left: -sizes.width.value / 2,
6943
- width: `${sizes.width.value}px`,
6944
- height: `${sizes.height.value}px`
7000
+ top: `-${h / 2}px`,
7001
+ left: `-${w / 2}px`,
7002
+ width: `${w}px`,
7003
+ height: `${h}px`
6945
7004
  },
6946
- zIndex: 2,
6947
- ...Object.assign({}, attrs.style)
7005
+ pointerEvents: fullscreen.value ? "none" : pointerEvents.value
6948
7006
  };
6949
7007
  });
6950
7008
  const transformInnerStyles = computed(() => ({
6951
7009
  position: "absolute",
6952
7010
  pointerEvents: pointerEvents.value
6953
7011
  }));
6954
- const occlusionMeshRef = ref(null);
6955
- const isMeshSizeSet = ref(false);
6956
- const isRayCastOcclusion = computed(() => occlude?.value && occlude?.value !== "blending" || Array.isArray(occlude?.value) && occlude?.value.length && isRef(occlude.value[0]));
6957
- watch(() => occlude, ({ value }) => {
6958
- if (value === "blending") {
6959
- el.value.style.zIndex = `${Math.floor(zIndexRange.value[0] / 2)}`;
6960
- el.value.style.position = "absolute";
6961
- el.value.style.pointerEvents = "none";
6962
- } else {
6963
- el.value.style.zIndex = null;
6964
- el.value.style.position = null;
6965
- el.value.style.pointerEvents = null;
6966
- }
7012
+ const isRayCastOcclusion = computed(() => {
7013
+ const o = occlude.value;
7014
+ return o && o !== "blending" && (Array.isArray(o) ? o.length && typeof o[0] !== "boolean" : true);
7015
+ });
7016
+ const effectiveMaterial = computed(() => {
7017
+ if (material.value) return material.value;
7018
+ return new ShaderMaterial({
7019
+ vertexShader: sprite.value ? vertex_default : transform.value ? passthrough_vertex_default : vertex_default,
7020
+ fragmentShader: fragment_default,
7021
+ side: DoubleSide,
7022
+ transparent: transparentMaterial.value,
7023
+ uniforms: {
7024
+ uWidth: { value: 1 },
7025
+ uHeight: { value: 1 }
7026
+ }
7027
+ });
6967
7028
  });
7029
+ watchEffect(() => {
7030
+ effectiveMaterial.value.transparent = transparentMaterial.value;
7031
+ });
7032
+ watch([occlude, () => renderer.instance], ([occludeVal, r]) => {
7033
+ if (!r || occludeVal !== "blending") return;
7034
+ const target = r.domElement;
7035
+ target.style.zIndex = `${Math.floor(zIndexRange.value[0] / 2)}`;
7036
+ target.style.position = "absolute";
7037
+ }, { immediate: true });
6968
7038
  watch(() => [
6969
7039
  groupRef.value,
6970
7040
  renderer.instance,
6971
7041
  sizes.width.value,
6972
7042
  sizes.height.value,
6973
- slots.default?.()
6974
- ], ([group, renderer$1]) => {
6975
- if (group && renderer$1) {
6976
- const target = portal?.value || renderer$1.domElement;
6977
- scene.value?.updateMatrixWorld();
6978
- if (transform.value) el.value.style.cssText = "position:absolute;top:0;left:0;pointer-events:none;overflow:hidden;";
6979
- else {
6980
- const vector = calculatePosition(group, camera.activeCamera.value, {
6981
- width: sizes.width.value,
6982
- height: sizes.height.value
6983
- });
6984
- el.value.style.cssText = `position:absolute;top:0;left:0;transform:translate3d(${vector[0]}px,${vector[1]}px,0);transform-origin:0 0;`;
6985
- }
6986
- if (target && !el.value.parentNode) target.parentNode?.appendChild(el.value);
6987
- if (transform.value) vnode.value = createVNode("div", {
6988
- id: "outer",
6989
- style: styles.value
6990
- }, [createVNode("div", {
6991
- id: "inner",
6992
- style: transformInnerStyles.value
6993
- }, [createVNode("div", {
6994
- key: meshRef.value?.uuid,
6995
- id: scene?.value.uuid,
6996
- class: attrs.class,
6997
- style: attrs.style
6998
- }, slots.default?.())])]);
6999
- else vnode.value = createVNode("div", {
7000
- key: meshRef.value?.uuid,
7001
- id: scene?.value.uuid,
7002
- style: styles.value
7003
- }, slots.default?.());
7004
- render(vnode.value, el.value);
7043
+ slots.default?.(),
7044
+ camera.activeCamera.value
7045
+ ], ([group, r]) => {
7046
+ if (!group || !r || !camera.activeCamera.value) return;
7047
+ isMeshSizeSet.value = false;
7048
+ scene.value?.updateMatrixWorld();
7049
+ const elStyle = el.value.style;
7050
+ elStyle.position = "absolute";
7051
+ elStyle.top = "0";
7052
+ elStyle.left = "0";
7053
+ if (transform.value) {
7054
+ elStyle.pointerEvents = "none";
7055
+ elStyle.overflow = "hidden";
7056
+ elStyle.transformStyle = "preserve-3d";
7057
+ } else {
7058
+ elStyle.transformOrigin = "0 0";
7059
+ elStyle.willChange = "transform";
7060
+ if (!occlude.value) elStyle.zIndex = `${zIndexRange.value[0]}`;
7005
7061
  }
7062
+ const parent = portal.value || r.domElement?.parentNode;
7063
+ if (parent && !el.value.parentNode) prepend.value ? parent.prepend(el.value) : parent.appendChild(el.value);
7064
+ vnode.value = transform.value ? createVNode("div", { style: styles.value }, [createVNode("div", { style: transformInnerStyles.value }, [createVNode("div", {
7065
+ key: groupRef.value?.uuid,
7066
+ class: attrs.class,
7067
+ style: attrs.style
7068
+ }, slots.default?.())])]) : createVNode("div", {
7069
+ key: groupRef.value?.uuid,
7070
+ style: styles.value,
7071
+ class: attrs.class
7072
+ }, slots.default?.());
7073
+ render(vnode.value, el.value);
7006
7074
  });
7007
7075
  watchEffect(() => {
7008
- if (wrapperClass?.value) el.value.className = wrapperClass.value;
7076
+ if (wrapperClass.value) el.value.className = wrapperClass.value;
7009
7077
  });
7010
- const visible = ref(true);
7011
7078
  const { onBeforeRender } = useLoop();
7012
- onBeforeRender(() => {
7013
- if (groupRef.value && camera.activeCamera.value && renderer.instance) {
7014
- camera.activeCamera.value?.updateMatrixWorld();
7015
- groupRef.value.updateWorldMatrix(true, false);
7016
- const vector = transform.value ? previousPosition.value : calculatePosition(groupRef.value, camera.activeCamera.value, {
7017
- width: sizes.width.value || 0,
7018
- height: sizes.height.value || 0
7019
- });
7020
- if (transform.value || Math.abs(previousZoom.value - camera.activeCamera.value.zoom) > eps.value || Math.abs(previousPosition.value[0] - vector[0]) > eps.value || Math.abs(previousPosition.value[1] - vector[1]) > eps.value || Math.abs(previousPosition.value[2] - vector[2]) > eps.value) {
7021
- const isBehindCamera = isObjectBehindCamera(groupRef.value, camera.activeCamera.value);
7022
- let raytraceTarget = false;
7023
- if (isRayCastOcclusion.value) {
7024
- if (Array.isArray(occlude?.value)) raytraceTarget = occlude?.value;
7025
- else if (occlude?.value !== "blending") raytraceTarget = [scene.value];
7026
- }
7027
- const previouslyVisible = visible.value;
7028
- if (raytraceTarget) visible.value = isObjectVisible(groupRef.value, camera.activeCamera.value, raycaster.value, raytraceTarget) && !isBehindCamera;
7029
- else visible.value = !isBehindCamera;
7030
- if (previouslyVisible !== visible.value) {
7031
- emits("onOcclude", !visible.value);
7032
- el.value.style.display = visible.value ? "block" : "none";
7033
- }
7034
- const halfRange = Math.floor(zIndexRange.value[0] / 2);
7035
- const zRange = occlude?.value ? isRayCastOcclusion.value ? [zIndexRange.value[0], halfRange] : [halfRange - 1, 0] : zIndexRange.value;
7036
- el.value.style.zIndex = `${objectZIndex(groupRef.value, camera.activeCamera.value, zRange)}`;
7037
- if (transform.value) {
7038
- const [widthHalf, heightHalf] = [sizes.width.value / 2, sizes.height.value / 2];
7039
- const fov = camera.activeCamera.value.projectionMatrix.elements[5] * heightHalf;
7040
- const { isOrthographicCamera: isOrthographicCamera$2, top, left, bottom, right } = camera.activeCamera.value;
7041
- const cameraMatrix = getCameraCSSMatrix(camera.activeCamera.value.matrixWorldInverse);
7042
- const cameraTransform = isOrthographicCamera$2 ? `scale(${fov})translate(${epsilon(-(right + left) / 2)}px,${epsilon((top + bottom) / 2)}px)` : `translateZ(${fov}px)`;
7043
- let matrix = groupRef.value.matrixWorld;
7044
- if (sprite.value) {
7045
- matrix = camera.activeCamera.value.matrixWorldInverse.clone().transpose().copyPosition(matrix).scale(groupRef.value.scale);
7046
- matrix.elements[3] = matrix.elements[7] = matrix.elements[11] = 0;
7047
- matrix.elements[15] = 1;
7048
- }
7049
- el.value.style.width = `${sizes.width.value}px`;
7050
- el.value.style.height = `${sizes.height.value}px`;
7051
- el.value.style.perspective = isOrthographicCamera$2 ? "" : `${fov}px`;
7052
- if (vnode.value?.el && vnode.value?.children && Array.isArray(vnode.value.children)) {
7053
- vnode.value.el.style.transform = `${cameraTransform}${cameraMatrix}translate(${widthHalf}px,${heightHalf}px)`;
7054
- const firstChild = vnode.value.children[0];
7055
- if (firstChild && firstChild.el) firstChild.el.style.transform = getObjectCSSMatrix(matrix, 1 / ((distanceFactor?.value || 10) / 400));
7056
- }
7057
- } else {
7058
- const scale = distanceFactor?.value === void 0 ? 1 : objectScale(groupRef.value, camera.activeCamera.value) * distanceFactor?.value;
7059
- el.value.style.transform = `translate3d(${vector[0]}px,${vector[1]}px,0) scale(${scale})`;
7060
- }
7079
+ onBeforeRender(({ invalidate }) => {
7080
+ const group = groupRef.value;
7081
+ const cam = camera.activeCamera.value;
7082
+ const rend = renderer.instance;
7083
+ if (!group || !cam || !rend) return;
7084
+ cam.updateMatrixWorld();
7085
+ group.updateWorldMatrix(true, false);
7086
+ const width = sizes.width.value;
7087
+ const height = sizes.height.value;
7088
+ const widthHalf = width * .5;
7089
+ const heightHalf = height * .5;
7090
+ const newPos = transform.value ? previousPosition.value : calculatePosition$1.value(group, cam, {
7091
+ width,
7092
+ height
7093
+ });
7094
+ const posChanged = Math.abs(previousZoom.value - cam.zoom) > eps.value || Math.abs(previousPosition.value[0] - newPos[0]) > eps.value || Math.abs(previousPosition.value[1] - newPos[1]) > eps.value || Math.abs(previousPosition.value[2] - newPos[2]) > eps.value;
7095
+ let changed = transform.value || posChanged;
7096
+ let visible = true;
7097
+ const behind = isObjectBehindCamera(group, cam);
7098
+ if (isRayCastOcclusion.value) {
7099
+ let targets = false;
7100
+ if (Array.isArray(occlude.value)) targets = occlude.value;
7101
+ else if (occlude.value !== "blending") targets = [scene.value];
7102
+ if (targets) visible = isObjectVisible(group, cam, raycaster, targets) && !behind;
7103
+ } else visible = !behind;
7104
+ if (visible !== isVisible.value) {
7105
+ isVisible.value = visible;
7106
+ el.value.style.display = visible ? "block" : "none";
7107
+ emits("onOcclude", !visible);
7108
+ changed = true;
7109
+ }
7110
+ const halfRange = Math.floor(zIndexRange.value[0] / 2);
7111
+ const zRange = occlude.value ? isRayCastOcclusion.value ? [zIndexRange.value[0], halfRange] : [halfRange - 1, 0] : zIndexRange.value;
7112
+ el.value.style.zIndex = `${objectZIndex(group, cam, zRange)}`;
7113
+ if (transform.value) {
7114
+ const persp = cam.projectionMatrix.elements[5] * heightHalf;
7115
+ const camMatrix = getCameraCSSMatrix(cam.matrixWorldInverse);
7116
+ const isOrtho = cam instanceof OrthographicCamera;
7117
+ const cameraTransform = isOrtho ? `scale(${persp})translate(${epsilon(-(cam.right + cam.left) / 2)}px,${epsilon((cam.top + cam.bottom) / 2)}px)` : `translateZ(${persp}px)`;
7118
+ let finalMatrix = group.matrixWorld;
7119
+ if (sprite.value) {
7120
+ tmpMatrix.copy(group.matrixWorld);
7121
+ const invCamMat = cam.matrixWorldInverse.clone().transpose();
7122
+ tmpQuat.setFromRotationMatrix(invCamMat);
7123
+ tmpMatrix.makeRotationFromQuaternion(tmpQuat);
7124
+ group.getWorldPosition(tmpVec);
7125
+ tmpMatrix.setPosition(tmpVec);
7126
+ tmpMatrix.scale(group.scale);
7127
+ tmpMatrix.elements[3] = tmpMatrix.elements[7] = tmpMatrix.elements[11] = 0;
7128
+ tmpMatrix.elements[15] = 1;
7129
+ finalMatrix = tmpMatrix;
7130
+ }
7131
+ const style = el.value.style;
7132
+ style.width = `${width}px`;
7133
+ style.height = `${height}px`;
7134
+ style.perspective = isOrtho ? "" : `${persp}px`;
7135
+ if (vnode.value?.el) {
7136
+ vnode.value.el.style.transform = `${cameraTransform}${camMatrix}translate(${widthHalf}px,${heightHalf}px)`;
7137
+ let inner;
7138
+ if (Array.isArray(vnode.value.children)) inner = vnode.value.children[0];
7139
+ if (inner?.el) inner.el.style.transform = getObjectCSSMatrix(finalMatrix, 1 / ((distanceFactor.value || 10) / 400));
7061
7140
  }
7062
- previousPosition.value = vector;
7063
- previousZoom.value = camera.activeCamera.value.zoom;
7141
+ } else {
7142
+ const scale = distanceFactor.value === void 0 ? 1 : objectScale(group, cam) * distanceFactor.value;
7143
+ el.value.style.transform = `translate3d(${newPos[0]}px,${newPos[1]}px,0) scale(${scale})`;
7064
7144
  }
7065
- if (!isRayCastOcclusion.value && meshRef.value && !isMeshSizeSet.value) if (transform.value) {
7066
- if (vnode.value?.el && vnode.value?.children) {
7067
- const el$1 = (vnode.value?.children)[0];
7068
- if (el$1?.clientWidth && el$1?.clientHeight) {
7069
- const { isOrthographicCamera: isOrthographicCamera$2 } = camera.activeCamera.value;
7070
- if (isOrthographicCamera$2 || geometry) {
7071
- if (attrs.scale) if (!Array.isArray(attrs.scale)) meshRef.value.scale.setScalar(1 / attrs.scale);
7072
- else if (attrs.scale instanceof Vector3) meshRef.value.scale.copy(attrs.scale.clone().divideScalar(1));
7073
- else meshRef.value.scale.set(1 / attrs.scale[0], 1 / attrs.scale[1], 1 / attrs.scale[2]);
7074
- } else {
7075
- const ratio = (distanceFactor?.value || 10) / 400;
7076
- const w = el$1.clientWidth * ratio;
7077
- const h = el$1.clientHeight * ratio;
7078
- meshRef.value.scale.set(w, h, 1);
7145
+ previousPosition.value = [
7146
+ newPos[0],
7147
+ newPos[1],
7148
+ newPos[2]
7149
+ ];
7150
+ previousZoom.value = cam.zoom;
7151
+ if (!isRayCastOcclusion.value && occlusionMeshRef.value && !isMeshSizeSet.value) {
7152
+ const mesh = occlusionMeshRef.value;
7153
+ if (transform.value) {
7154
+ const children = vnode.value?.children;
7155
+ if (Array.isArray(children)) {
7156
+ const element = children[0]?.el;
7157
+ if (element) {
7158
+ const isOrtho = cam instanceof OrthographicCamera;
7159
+ if (isOrtho && geometry.value && attrs.scale) if (!Array.isArray(attrs.scale)) mesh.scale.setScalar(1 / attrs.scale);
7160
+ else if (attrs.scale instanceof Vector3) mesh.scale.copy(attrs.scale);
7161
+ else mesh.scale.set(1 / attrs.scale[0], 1 / attrs.scale[1], 1 / attrs.scale[2]);
7162
+ else if (!isOrtho && !geometry.value) {
7163
+ const ratio = (distanceFactor.value || 10) / 400;
7164
+ if (sprite.value) {
7165
+ effectiveMaterial.value.uniforms.uWidth.value = element.clientWidth * ratio;
7166
+ effectiveMaterial.value.uniforms.uHeight.value = element.clientHeight * ratio;
7167
+ mesh.lookAt(cam.position);
7168
+ mesh.scale.set(1, 1, 1);
7169
+ } else {
7170
+ const w = element.clientWidth * ratio;
7171
+ const h = element.clientHeight * ratio;
7172
+ mesh.scale.set(w, h, 1);
7173
+ }
7174
+ }
7175
+ isMeshSizeSet.value = true;
7079
7176
  }
7177
+ }
7178
+ } else {
7179
+ const element = el.value.children[0];
7180
+ if (element?.clientWidth && element?.clientHeight) {
7181
+ group.getWorldPosition(tmpVec);
7182
+ const ratio = 1 / getViewportFactor(cam, tmpVec, {
7183
+ width,
7184
+ height
7185
+ });
7186
+ effectiveMaterial.value.uniforms.uWidth.value = element.clientWidth * ratio;
7187
+ effectiveMaterial.value.uniforms.uHeight.value = element.clientHeight * ratio;
7188
+ mesh.scale.set(1, 1, 1);
7189
+ mesh.lookAt(cam.position);
7080
7190
  isMeshSizeSet.value = true;
7081
7191
  }
7082
7192
  }
7083
- } else {
7084
- const ele = el.value.children[0];
7085
- if (ele?.clientWidth && ele?.clientHeight) {
7086
- const ratio = 1 / 1;
7087
- const w = ele.clientWidth * ratio;
7088
- const h = ele.clientHeight * ratio;
7089
- meshRef.value.scale.set(w, h, 1);
7090
- isMeshSizeSet.value = true;
7091
- }
7092
- occlusionMeshRef.value.lookAt(camera.activeCamera.value?.position);
7093
7193
  }
7094
- });
7095
- const shaders = computed(() => ({
7096
- vertexShader: transform.value ? void 0 : vertex_default,
7097
- fragmentShader: fragment_default
7098
- }));
7099
- const shaderMaterial$1 = computed(() => {
7100
- const shader = shaders.value;
7101
- return material.value || new ShaderMaterial({
7102
- vertexShader: shader.vertexShader,
7103
- fragmentShader: shader.fragmentShader,
7104
- side: DoubleSide
7105
- });
7194
+ if (changed) invalidate();
7106
7195
  });
7107
7196
  onUnmounted(() => {
7108
- if (shaderMaterial$1.value) shaderMaterial$1.value.dispose();
7109
- el.value.remove();
7197
+ defaultPlaneGeometry?.dispose();
7198
+ effectiveMaterial.value?.dispose();
7199
+ if (el.value?.parentNode) el.value.parentNode.removeChild(el.value);
7200
+ });
7201
+ __expose({
7202
+ instance: groupRef,
7203
+ isVisible,
7204
+ occlusionMesh: occlusionMeshRef
7110
7205
  });
7111
- __expose({ instance: groupRef });
7112
7206
  return (_ctx, _cache) => {
7113
- return openBlock(), createElementBlock("TresGroup", {
7207
+ return openBlock(), createElementBlock("TresGroup", mergeProps(_ctx.$attrs, {
7114
7208
  ref_key: "groupRef",
7115
7209
  ref: groupRef
7116
- }, [unref(occlude) && !isRayCastOcclusion.value ? (openBlock(), createElementBlock("TresMesh", {
7210
+ }), [unref(occlude) && !isRayCastOcclusion.value ? (openBlock(), createElementBlock("TresMesh", {
7117
7211
  key: 0,
7118
- ref_key: "meshRef",
7119
- ref: meshRef,
7120
- geometry: unref(geometry),
7121
- material: shaderMaterial$1.value
7122
- }, null, 8, _hoisted_1$33)) : createCommentVNode("v-if", true)], 512);
7212
+ ref_key: "occlusionMeshRef",
7213
+ ref: occlusionMeshRef,
7214
+ material: effectiveMaterial.value,
7215
+ "cast-shadow": unref(castShadow),
7216
+ "receive-shadow": unref(receiveShadow),
7217
+ geometry: unref(geometry) || unref(defaultPlaneGeometry)
7218
+ }, null, 8, _hoisted_1$33)) : createCommentVNode("v-if", true)], 16);
7123
7219
  };
7124
7220
  }
7125
7221
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tresjs/cientos",
3
3
  "type": "module",
4
- "version": "5.1.2",
4
+ "version": "5.2.0",
5
5
  "description": "Collection of useful helpers and fully functional, ready-made abstractions for Tres",
6
6
  "author": "Alvaro Saburido <hola@alvarosaburido.dev> (https://github.com/alvarosabu/)",
7
7
  "license": "MIT",
@@ -73,8 +73,8 @@
73
73
  "vite-plugin-glsl": "^1.5.1",
74
74
  "vite-svg-loader": "^5.1.0",
75
75
  "vue-tsc": "^3.1.1",
76
- "@tresjs/eslint-config": "1.5.1",
77
- "@tresjs/core": "5.2.0"
76
+ "@tresjs/core": "5.2.0",
77
+ "@tresjs/eslint-config": "1.5.1"
78
78
  },
79
79
  "nx": {
80
80
  "implicitDependencies": [