@threepipe/plugin-blend-importer 0.0.5 → 0.0.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.
@@ -1,3 +1,4 @@
1
1
  import { Object3D } from 'threepipe';
2
- export declare function createCamera(object: any, ctx: any): Object3D | undefined;
2
+ import { Ctx } from './ctx';
3
+ export declare function createCamera(object: any, ctx: Ctx): Object3D | undefined;
3
4
  //# sourceMappingURL=camera.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../src/loader/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAElC,wBAAgB,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,QAAQ,GAAG,SAAS,CA2CxE"}
1
+ {"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../../src/loader/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAEzB,wBAAgB,YAAY,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,QAAQ,GAAG,SAAS,CAmDxE"}
@@ -0,0 +1,16 @@
1
+ import { AmbientLight, BufferAttribute, BufferGeometry, DirectionalLight, Mesh, MeshBasicMaterial, MeshPhysicalMaterial, Object3D, OrthographicCamera, PerspectiveCamera, PointLight, SpotLight } from 'threepipe';
2
+ export interface Ctx {
3
+ PointLight: typeof PointLight;
4
+ SpotLight: typeof SpotLight;
5
+ DirectionalLight: typeof DirectionalLight;
6
+ AmbientLight: typeof AmbientLight;
7
+ Object3D: typeof Object3D;
8
+ PerspectiveCamera: typeof PerspectiveCamera;
9
+ OrthographicCamera: typeof OrthographicCamera;
10
+ Mesh: typeof Mesh;
11
+ BufferGeometry: typeof BufferGeometry;
12
+ BufferAttribute: typeof BufferAttribute;
13
+ MeshPhysicalMaterial: typeof MeshPhysicalMaterial;
14
+ MeshBasicMaterial: typeof MeshBasicMaterial;
15
+ }
16
+ //# sourceMappingURL=ctx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ctx.d.ts","sourceRoot":"","sources":["../../src/loader/ctx.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EACZ,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,IAAI,EACJ,iBAAiB,EACjB,oBAAoB,EACpB,QAAQ,EACR,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,SAAS,EACZ,MAAM,WAAW,CAAA;AAElB,MAAM,WAAW,GAAG;IAChB,UAAU,EAAE,OAAO,UAAU,CAAA;IAC7B,SAAS,EAAE,OAAO,SAAS,CAAA;IAC3B,gBAAgB,EAAE,OAAO,gBAAgB,CAAA;IACzC,YAAY,EAAE,OAAO,YAAY,CAAA;IACjC,QAAQ,EAAE,OAAO,QAAQ,CAAA;IACzB,iBAAiB,EAAE,OAAO,iBAAiB,CAAA;IAC3C,kBAAkB,EAAE,OAAO,kBAAkB,CAAA;IAC7C,IAAI,EAAE,OAAO,IAAI,CAAA;IACjB,cAAc,EAAE,OAAO,cAAc,CAAA;IACrC,eAAe,EAAE,OAAO,eAAe,CAAA;IACvC,oBAAoB,EAAE,OAAO,oBAAoB,CAAA;IACjD,iBAAiB,EAAE,OAAO,iBAAiB,CAAA;CAC9C"}
@@ -1,3 +1,4 @@
1
- export declare function createBufferGeometry(meshData: any, ctx: any): any;
2
- export declare function createBufferGeometryOld(mesh: any, ctx: any): any;
1
+ import { Ctx } from './ctx';
2
+ export declare function createBufferGeometry(meshData: any, ctx: Ctx): import('three').BufferGeometry<import('three').NormalBufferAttributes, import('three').BufferGeometryEventMap>;
3
+ export declare function createBufferGeometryOld(mesh: any, ctx: Ctx): import('three').BufferGeometry<import('three').NormalBufferAttributes, import('three').BufferGeometryEventMap>;
3
4
  //# sourceMappingURL=geometry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/loader/geometry.ts"],"names":[],"mappings":"AAaA,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAgM3D;AASD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OA0E1D"}
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/loader/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAezB,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,kHAoM3D;AASD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,kHA6E1D"}
@@ -1,3 +1,4 @@
1
1
  import { Object3D } from 'threepipe';
2
- export declare function createObjects(file: any, ctx: any): Promise<Object3D<import('threepipe').Object3DEventMap>[]>;
2
+ import { Ctx } from './ctx';
3
+ export declare function createObjects(file: any, ctx: Ctx): Promise<Object3D<import('threepipe').Object3DEventMap>[]>;
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAUlC,wBAAsB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,6DAgEtD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/loader/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAY,QAAQ,EAAC,MAAM,WAAW,CAAA;AAC7C,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAYzB,wBAAsB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,6DAgEtD"}
@@ -1,3 +1,4 @@
1
1
  import { Light } from 'threepipe';
2
- export declare function createLight(lamp: any, ctx: any): Light<import('three').LightShadow<import('threepipe').Camera<import('threepipe').Object3DEventMap>> | undefined, import('threepipe').Object3DEventMap> | undefined;
2
+ import { Ctx } from './ctx';
3
+ export declare function createLight(lamp: any, ctx: Ctx): Light<import('three').LightShadow<import('threepipe').Camera<import('threepipe').Object3DEventMap>> | undefined, import('threepipe').Object3DEventMap> | undefined;
3
4
  //# sourceMappingURL=light.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"light.d.ts","sourceRoot":"","sources":["../../src/loader/light.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAU/B,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,sKAmC9C"}
1
+ {"version":3,"file":"light.d.ts","sourceRoot":"","sources":["../../src/loader/light.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,EAAC,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAUzB,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,sKAmC9C"}
@@ -1,2 +1,3 @@
1
- export declare function createMaterial(mat: any, ctx: any): any;
1
+ import { Ctx } from './ctx';
2
+ export declare function createMaterial(mat: any, ctx: Ctx): import('three').MeshPhysicalMaterial<import('three').MaterialEventMap>;
2
3
  //# sourceMappingURL=material.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/loader/material.ts"],"names":[],"mappings":"AAEA,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAShD"}
1
+ {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/loader/material.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAEzB,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,0EAShD"}
@@ -1,4 +1,3 @@
1
- import { Object3D } from 'threepipe';
2
- export declare function setCreateTransform(object: any, obj: Object3D): void;
3
- export declare function createMesh(object: any, loaded: WeakMap<any, any>, ctx: any): any;
1
+ import { Ctx } from './ctx';
2
+ export declare function createMesh(object: any, loaded: WeakMap<any, any>, ctx: Ctx): import('three').Mesh<any, any, import('three').Object3DEventMap> | undefined;
4
3
  //# sourceMappingURL=mesh.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../../src/loader/mesh.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAIlC,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,QAU5D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,OAsB1E"}
1
+ {"version":3,"file":"mesh.d.ts","sourceRoot":"","sources":["../../src/loader/mesh.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,GAAG,EAAC,MAAM,OAAO,CAAA;AAEzB,wBAAgB,UAAU,CAAC,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,gFAsB1E"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@threepipe/plugin-blend-importer",
3
3
  "description": "Basic importer for .blend file",
4
- "version": "0.0.5",
4
+ "version": "0.0.7",
5
5
  "dependencies": {},
6
6
  "exports": {
7
7
  ".": {
@@ -1,4 +1,5 @@
1
1
  import {
2
+ AmbientLight2,
2
3
  AnyOptions,
3
4
  BaseImporterPlugin,
4
5
  BufferAttribute,
@@ -6,7 +7,7 @@ import {
6
7
  DirectionalLight2,
7
8
  FileLoader,
8
9
  ILoader,
9
- Importer,
10
+ Importer, Mesh,
10
11
  Mesh2,
11
12
  Object3D,
12
13
  Object3D2,
@@ -14,7 +15,7 @@ import {
14
15
  PerspectiveCamera0,
15
16
  PhysicalMaterial,
16
17
  PointLight2,
17
- Scene,
18
+ Scene, SpotLight2,
18
19
  UnlitMaterial,
19
20
  } from 'threepipe'
20
21
  import {parseBlend} from './js-blend/main.js'
@@ -36,19 +37,23 @@ export class BlendLoadPlugin extends BaseImporterPlugin {
36
37
  // console.log(bakeGetters(blend))
37
38
  const ctx = {
38
39
  Object3D: Object3D2,
39
- Mesh: Mesh2,
40
+ Mesh: Mesh2 as typeof Mesh,
40
41
  MeshPhysicalMaterial: PhysicalMaterial,
41
42
  MeshBasicMaterial: UnlitMaterial,
42
43
  PerspectiveCamera: PerspectiveCamera0,
43
44
  OrthographicCamera: OrthographicCamera0,
44
45
  PointLight: PointLight2,
45
46
  DirectionalLight: DirectionalLight2,
47
+ SpotLight: SpotLight2,
48
+ AmbientLight: AmbientLight2,
46
49
  BufferGeometry: BufferGeometry2,
47
50
  BufferAttribute: BufferAttribute,
48
51
  }
49
52
  const objects = await createObjects(blend, ctx)
50
53
  const root = new Object3D()
51
54
  root.add(...objects)
55
+ // root.userData.autoScaled = true
56
+ // root.userData.autoCentered = true
52
57
  // console.log(res, blend, root)
53
58
  blend.scene = root
54
59
  return blend
@@ -583,6 +583,15 @@ function worker_code () {
583
583
  function toString (buffer, _in, _out) {
584
584
  return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
585
585
  }
586
+ function seekCheck (buffer, _in, str) {
587
+ const length = str.length;
588
+ for (let i = 0; i < length; i++) {
589
+ if (buffer.getUint8(_in + i) !== str.charCodeAt(i)) {
590
+ return false;
591
+ }
592
+ }
593
+ return true;
594
+ }
586
595
 
587
596
  // Begin parsing blender __blender_file__
588
597
 
@@ -674,19 +683,16 @@ function worker_code () {
674
683
  curr_count++;
675
684
  }
676
685
 
677
- // todo fix seek logic
678
- // Adjust for 4byte alignment TYPE
679
- if (toString(_data, offset2, offset2 + 4) !== 'TYPE'
680
- ) {
681
- for (let j = 0; j < 8; j++) {
682
- if(toString(_data, offset2, offset2 + 4) === 'TYPE') break
683
- offset2++;
684
- }
685
- // offset2 = (4 - (offset2 % 4)) + offset2;
686
+ // Adjust for alignment TYPE
687
+ for (let j = 0; j < 8; j++) {
688
+ if(seekCheck(data, offset2, 'TYPE')) break
689
+ offset2++;
686
690
  }
687
- if(toString(_data, offset2, offset2 + 4) !== 'TYPE') {
688
- debugger
691
+ if(!seekCheck(data, offset2, 'TYPE')) {
692
+ ERROR = 'Unexpected alignment error in SDNA parsing';
693
+ break
689
694
  }
695
+
690
696
  offset2 += 4;
691
697
 
692
698
  // Number of struct types
@@ -706,18 +712,14 @@ function worker_code () {
706
712
  curr_count++;
707
713
  }
708
714
 
709
- // todo fix seek logic
710
- // Adjust for 4byte alignment
711
- if (toString(_data, offset2, offset2 + 4) !== 'TLEN'
712
- ) {
713
- for (let j = 0; j < 8; j++) {
714
- if(toString(_data, offset2, offset2 + 4) === 'TLEN') break
715
- offset2++;
716
- }
717
- // offset2 = (4 - (offset2 % 4)) + offset2;
715
+ // Adjust for alignment
716
+ for (let j = 0; j < 8; j++) {
717
+ if(seekCheck(data, offset2, 'TLEN')) break
718
+ offset2++;
718
719
  }
719
- if(toString(_data, offset2, offset2 + 4) !== 'TLEN') {
720
- debugger
720
+ if(!seekCheck(data, offset2, 'TLEN')) {
721
+ ERROR = 'Unexpected alignment error in SDNA parsing';
722
+ break
721
723
  }
722
724
  offset2 += 4;
723
725
  curr_count = 0;
@@ -729,18 +731,14 @@ function worker_code () {
729
731
  curr_count++;
730
732
  }
731
733
 
732
- // todo fix seek logic
733
- // Adjust for 4byte alignment STRC
734
- if (toString(_data, offset2, offset2 + 4) !== 'STRC'
735
- ) {
736
- for (let j = 0; j < 8; j++) {
737
- if(toString(_data, offset2, offset2 + 4) === 'STRC') break
738
- offset2++;
739
- }
740
- // offset2 = (4 - (offset2 % 4)) + offset2;
734
+ // Adjust for alignment
735
+ for (let j = 0; j < 8; j++) {
736
+ if(seekCheck(data, offset2, 'STRC')) break
737
+ offset2++;
741
738
  }
742
- if(toString(_data, offset2, offset2 + 4) !== 'STRC') {
743
- debugger
739
+ if(!seekCheck(data, offset2, 'STRC')) {
740
+ ERROR = 'Unexpected alignment error in SDNA parsing';
741
+ break
744
742
  }
745
743
  offset2 += 4;
746
744
 
@@ -1,6 +1,7 @@
1
1
  import {Object3D} from 'threepipe'
2
+ import {Ctx} from './ctx'
2
3
 
3
- export function createCamera(object: any, ctx: any): Object3D | undefined {
4
+ export function createCamera(object: any, ctx: Ctx): Object3D | undefined {
4
5
  const cdata = object.data
5
6
  // console.log(bakeGetters(object))
6
7
  if (!cdata) return undefined
@@ -10,14 +11,19 @@ export function createCamera(object: any, ctx: any): Object3D | undefined {
10
11
  let camera: Object3D
11
12
  if (type === 0) {
12
13
  // Perspective
14
+ // Convert lens (mm) to field of view (fov) in degrees (vfov)
15
+ const sensorWidth = cdata.sensor_x || 36
16
+ const sensorHeight = cdata.sensor_y || 24
17
+ const lens = cdata.lens || 50
18
+ const fov = 2 * Math.atan(sensorHeight / (2 * lens)) * (180 / Math.PI)
19
+
13
20
  camera = new ctx.PerspectiveCamera(
14
- cdata.lens || 50, // fov or lens
15
- (cdata.sensor_x || 36) / (cdata.sensor_y || 24), // aspect
16
- cdata.clipsta || 0.1, // near
17
- cdata.clipend || 1000 // far
21
+ fov,
22
+ sensorWidth / sensorHeight,
23
+ cdata.clipsta || 0.1,
24
+ cdata.clipend || 1000
18
25
  )
19
- // Set additional properties if needed
20
- camera.position.set(0, 0, 0)
26
+ if ('shiftx' in cdata) camera.userData.shiftX = cdata.shiftx // todo?
21
27
  if ('shiftx' in cdata) camera.userData.shiftX = cdata.shiftx // todo?
22
28
  if ('shifty' in cdata) camera.userData.shiftY = cdata.shifty
23
29
  } else if (type === 1) {
@@ -33,7 +39,6 @@ export function createCamera(object: any, ctx: any): Object3D | undefined {
33
39
  cdata.clipsta || 0.1,
34
40
  cdata.clipend || 1000
35
41
  )
36
- camera.position.set(0, 0, 0)
37
42
  if ('shiftx' in cdata) camera.userData.shiftX = cdata.shiftx
38
43
  if ('shifty' in cdata) camera.userData.shiftY = cdata.shifty
39
44
  } else {
@@ -42,5 +47,9 @@ export function createCamera(object: any, ctx: any): Object3D | undefined {
42
47
  console.warn('Unsupported camera type', type)
43
48
  }
44
49
 
50
+ // const obj = new Object3D()
51
+ // camera.rotation.x = -Math.PI / 2
52
+ // obj.add(camera)
53
+
45
54
  return camera
46
55
  }
@@ -0,0 +1,29 @@
1
+ import {
2
+ AmbientLight,
3
+ BufferAttribute,
4
+ BufferGeometry,
5
+ DirectionalLight,
6
+ Mesh,
7
+ MeshBasicMaterial,
8
+ MeshPhysicalMaterial,
9
+ Object3D,
10
+ OrthographicCamera,
11
+ PerspectiveCamera,
12
+ PointLight,
13
+ SpotLight,
14
+ } from 'threepipe'
15
+
16
+ export interface Ctx {
17
+ PointLight: typeof PointLight
18
+ SpotLight: typeof SpotLight
19
+ DirectionalLight: typeof DirectionalLight
20
+ AmbientLight: typeof AmbientLight
21
+ Object3D: typeof Object3D
22
+ PerspectiveCamera: typeof PerspectiveCamera
23
+ OrthographicCamera: typeof OrthographicCamera
24
+ Mesh: typeof Mesh
25
+ BufferGeometry: typeof BufferGeometry
26
+ BufferAttribute: typeof BufferAttribute
27
+ MeshPhysicalMaterial: typeof MeshPhysicalMaterial
28
+ MeshBasicMaterial: typeof MeshBasicMaterial
29
+ }
@@ -1,3 +1,5 @@
1
+ import {Ctx} from './ctx'
2
+
1
3
  function getLayer(layers: any, i: number) {
2
4
  if (!Array.isArray(layers)) return layers
3
5
  return layers[i]
@@ -11,7 +13,7 @@ function getLayer(layers: any, i: number) {
11
13
  // https://projects.blender.org/blender/blender/pulls/106638
12
14
 
13
15
  // https://github.com/blender/blender/blob/55e2fd2929b7577e0785c128c8f8069efd990c07/source/blender/blenkernel/intern/mesh.cc#L413
14
- export function createBufferGeometry(meshData: any, ctx: any) {
16
+ export function createBufferGeometry(meshData: any, ctx: Ctx) {
15
17
 
16
18
  if (meshData.mpoly) return createBufferGeometryOld(meshData, ctx)
17
19
  const geometry = new ctx.BufferGeometry()
@@ -22,7 +24,9 @@ export function createBufferGeometry(meshData: any, ctx: any) {
22
24
  // https://github.com/blender/blender/blob/05dcc0377b62d8e026e1901dfbecbd4b06fda0b5/scripts/addons_core/io_scene_gltf2/blender/exp/primitive_extract.py#L19
23
25
 
24
26
  let vertices
27
+ let verticesData
25
28
  let indices
29
+ let indicesData
26
30
 
27
31
  // Extract vertex positions from vdata layers
28
32
  if (meshData.vdata && meshData.vdata.layers && meshData.vdata.totlayer > 0) {
@@ -38,6 +42,7 @@ export function createBufferGeometry(meshData: any, ctx: any) {
38
42
  continue
39
43
  }
40
44
  vertices = layer
45
+ verticesData = data
41
46
  } else {
42
47
  // console.log('unknown vdata', layer)
43
48
  }
@@ -59,6 +64,7 @@ export function createBufferGeometry(meshData: any, ctx: any) {
59
64
  continue
60
65
  }
61
66
  indices = layer
67
+ indicesData = data
62
68
  } else {
63
69
  // console.log('unknown ldata', layer)
64
70
  }
@@ -104,30 +110,30 @@ export function createBufferGeometry(meshData: any, ctx: any) {
104
110
  // return geometry
105
111
  // }
106
112
 
107
- if (vertices?.data && vertices.data.length > 0) {
108
- const positions = new Float32Array(vertices.data.length * 3)
109
- for (let j = 0; j < vertices.data.length; j++) {
110
- const vertex = vertices.data[j]
111
- if (vertex.x !== undefined) {
112
- positions[j * 3] = vertex.x
113
- positions[j * 3 + 1] = vertex.z
114
- positions[j * 3 + 2] = -vertex.y
115
- } else if (vertex.co !== undefined) {
116
- positions[j * 3] = vertex.co[0]
117
- positions[j * 3 + 1] = vertex.co[2]
118
- positions[j * 3 + 2] = -vertex.co[1]
113
+ if (verticesData && verticesData.length > 0) {
114
+ const positions = new Float32Array(verticesData.length * 3)
115
+ for (let j = 0; j < verticesData.length; j++) {
116
+ const {x, y, z, co} = verticesData[j] || {}
117
+ if (x !== undefined) {
118
+ positions[j * 3] = x
119
+ positions[j * 3 + 1] = z
120
+ positions[j * 3 + 2] = -y
121
+ } else if (co !== undefined) {
122
+ positions[j * 3] = co[0]
123
+ positions[j * 3 + 1] = co[2]
124
+ positions[j * 3 + 2] = -co[1]
119
125
  } else {
120
126
  // console.log(bakeGetters(meshData))
121
127
  // const t = [...new Int32Array(vertex.__blender_file__.AB, vertex.__data_address__, 8)]
122
128
  // debugger
123
- console.error('BlendLoader - unknown vertex', vertex)
129
+ console.error('BlendLoader - unknown vertex', verticesData[j])
124
130
  break
125
131
  }
126
132
  }
127
133
  geometry.setAttribute('position', new ctx.BufferAttribute(positions, 3))
128
134
  }
129
135
 
130
- if (indices?.data && indices.data.length > 0 && vertices?.data?.length) {
136
+ if (indicesData && indicesData.length > 0 && verticesData?.length) {
131
137
  const faceSize = meshData.totloop / meshData.totpoly
132
138
  if (faceIndices.length > 0) {
133
139
  // Use face offset indices for variable-sized faces
@@ -147,11 +153,11 @@ export function createBufferGeometry(meshData: any, ctx: any) {
147
153
 
148
154
  if (faceVertCount >= 3) {
149
155
  // todo better Triangulate the face using fan triangulation
150
- const firstVert = indices.data[faceStart].i
156
+ const firstVert = indicesData[faceStart].i
151
157
  for (let k = 1; k < faceVertCount - 1; k++) {
152
158
  indexes[t++] = firstVert
153
- indexes[t++] = indices.data[faceStart + k].i
154
- indexes[t++] = indices.data[faceStart + k + 1].i
159
+ indexes[t++] = indicesData[faceStart + k].i
160
+ indexes[t++] = indicesData[faceStart + k + 1].i
155
161
  }
156
162
  } else {
157
163
  // debugger
@@ -212,7 +218,7 @@ export function createBufferGeometry(meshData: any, ctx: any) {
212
218
  // // meshData.eData = domain edge - https://github.com/blender/blender/blob/05dcc0377b62d8e026e1901dfbecbd4b06fda0b5/scripts/addons_core/io_scene_gltf2/blender/exp/primitive_extract.py#L189
213
219
  // // todo normals, tangents
214
220
 
215
- export function createBufferGeometryOld(mesh: any, ctx: any) {
221
+ export function createBufferGeometryOld(mesh: any, ctx: Ctx) {
216
222
  const
217
223
  faces = Array.isArray(mesh.mpoly) ? mesh.mpoly as any[] : [mesh.mpoly],
218
224
  loops = mesh.mloop,
@@ -249,24 +255,27 @@ export function createBufferGeometryOld(mesh: any, ctx: any) {
249
255
  index += indexi - 1 + l
250
256
 
251
257
  const loop = loops[index]
252
- const vert = vertices[loop.v]
258
+ const {co, no} = vertices[loop.v] || {}
253
259
  indices[currentIndex] = currentIndex
254
260
 
255
- positions[currentIndex * 3 + 0] = vert.co[0]
256
- positions[currentIndex * 3 + 1] = vert.co[2]
257
- positions[currentIndex * 3 + 2] = -vert.co[1]
261
+ if (co) {
262
+ positions[currentIndex * 3 + 0] = co[0]
263
+ positions[currentIndex * 3 + 1] = co[2]
264
+ positions[currentIndex * 3 + 2] = -co[1]
265
+ }
258
266
 
259
- if (vert.no) {
260
- normals[currentIndex * 3 + 0] = vert.no[0]
261
- normals[currentIndex * 3 + 1] = vert.no[2]
262
- normals[currentIndex * 3 + 2] = -vert.no[1]
267
+ if (no) {
268
+ normals[currentIndex * 3 + 0] = no[0]
269
+ normals[currentIndex * 3 + 1] = no[2]
270
+ normals[currentIndex * 3 + 2] = -no[1]
263
271
  } else {
264
272
  computeNormals = true
265
273
  }
266
274
 
267
275
  if (uv) {
268
- uvs[currentIndex * 2 + 0] = uv[index].uv[0]
269
- uvs[currentIndex * 2 + 1] = uv[index].uv[1]
276
+ const uv1 = uv[index].uv
277
+ uvs[currentIndex * 2 + 0] = uv1[0]
278
+ uvs[currentIndex * 2 + 1] = uv1[1]
270
279
  }
271
280
 
272
281
  currentIndex++
@@ -1,7 +1,10 @@
1
1
  import {createCamera} from './camera'
2
2
  import {createLight} from './light'
3
- import {createMesh, setCreateTransform} from './mesh'
4
- import {Object3D} from 'threepipe'
3
+ import {createMesh} from './mesh'
4
+ import {IObject3D, Object3D} from 'threepipe'
5
+ import {Ctx} from './ctx'
6
+ import {Euler, EulerOrder} from 'three/src/math/Euler'
7
+ import {Quaternion, Vector3} from 'three'
5
8
 
6
9
  // https://github.com/blender/blender/blob/99a4c93081cc2310a09a14f20a1493e8974c10d2/source/blender/makesdna/DNA_object_types.h#L445
7
10
  const blenderObjectTypes = {
@@ -11,7 +14,7 @@ const blenderObjectTypes = {
11
14
  camera: 11,
12
15
  }
13
16
 
14
- export async function createObjects(file: any, ctx: any) {
17
+ export async function createObjects(file: any, ctx: Ctx) {
15
18
  const objects: (Object3D|null)[] = []
16
19
  const childMap = new Map<any, Object3D[]>()
17
20
  const objMap = new Map<any, Object3D>()
@@ -42,7 +45,7 @@ export async function createObjects(file: any, ctx: any) {
42
45
  console.warn('Unsupported object type', object.type, object, obj)
43
46
  }
44
47
  if (obj) {
45
- setCreateTransform(object, obj)
48
+ setTransform(object, obj as any)
46
49
  const exChildren = childMap.get(object)
47
50
  if (exChildren) {
48
51
  for (const exChild of exChildren) {
@@ -52,7 +55,7 @@ export async function createObjects(file: any, ctx: any) {
52
55
  }
53
56
  objMap.set(object, obj)
54
57
  if (object.parent === object) {
55
- console.error('invalid, parent same as object, adding to root', object)
58
+ console.error('BlendLoader - invalid, parent same as object, adding to root', object)
56
59
  objects.push(obj)
57
60
  } else if (!object.parent) { // just in case
58
61
  objects.push(obj)
@@ -71,8 +74,42 @@ export async function createObjects(file: any, ctx: any) {
71
74
  }
72
75
  if (childMap.size) {
73
76
  const vals = [...childMap.values()].flat()
74
- console.warn('unknown objects with parents, adding to root', vals, childMap)
77
+ console.warn('BlendLoader - unknown objects with parents, adding to root', vals, childMap)
75
78
  objects.push(...vals)
76
79
  }
77
80
  return objects.filter(o => !!o) as Object3D[]
78
81
  }
82
+
83
+
84
+ // https://github.com/blender/blender/blob/458e224587e8c45da20841a283cc1b41adc98950/source/blender/makesdna/DNA_action_types.h#L526
85
+ const eulerModes: Record<number, EulerOrder> = {
86
+ [1]: 'XYZ',
87
+ [2]: 'XZY',
88
+ [3]: 'YXZ',
89
+ [4]: 'YZX',
90
+ [5]: 'ZXY',
91
+ [6]: 'ZYX',
92
+ }
93
+
94
+ function setTransform(object: any, obj: IObject3D) {
95
+ obj.name = object.aname
96
+ obj.scale.set(object.size[0], object.size[2], object.size[1])
97
+ obj.position.set(object.loc[0], object.loc[2], -object.loc[1])
98
+
99
+ if (!object.rotmode || object.rotmode === 0) {
100
+ // const quat = new Quaternion()
101
+ obj.quaternion.set(object.quat[1], object.quat[3], -object.quat[2], object.quat[0]) // wxyz
102
+ } else {
103
+ // console.log(object.rotmode)
104
+ // const order = eulerModes[4]
105
+ const order = eulerModes[object.rotmode] ?? 'XYZ'
106
+ const quat = new Quaternion().setFromEuler(new Euler(object.rot[0], object.rot[1], object.rot[2], order.split('').reverse().join('') as any))
107
+ obj.quaternion.set(quat.x, quat.z, -quat.y, quat.w) // wxyz
108
+ }
109
+ // because camera is rotated 90d in blender
110
+ if (object.type === blenderObjectTypes.camera)
111
+ obj.quaternion.multiply(new Quaternion().setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2))
112
+
113
+ obj.updateMatrix()
114
+ if (obj.setDirty) obj.setDirty()
115
+ }
@@ -1,4 +1,5 @@
1
1
  import {Light} from 'threepipe'
2
+ import {Ctx} from './ctx'
2
3
 
3
4
  const blenderLightTypes = {
4
5
  point: 0,
@@ -8,7 +9,7 @@ const blenderLightTypes = {
8
9
  area: 0,
9
10
  }
10
11
 
11
- export function createLight(lamp: any, ctx: any) {
12
+ export function createLight(lamp: any, ctx: Ctx) {
12
13
  const ldata = lamp.data
13
14
 
14
15
  const position = [lamp.loc[0], lamp.loc[2], -lamp.loc[1]]
@@ -1,6 +1,8 @@
1
1
  // todo see blender gltf exporter and convert to js. structure is the same
2
2
  // https://github.com/KhronosGroup/glTF-Blender-IO/blob/ed5100ab6c40472b7c3254fddfe0dd0d76d60644/addons/io_scene_gltf2/blender/exp/material/materials.py#L60
3
- export function createMaterial(mat: any, ctx: any) {
3
+ import {Ctx} from './ctx'
4
+
5
+ export function createMaterial(mat: any, ctx: Ctx) {
4
6
  const material = new ctx.MeshPhysicalMaterial()
5
7
  material.color.setRGB(mat.r, mat.g, mat.b)
6
8
  material.roughness = mat.roughness !== undefined ? mat.roughness : 0.4
@@ -1,20 +1,8 @@
1
- import {Object3D} from 'threepipe'
2
1
  import {createBufferGeometry} from './geometry'
3
2
  import {createMaterial} from './material'
3
+ import {Ctx} from './ctx'
4
4
 
5
- export function setCreateTransform(object: any, obj: Object3D) {
6
- // obj.rotateZ(object.rot[2])
7
- // obj.rotateY(object.rot[1])
8
- // obj.rotateX(object.rot[0])
9
-
10
- obj.name = object.aname
11
- obj.quaternion.set(object.quat[1], object.quat[3], -object.quat[2], object.quat[0]) // wxyz
12
- obj.scale.set(object.size[0], object.size[1], object.size[2])
13
- obj.position.set(object.loc[0], object.loc[2], -object.loc[1])
14
- obj.updateMatrix()
15
- }
16
-
17
- export function createMesh(object: any, loaded: WeakMap<any, any>, ctx: any) {
5
+ export function createMesh(object: any, loaded: WeakMap<any, any>, ctx: Ctx) {
18
6
  if (!object.data) {
19
7
  return undefined
20
8
  }