@configura/web-core 1.3.0-alpha.2 → 1.3.0-alpha.7

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.
Files changed (69) hide show
  1. package/dist/cm/core3D/ATriMeshF.d.ts +7 -1
  2. package/dist/cm/core3D/ATriMeshF.js +9 -5
  3. package/dist/cm/core3D/GMaterial3D.d.ts +4 -0
  4. package/dist/cm/core3D/GMaterial3D.js +4 -4
  5. package/dist/cm/core3D/GMaterialPBR.js +25 -13
  6. package/dist/cm/core3D/{UVMapEnv.d.ts → uvmapper/UVMapEnv.d.ts} +3 -1
  7. package/dist/cm/core3D/{UVMapEnv.js → uvmapper/UVMapEnv.js} +13 -1
  8. package/dist/cm/core3D/uvmapper/UVMapper.d.ts +42 -0
  9. package/dist/cm/core3D/uvmapper/UVMapper.js +94 -0
  10. package/dist/cm/core3D/uvmapper/UVMapperBox.d.ts +5 -0
  11. package/dist/cm/core3D/uvmapper/UVMapperBox.js +181 -0
  12. package/dist/cm/core3D/uvmapper/UVMapperCylinder.d.ts +10 -0
  13. package/dist/cm/core3D/uvmapper/UVMapperCylinder.js +96 -0
  14. package/dist/cm/core3D/uvmapper/UVMapperPlane.d.ts +4 -0
  15. package/dist/cm/core3D/uvmapper/UVMapperPlane.js +84 -0
  16. package/dist/cm/core3D/{UVTransformer.d.ts → uvmapper/UVTransformer.d.ts} +1 -1
  17. package/dist/cm/core3D/{UVTransformer.js → uvmapper/UVTransformer.js} +0 -0
  18. package/dist/cm/core3D/uvmapper/instantiateUVMapper.d.ts +4 -0
  19. package/dist/cm/core3D/uvmapper/instantiateUVMapper.js +4 -0
  20. package/dist/cm/format/cmsym/SymNode.d.ts +8 -0
  21. package/dist/cm/format/cmsym/SymNode.js +75 -0
  22. package/dist/cm/format/cmsym/components/SymBox.d.ts +1 -0
  23. package/dist/cm/format/cmsym/components/SymBox.js +8 -3
  24. package/dist/cm/format/cmsym/components/SymGMaterialSelector.d.ts +5 -0
  25. package/dist/cm/format/cmsym/components/SymGMaterialSelector.js +5 -3
  26. package/dist/cm/format/cmsym/components/SymMeasure.d.ts +3 -4
  27. package/dist/cm/format/cmsym/components/SymMeasure.js +20 -29
  28. package/dist/cm/format/cmsym/components/SymMultiSelector.js +7 -8
  29. package/dist/cm/format/cmsym/components/SymParams.d.ts +12 -0
  30. package/dist/cm/format/cmsym/components/SymParams.js +51 -0
  31. package/dist/cm/format/cmsym/components/SymPlane.d.ts +1 -1
  32. package/dist/cm/format/cmsym/components/SymPlane.js +4 -1
  33. package/dist/cm/format/cmsym/components/SymProgs.d.ts +28 -0
  34. package/dist/cm/format/cmsym/components/SymProgs.js +113 -0
  35. package/dist/cm/format/cmsym/components/SymProps.d.ts +1 -1
  36. package/dist/cm/format/cmsym/components/SymRep.d.ts +4 -4
  37. package/dist/cm/format/cmsym/components/SymRep.js +5 -5
  38. package/dist/cm/format/cmsym/components/SymReps.js +3 -3
  39. package/dist/cm/format/cmsym/components/SymShape.js +4 -1
  40. package/dist/cm/format/cmsym/components/SymSphere.d.ts +2 -0
  41. package/dist/cm/format/cmsym/components/SymSphere.js +6 -3
  42. package/dist/cm/format/cmsym/components/SymText2D.d.ts +1 -0
  43. package/dist/cm/format/cmsym/components/SymText2D.js +1 -1
  44. package/dist/cm/format/cmsym/components/SymText3D.d.ts +1 -0
  45. package/dist/cm/format/cmsym/components/SymText3D.js +1 -1
  46. package/dist/cm/format/cmsym/components/SymUVMapper.d.ts +4 -4
  47. package/dist/cm/format/cmsym/components/SymUVMapper.js +3 -3
  48. package/dist/cm/format/dex/DexObj.d.ts +1 -1
  49. package/dist/cm/format/dex/DexObj.js +1 -1
  50. package/dist/cm/format/dex/DexReader.d.ts +5 -1
  51. package/dist/cm/format/dex/DexReader.js +40 -0
  52. package/dist/cm/geometry/Angle.js +2 -2
  53. package/dist/cm/geometry/DetailMask.d.ts +5 -0
  54. package/dist/cm/geometry/DetailMask.js +7 -5
  55. package/dist/cm/geometry/Matrix22.d.ts +1 -0
  56. package/dist/cm/geometry/Matrix22.js +3 -0
  57. package/dist/cm/geometry/Plane.d.ts +2 -2
  58. package/dist/cm/geometry/Point.d.ts +3 -0
  59. package/dist/cm/geometry/Point.js +9 -0
  60. package/dist/cm/geometry/Point2D.d.ts +1 -0
  61. package/dist/cm/geometry/Point2D.js +3 -0
  62. package/dist/cm/geometry/Transform2D.d.ts +2 -2
  63. package/dist/cm/io/Semver.d.ts +1 -0
  64. package/dist/cm/io/Semver.js +4 -1
  65. package/package.json +4 -4
  66. package/dist/cm/core3D/DummyUVMapper.d.ts +0 -7
  67. package/dist/cm/core3D/DummyUVMapper.js +0 -6
  68. package/dist/cm/core3D/instantiateUVMapper.d.ts +0 -4
  69. package/dist/cm/core3D/instantiateUVMapper.js +0 -5
@@ -50,7 +50,8 @@ export declare class ATriMeshF {
50
50
  */
51
51
  doubleSided: boolean;
52
52
  constructor(data: Uint8Array | undefined, lowerLeftTextureOrigin: boolean, doubleSided: boolean);
53
- static createWithArrays(indices: Uint32Array, vertices: Float32Array, normals: Float32Array, uvs?: Float32Array, colors?: Float32Array, tangents?: Float32Array): ATriMeshF;
53
+ /** Creates and returns a new ATriMeshF with the mesh data supplied. */
54
+ static createWithArrays(indices: Uint32Array, vertices: Float32Array, normals?: Float32Array, uvs?: Float32Array, colors?: Float32Array, tangents?: Float32Array): ATriMeshF;
54
55
  get indices(): Uint32Array;
55
56
  get vertices(): Float32Array;
56
57
  get normals(): Float32Array;
@@ -81,6 +82,11 @@ export declare class ATriMeshF {
81
82
  * public geometry getters.
82
83
  */
83
84
  load(): void;
85
+ /**
86
+ * Calculates and sets tangent data if this ATriMeshF has normals but no gradient (constant) UV
87
+ * coordinates. Without this fix, shader calculations that depends on UV gradients can fail.
88
+ * This is only a workaround since a the tangent is not well defined without a UV gradient.
89
+ */
84
90
  private computeTangentsIfNeeded;
85
91
  hasNormals(): boolean;
86
92
  hasUVCoordinates(): boolean;
@@ -26,12 +26,14 @@ export class ATriMeshF {
26
26
  this._colors = new Float32Array(0);
27
27
  this._tangents = new Float32Array(0);
28
28
  }
29
- /// Creates and returns a new ATriMeshF with the mesh data supplied.
29
+ /** Creates and returns a new ATriMeshF with the mesh data supplied. */
30
30
  static createWithArrays(indices, vertices, normals, uvs, colors, tangents) {
31
31
  const mesh = new ATriMeshF(undefined, false, false);
32
32
  mesh._indices = indices;
33
33
  mesh._vertices = vertices;
34
- mesh._normals = normals;
34
+ if (normals !== undefined) {
35
+ mesh._normals = normals;
36
+ }
35
37
  if (uvs !== undefined) {
36
38
  mesh._uvs = uvs;
37
39
  }
@@ -129,9 +131,11 @@ export class ATriMeshF {
129
131
  // );
130
132
  this.computeTangentsIfNeeded();
131
133
  }
132
- /// Calculates and sets tangent data if this ATriMeshF has normals but no gradient (constant)
133
- /// UV coordinates. Without this fix, shader calculations that depends on UV gradients can fail.
134
- /// This is only a workaround since a the tangent is not well defined without a UV gradient.
134
+ /**
135
+ * Calculates and sets tangent data if this ATriMeshF has normals but no gradient (constant) UV
136
+ * coordinates. Without this fix, shader calculations that depends on UV gradients can fail.
137
+ * This is only a workaround since a the tangent is not well defined without a UV gradient.
138
+ */
135
139
  computeTangentsIfNeeded() {
136
140
  if (this._uvs.length < 2 || this._normals.length < 3) {
137
141
  return;
@@ -31,6 +31,7 @@ export declare const enum TextureType {
31
31
  pbrRefraction = "refraction",
32
32
  pbrRoughness = "roughness"
33
33
  }
34
+ /** Common texture class used both by Classic and PBR GMaterials. */
34
35
  export declare class GMaterial3DTexture {
35
36
  readonly type: TextureType;
36
37
  constructor(type: TextureType);
@@ -39,13 +40,16 @@ export declare class GMaterial3DTexture {
39
40
  vScale: number;
40
41
  uOffset: number;
41
42
  vOffset: number;
43
+ /** Texture rotation in radians. */
42
44
  rot: number;
43
45
  wrapU: TextureWrap;
44
46
  wrapV: TextureWrap;
45
47
  minFilter: TextureFilter;
46
48
  magFilter: TextureFilter;
49
+ /** mipFilter is tristate. Also not (yet) included in the CmSym PBR specification. */
47
50
  mipFilter: TextureFilter | undefined;
48
51
  }
52
+ /** Common settings for both Classic and PBR GMaterials. */
49
53
  export declare class GMaterial3D {
50
54
  materialKey?: string;
51
55
  doubleSided: boolean;
@@ -1,7 +1,7 @@
1
1
  import { DexObj } from "../format/dex/DexObj.js";
2
2
  import { DexURL } from "../format/dex/DexURL.js";
3
3
  import { DexXRef } from "../format/dex/DexXRef.js";
4
- /// Common texture class used both by Classic and PBR GMaterials
4
+ /** Common texture class used both by Classic and PBR GMaterials. */
5
5
  export class GMaterial3DTexture {
6
6
  constructor(type) {
7
7
  this.type = type;
@@ -10,7 +10,7 @@ export class GMaterial3DTexture {
10
10
  this.vScale = 1;
11
11
  this.uOffset = 0;
12
12
  this.vOffset = 0;
13
- /// Texture rotation in radians
13
+ /** Texture rotation in radians. */
14
14
  this.rot = 0;
15
15
  // Texture wrap modes
16
16
  this.wrapU = 0 /* repeat */;
@@ -18,11 +18,11 @@ export class GMaterial3DTexture {
18
18
  // Texture filtering. Default to trilinear.
19
19
  this.minFilter = 0 /* linear */;
20
20
  this.magFilter = 0 /* linear */;
21
- /// mipFilter is tristate. Also not (yet) included in the CmSym PBR specification.
21
+ /** mipFilter is tristate. Also not (yet) included in the CmSym PBR specification. */
22
22
  this.mipFilter = 0 /* linear */;
23
23
  }
24
24
  }
25
- /// Common settings for both Classic and PBR GMaterials
25
+ /** Common settings for both Classic and PBR GMaterials. */
26
26
  export class GMaterial3D {
27
27
  constructor(log, obj) {
28
28
  this.doubleSided = false;
@@ -1,7 +1,7 @@
1
1
  import { ColorF } from "../basic/ColorF.js";
2
2
  import { DexObj } from "../format/dex/DexObj.js";
3
3
  import { AngleF } from "../geometry/AngleF.js";
4
- import { GMaterial3D, GMaterial3DTexture, imageUrlFromDex, textureWrapFromDex } from "./GMaterial3D.js";
4
+ import { GMaterial3D, GMaterial3DTexture, imageUrlFromDex, textureWrapFromDex, } from "./GMaterial3D.js";
5
5
  // tslint:disable:max-classes-per-file
6
6
  export class GMaterialPBR extends GMaterial3D {
7
7
  constructor(log, obj) {
@@ -159,8 +159,10 @@ export class PBRRoughness {
159
159
  this.channel = channel;
160
160
  }
161
161
  }
162
- /// Loads and returns the specified texture. Returns undefined if the texture was not found (they
163
- /// are optional) or there was an problem loading the texture.
162
+ /**
163
+ * Loads and returns the specified texture. Returns undefined if the texture was not found (they
164
+ * are optional) or there was an problem loading the texture.
165
+ */
164
166
  function loadTexture(log, type, dex) {
165
167
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
166
168
  const scope = type + ".texture";
@@ -201,8 +203,10 @@ function loadTexture(log, type, dex) {
201
203
  }
202
204
  return txt;
203
205
  }
204
- /// Loads and returns the TextureFilter specified by the name parameter.
205
- /// Returns undefined if the object was not found or not of the correct type.
206
+ /**
207
+ * Loads and returns the TextureFilter specified by the name parameter.
208
+ * Returns undefined if the object was not found or not of the correct type.
209
+ */
206
210
  function loadTextureFilter(log, scope, dex, name) {
207
211
  const obj = dex.get(name);
208
212
  switch (obj) {
@@ -240,8 +244,10 @@ function loadChannels(log, scope, dex, name = "channels") {
240
244
  log.warn(`Channels property not valid (${scope}.${name}): ${obj}`);
241
245
  return undefined;
242
246
  }
243
- /// Loads and returns the number specified by the name parameter.
244
- /// Returns undefined if the object was not found or not of the correct type.
247
+ /**
248
+ * Loads and returns the number specified by the name parameter.
249
+ * Returns undefined if the object was not found or not of the correct type.
250
+ */
245
251
  function loadNumber(log, scope, dex, name) {
246
252
  const obj = dex.get(name);
247
253
  if (obj !== undefined && typeof obj !== "number") {
@@ -250,8 +256,10 @@ function loadNumber(log, scope, dex, name) {
250
256
  }
251
257
  return obj;
252
258
  }
253
- /// Loads and returns the angle (in radians) specified by the name parameter.
254
- /// Returns undefined if the object was not found or not of the correct type.
259
+ /**
260
+ * Loads and returns the angle (in radians) specified by the name parameter.
261
+ * Returns undefined if the object was not found or not of the correct type.
262
+ */
255
263
  function loadAngle(log, scope, dex, name) {
256
264
  const obj = dex.get(name);
257
265
  if (obj !== undefined && !(obj instanceof AngleF)) {
@@ -260,8 +268,10 @@ function loadAngle(log, scope, dex, name) {
260
268
  }
261
269
  return obj === null || obj === void 0 ? void 0 : obj.radians;
262
270
  }
263
- /// Loads and returns the ColorF specified by the name parameter.
264
- /// Returns <1,1,1,1> if the object was not found or not of the correct type.
271
+ /**
272
+ * Loads and returns the ColorF specified by the name parameter.
273
+ * Returns <1,1,1,1> if the object was not found or not of the correct type.
274
+ */
265
275
  function loadColorF(log, scope, dex, name) {
266
276
  const obj = dex.get(name);
267
277
  if (!(obj instanceof ColorF)) {
@@ -272,8 +282,10 @@ function loadColorF(log, scope, dex, name) {
272
282
  }
273
283
  return obj;
274
284
  }
275
- /// Loads and returns the PBROpacityMode mode.
276
- /// Returns "opaque" if the object was not found or not of the correct type.
285
+ /**
286
+ * Loads and returns the PBROpacityMode mode.
287
+ * Returns "opaque" if the object was not found or not of the correct type.
288
+ */
277
289
  function loadOpacityMode(log, scope, dex) {
278
290
  const obj = dex.get("mode");
279
291
  switch (obj) {
@@ -1,4 +1,4 @@
1
- import { Point } from "../geometry/Point.js";
1
+ import { Point } from "../../geometry/Point.js";
2
2
  import { UVTransformer } from "./UVTransformer.js";
3
3
  export declare enum UVMapperType {
4
4
  Box = 0,
@@ -14,5 +14,7 @@ export declare class UVMapEnv {
14
14
  normal: Point;
15
15
  uniform: boolean;
16
16
  constructor(type: UVMapperType, transforms?: UVTransformer[] | undefined, normal?: Point, uniform?: boolean);
17
+ private _hash;
18
+ get hash(): number;
17
19
  }
18
20
  //# sourceMappingURL=UVMapEnv.d.ts.map
@@ -1,4 +1,5 @@
1
- import { Point } from "../geometry/Point.js";
1
+ import { hashCode } from "@configura/web-utilities";
2
+ import { Point } from "../../geometry/Point.js";
2
3
  export var UVMapperType;
3
4
  (function (UVMapperType) {
4
5
  UVMapperType[UVMapperType["Box"] = 0] = "Box";
@@ -32,4 +33,15 @@ export class UVMapEnv {
32
33
  this.normal = normal;
33
34
  this.uniform = uniform;
34
35
  }
36
+ get hash() {
37
+ if (this._hash === undefined) {
38
+ this._hash = hashCode(`ty${this.type}-tr${(this.transforms || [])
39
+ .map((t) => {
40
+ const { pos, mapping } = t.transform;
41
+ return `po${pos.toString()}-ma${mapping.toString()}`;
42
+ })
43
+ .join("-")}-no${this.normal.toString()}-un${this.uniform}`);
44
+ }
45
+ return this._hash;
46
+ }
35
47
  }
@@ -0,0 +1,42 @@
1
+ import { Logger } from "@configura/web-utilities";
2
+ import { UVMapEnv } from "./UVMapEnv.js";
3
+ import { UVTransformer } from "./UVTransformer.js";
4
+ export declare type MinMaxSize = {
5
+ min: number[];
6
+ max: number[];
7
+ size: number[];
8
+ };
9
+ export declare class UVMapper {
10
+ env?: UVMapEnv | undefined;
11
+ /**
12
+ * Applies linear transformations to the UV-coordinates. This is essentially rotating, scaling
13
+ * moving the texture before applying it.
14
+ */
15
+ static applyUvTransform(uv: [number, number], t: UVTransformer): [number, number];
16
+ static calculateLimits(bounds: MinMaxSize, refBounds: MinMaxSize | undefined): {
17
+ refMin: number[];
18
+ refSize: number[];
19
+ textureFixMin: number[];
20
+ textureFixMax: number[];
21
+ };
22
+ static calculateTextureFixLimits(bounds: MinMaxSize, refBounds: MinMaxSize): {
23
+ min: number[];
24
+ max: number[];
25
+ };
26
+ constructor(env?: UVMapEnv | undefined);
27
+ /**
28
+ * Do not use this method if you have prebaked coordinates in the CmSym file generated by CET.
29
+ * It is safer to use the existing ones since CET has already modified the geometry of the
30
+ * mesh by splitting vertices etc.
31
+ */
32
+ createUVCoordinates(logger: Logger, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array): Float32Array;
33
+ /**
34
+ * @param positions Stretched positions
35
+ * @param normals Used both for stretched and non-stretched. We cheat a bit by always using the same normals
36
+ * @param refPositions Non-stretched positions
37
+ * @param refUvs Non-stretched UV coordinates
38
+ * @returns
39
+ */
40
+ createUVCoordinatesForStretched(logger: Logger, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array, refPositions: Float32Array, refBounds: MinMaxSize, refUvs: Float32Array): Float32Array;
41
+ }
42
+ //# sourceMappingURL=UVMapper.d.ts.map
@@ -0,0 +1,94 @@
1
+ import { UVMapperType } from "./UVMapEnv.js";
2
+ import { createUVBoxCoordinates, createUVBoxCoordinatesForStretched } from "./UVMapperBox.js";
3
+ import { createUVCylinderCoordinates, createUVCylinderCoordinatesForStretched, } from "./UVMapperCylinder.js";
4
+ import { createUVPlaneCoordinates, createUVPlaneCoordinatesForStretched } from "./UVMapperPlane.js";
5
+ const xyz = [0, 1, 2];
6
+ export class UVMapper {
7
+ constructor(env) {
8
+ this.env = env;
9
+ }
10
+ /**
11
+ * Applies linear transformations to the UV-coordinates. This is essentially rotating, scaling
12
+ * moving the texture before applying it.
13
+ */
14
+ static applyUvTransform(uv, t) {
15
+ const { mapping, pos } = t.transform;
16
+ const [u, v] = uv;
17
+ const { x, y } = pos;
18
+ let uNew = u;
19
+ let vNew = v;
20
+ const { c0, c1 } = mapping;
21
+ uNew = c0.x * u + c1.x * v;
22
+ vNew = c0.y * u + c1.y * v;
23
+ uNew += x;
24
+ vNew += y;
25
+ return [uNew, vNew];
26
+ }
27
+ static calculateLimits(bounds, refBounds) {
28
+ const { min: refMin, size: refSize } = refBounds || bounds;
29
+ const { min: textureFixMin, max: textureFixMax } = refBounds === undefined
30
+ ? { min: [0, 0, 0], max: [0, 0, 0] }
31
+ : UVMapper.calculateTextureFixLimits(bounds, refBounds);
32
+ return {
33
+ refMin,
34
+ refSize,
35
+ textureFixMin,
36
+ textureFixMax,
37
+ };
38
+ }
39
+ static calculateTextureFixLimits(bounds, refBounds) {
40
+ return {
41
+ min: xyz.map((axis) => (refBounds.min[axis] - bounds.min[axis]) / refBounds.size[axis]),
42
+ max: xyz.map((axis) => (refBounds.max[axis] - bounds.max[axis]) / refBounds.size[axis]),
43
+ };
44
+ }
45
+ /**
46
+ * Do not use this method if you have prebaked coordinates in the CmSym file generated by CET.
47
+ * It is safer to use the existing ones since CET has already modified the geometry of the
48
+ * mesh by splitting vertices etc.
49
+ */
50
+ createUVCoordinates(logger, positions, bounds, normals) {
51
+ const env = this.env;
52
+ if (env === undefined) {
53
+ throw new Error("No UV mapping env");
54
+ }
55
+ switch (env.type) {
56
+ case UVMapperType.Box:
57
+ return createUVBoxCoordinates(env, positions, bounds, normals);
58
+ case UVMapperType.Planar:
59
+ return createUVPlaneCoordinates(env, positions);
60
+ case UVMapperType.Cylindrical:
61
+ return createUVCylinderCoordinates(env, positions, bounds, normals);
62
+ case UVMapperType.Spherical:
63
+ throw logger.errorAsObject(`Unsupported UV-mapper: ${env.type} (Spherical)`);
64
+ default:
65
+ throw logger.errorAsObject("Unknown UV-mapper: " + env.type);
66
+ }
67
+ }
68
+ /**
69
+ * @param positions Stretched positions
70
+ * @param normals Used both for stretched and non-stretched. We cheat a bit by always using the same normals
71
+ * @param refPositions Non-stretched positions
72
+ * @param refUvs Non-stretched UV coordinates
73
+ * @returns
74
+ */
75
+ createUVCoordinatesForStretched(logger, positions, bounds, normals, refPositions, refBounds, refUvs) {
76
+ const env = this.env;
77
+ if (env === undefined) {
78
+ throw new Error("No mapping env");
79
+ }
80
+ switch (env.type) {
81
+ case UVMapperType.Box:
82
+ return createUVBoxCoordinatesForStretched(env, positions, bounds, normals, refPositions, refBounds, refUvs);
83
+ case UVMapperType.Planar:
84
+ return createUVPlaneCoordinatesForStretched(env, positions, refPositions);
85
+ case UVMapperType.Cylindrical:
86
+ return createUVCylinderCoordinatesForStretched(env, positions, bounds, normals, refPositions, refBounds, refUvs);
87
+ case UVMapperType.Spherical:
88
+ logger.warn("Spherical mapping is not implemented for stretch. Original UV-coordinates will be used.");
89
+ return refUvs;
90
+ default:
91
+ throw logger.errorAsObject("Unknown UV-mapper");
92
+ }
93
+ }
94
+ }
@@ -0,0 +1,5 @@
1
+ import { UVMapEnv } from "./UVMapEnv.js";
2
+ import { MinMaxSize } from "./UVMapper.js";
3
+ export declare function createUVBoxCoordinates(env: UVMapEnv | undefined, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array): Float32Array;
4
+ export declare function createUVBoxCoordinatesForStretched(env: UVMapEnv | undefined, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array, refPositions: Float32Array, refBounds: MinMaxSize, refUvs: Float32Array): Float32Array;
5
+ //# sourceMappingURL=UVMapperBox.d.ts.map
@@ -0,0 +1,181 @@
1
+ import { UVMapper } from "./UVMapper.js";
2
+ const XYZ = [0, 1, 2];
3
+ const X = 0, Y = 1, Z = 2;
4
+ const toSide = (axis, negAxis) => axis * 2 + (negAxis ? 1 : 0);
5
+ const toAxisAndIsNeg = (side) => [Math.trunc(side / 2), side % 2 === 1];
6
+ /**
7
+ * This simulates how CET maps xyz-coordinates to uv-coordinates. On certain axis the mapping is
8
+ * flipped, this is handled here.
9
+ */
10
+ function uvFromXyz(axis, negAxis, xyz) {
11
+ let u = axis === X ? xyz[1] : xyz[0];
12
+ let v = axis === Z ? xyz[1] : xyz[2];
13
+ if ((axis === X && negAxis) || (axis === Y && !negAxis)) {
14
+ u = 1 - u;
15
+ }
16
+ if (axis === Z && negAxis) {
17
+ v = 1 - v;
18
+ }
19
+ return [u, v];
20
+ }
21
+ /**
22
+ * The recommended method for calculating what side vertices belong to. It uses already calculated
23
+ * UVs to and as such is useful when doing stretch. If you do not do stretch you don't need to use
24
+ * this mapper at all. Just use the existing UVs.
25
+ */
26
+ function calculateSideMapFromRefUvs(transforms, normals, refPositions, refBounds, refUvs) {
27
+ const vertexCount = refPositions.length / 3;
28
+ const { min: refMin, size: refSize } = refBounds;
29
+ const sideMap = new Uint8Array(vertexCount);
30
+ for (let i = 0; i < vertexCount; i++) {
31
+ const xyzOffset = i * 3;
32
+ const uvOffset = i * 2;
33
+ // Texture is applied as if the image texture was stretched to fit each side of the "cube"
34
+ const refNormalized = XYZ.map((axis) => (refPositions[xyzOffset + axis] - refMin[axis]) / refSize[axis]);
35
+ const refU = refUvs[uvOffset];
36
+ const refV = refUvs[uvOffset + 1];
37
+ // We aim at finding what side of the cube this vertex shall be textured from.
38
+ // We do this by in turn testing what UV-values we would get for non-stretched
39
+ // data and selecting the one which is the closest.
40
+ let diffOnLatestCandidate = Number.POSITIVE_INFINITY;
41
+ let normalComponentAbsOnLatestCandidate = 0;
42
+ let selectedSide;
43
+ for (let axis = 0; axis < 3; axis++) {
44
+ const normalComponent = normals[xyzOffset + axis];
45
+ const normalComponentAbs = Math.abs(normalComponent);
46
+ const negAxis = normalComponent < 0;
47
+ let [u, v] = uvFromXyz(axis, negAxis, refNormalized);
48
+ if (transforms !== undefined) {
49
+ [u, v] = UVMapper.applyUvTransform([u, v], transforms[axis]);
50
+ }
51
+ // How far off are we from the reference UV-coordinates?
52
+ const diffOnCandidate = Math.abs(refU - u) + Math.abs(refV - v);
53
+ // Here we need a lite extra care. For highly regular shapes, such as a cube it is very
54
+ // likely we will end up in a situation where the "pick best UV-match" approach does
55
+ // not work. You can imagine this as the same "color" touching the same corner from
56
+ // more than one side. In this case we also need to take the normals into account.
57
+ //
58
+ // For highly irregular shapes it is more unlikely that the texture coordinates will be
59
+ // identical, and if they are the high polygon count on such a model is likely to mask
60
+ // the error.
61
+ //
62
+ // The factors below are a bit arbitrarily chosen. They might need to be tweaked.
63
+ if (diffOnLatestCandidate - diffOnCandidate > 0.01 ||
64
+ normalComponentAbs - normalComponentAbsOnLatestCandidate > 0.9) {
65
+ selectedSide = toSide(axis, negAxis);
66
+ diffOnLatestCandidate = diffOnCandidate;
67
+ normalComponentAbsOnLatestCandidate = normalComponentAbs;
68
+ }
69
+ }
70
+ if (selectedSide === undefined) {
71
+ throw new Error("Unexpected error when calculating UV side mapping");
72
+ }
73
+ sideMap[i] = selectedSide;
74
+ }
75
+ return sideMap;
76
+ }
77
+ /**
78
+ * Fallback method of calculating what side a vertex belongs to in cases where you have no refUvs.
79
+ * It will give bad results in the boundary areas where mapping from different sides meet.
80
+ *
81
+ * WARNING: Only use it if you have no refUvs.
82
+ */
83
+ function calculateSideMapFromNormals(normals) {
84
+ const vertexCount = normals.length / 3;
85
+ const sideMap = new Uint8Array(vertexCount);
86
+ for (let i = 0; i < vertexCount; i++) {
87
+ const xyzOffset = i * 3;
88
+ const normalX = normals[xyzOffset];
89
+ const normalY = normals[xyzOffset + 1];
90
+ const normalZ = normals[xyzOffset + 2];
91
+ if (Math.abs(normalY) < Math.abs(normalX) && Math.abs(normalZ) < Math.abs(normalX)) {
92
+ sideMap[i] = toSide(0, normalX < 0);
93
+ continue;
94
+ }
95
+ if (Math.abs(normalZ) < Math.abs(normalY)) {
96
+ sideMap[i] = toSide(1, normalY < 0);
97
+ continue;
98
+ }
99
+ sideMap[i] = toSide(2, normalZ < 0);
100
+ }
101
+ return sideMap;
102
+ }
103
+ export function createUVBoxCoordinates(env, positions, bounds, normals) {
104
+ if (normals.length !== positions.length) {
105
+ throw new Error("Normals are wrong count");
106
+ }
107
+ return createUV(env, positions, bounds, undefined, calculateSideMapFromNormals(normals));
108
+ }
109
+ export function createUVBoxCoordinatesForStretched(env, positions, bounds, normals, refPositions, refBounds, refUvs) {
110
+ const transforms = env === null || env === void 0 ? void 0 : env.transforms;
111
+ const xyzCount = positions.length;
112
+ const vertexCount = xyzCount / 3;
113
+ const uvCount = vertexCount * 2;
114
+ if (refPositions.length !== xyzCount) {
115
+ throw new Error(`Position count differs: ${refPositions.length} vs ${xyzCount}.`);
116
+ }
117
+ if (normals.length !== xyzCount) {
118
+ throw new Error(`Normal count differs: ${normals.length} vs ${xyzCount}.`);
119
+ }
120
+ if (refUvs.length !== uvCount) {
121
+ throw new Error(`UV count differs: ${uvCount} vs ${refUvs.length}.`);
122
+ }
123
+ return createUV(env, positions, bounds, refBounds, calculateSideMapFromRefUvs(transforms, normals, refPositions, refBounds, refUvs));
124
+ }
125
+ function createUV(env, positions, bounds, refBounds, sideMap) {
126
+ const transforms = env === null || env === void 0 ? void 0 : env.transforms;
127
+ const xyzCount = positions.length;
128
+ const vertexCount = xyzCount / 3;
129
+ const uvCount = vertexCount * 2;
130
+ const { refMin, refSize, textureFixMin, textureFixMax } = UVMapper.calculateLimits(bounds, refBounds);
131
+ // This is what this entire method aims at populating
132
+ const newUvs = new Float32Array(uvCount);
133
+ for (let i = 0; i < vertexCount; i++) {
134
+ const xyzOffset = i * 3;
135
+ const uvOffset = i * 2;
136
+ // We normalize using the ref-sizes as we want the texture to tile. Normalizing to the
137
+ // stretched positions would make it just stretch (and defeat the entire purpose)
138
+ const normalized = XYZ.map((axis) => (positions[xyzOffset + axis] - refMin[axis]) / refSize[axis]);
139
+ const [axis, isNegAxis] = toAxisAndIsNeg(sideMap[i]);
140
+ let [u, v] = uvFromXyz(axis, isNegAxis, normalized);
141
+ // CET uses different texture origins for different sides of the cube, which makes it look
142
+ // like the texture "moves with" the stretch direction on some sides and stays in place on
143
+ // some sides.
144
+ //
145
+ // The code below emulates the CET behavior even though it can be argued that it is neither
146
+ // expected nor "correct".
147
+ if (axis === 0) {
148
+ if (isNegAxis) {
149
+ u -= textureFixMax[1];
150
+ }
151
+ else {
152
+ u += textureFixMin[1];
153
+ }
154
+ v += textureFixMin[2];
155
+ }
156
+ else if (axis === 1) {
157
+ if (isNegAxis) {
158
+ u += textureFixMin[0];
159
+ }
160
+ else {
161
+ u -= textureFixMax[0];
162
+ }
163
+ v += textureFixMin[2];
164
+ }
165
+ else {
166
+ u += textureFixMin[0];
167
+ if (isNegAxis) {
168
+ v -= textureFixMax[1];
169
+ }
170
+ else {
171
+ v += textureFixMin[1];
172
+ }
173
+ }
174
+ if (transforms !== undefined) {
175
+ [u, v] = UVMapper.applyUvTransform([u, v], transforms[axis]);
176
+ }
177
+ newUvs[uvOffset] = u;
178
+ newUvs[uvOffset + 1] = v;
179
+ }
180
+ return newUvs;
181
+ }
@@ -0,0 +1,10 @@
1
+ import { UVMapEnv } from "./UVMapEnv.js";
2
+ import { MinMaxSize } from "./UVMapper.js";
3
+ /**
4
+ * This mapper gives bad results in the "seam" where the wrapped texture meet itself. If you have
5
+ * access to prebaked UVs then use those, and if you do stretch use the for stretched method with
6
+ * the prebaked UVS as a start point
7
+ */
8
+ export declare function createUVCylinderCoordinates(env: UVMapEnv | undefined, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array): Float32Array;
9
+ export declare function createUVCylinderCoordinatesForStretched(env: UVMapEnv | undefined, positions: Float32Array, bounds: MinMaxSize, normals: Float32Array, refPositions: Float32Array, refBounds: MinMaxSize, refUvs: Float32Array): Float32Array;
10
+ //# sourceMappingURL=UVMapperCylinder.d.ts.map