@planara/core 1.3.1 → 1.4.1

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,4 +1,6 @@
1
1
  import { Renderer } from './renderer';
2
+ import { Mesh } from 'ogl';
3
+ import { Figure } from '@planara/types';
2
4
  /**
3
5
  * Рендерер для редактора.
4
6
  * Добавляет сетку, оси координат и поддержку Orbit для управления камерой.
@@ -7,6 +9,10 @@ import { Renderer } from './renderer';
7
9
  export declare class EditorRenderer extends Renderer {
8
10
  /** Orbit-контроллер для управления камерой */
9
11
  private orbit;
12
+ /** Raycast для подсветки моделей при наведении */
13
+ private raycast;
14
+ /** Курсор мыши для остлеживания наведения на 3D-модель */
15
+ private readonly mouse;
10
16
  /**
11
17
  * Инициализация сцены редактора.
12
18
  * Создает сетку, оси координат и orbit-контроллер.
@@ -17,5 +23,23 @@ export declare class EditorRenderer extends Renderer {
17
23
  * Обновление состояния рендерера.
18
24
  */
19
25
  protected update(): void;
26
+ /**
27
+ * Метод для добавления фигуры.
28
+ * Настройка raycast.
29
+ * @param figure Данные фигуры: position, normal, uv
30
+ */
31
+ addFigure(figure: Figure): Mesh<import('ogl').Geometry, import('ogl').Program>;
32
+ /**
33
+ * Обновление uniform uHit для конкретной 3D-модели
34
+ */
35
+ protected updateHitUniform(mesh: Mesh): void;
36
+ /**
37
+ * Инициализация обработчиков мыши для raycast
38
+ */
39
+ private initMouseListeners;
40
+ /**
41
+ * Обработчик движения мыши
42
+ */
43
+ private handleMouseMove;
20
44
  }
21
45
  //# sourceMappingURL=editor-renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor-renderer.d.ts","sourceRoot":"","sources":["../../src/core/editor-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,8CAA8C;IAC9C,OAAO,CAAC,KAAK,CAAS;IAEtB;;;;OAIG;gBACgB,MAAM,EAAE,iBAAiB;IAgB5C;;OAEG;IACH,SAAS,CAAC,MAAM;CAIjB"}
1
+ {"version":3,"file":"editor-renderer.d.ts","sourceRoot":"","sources":["../../src/core/editor-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAgD,KAAK,IAAI,EAAE,MAAM,KAAK,CAAC;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,8CAA8C;IAC9C,OAAO,CAAC,KAAK,CAAS;IAEtB,kDAAkD;IAClD,OAAO,CAAC,OAAO,CAAW;IAE1B,0DAA0D;IAC1D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAE9B;;;;OAIG;gBACgB,MAAM,EAAE,iBAAiB;IAyB5C;;OAEG;IACH,SAAS,CAAC,MAAM;IAKhB;;;;OAIG;IACa,SAAS,CAAC,MAAM,EAAE,MAAM;IAsBxC;;OAEG;IACH,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI;IAIrC;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,eAAe,CAerB;CACH"}
@@ -13,7 +13,10 @@ export declare abstract class Renderer {
13
13
  protected camera: Camera;
14
14
  /** HTML-элемент canvas, на котором рендерится сцена */
15
15
  protected canvas: HTMLCanvasElement;
16
+ /** Program для настройки рендеринга моделей */
16
17
  protected program: Program;
18
+ /** Массив моделей на сцене */
19
+ protected meshes: Mesh[];
17
20
  /**
18
21
  * Конструктор рендерера
19
22
  * @param canvas - HTMLCanvasElement для рендеринга
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/core/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAE/F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;GAGG;AACH,8BAAsB,QAAQ;IAC5B,8BAA8B;IAC9B,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC;IAE1B,4BAA4B;IAC5B,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC;IAE3B,uBAAuB;IACvB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEpC,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,SAAS,aAAa,MAAM,EAAE,iBAAiB;IAyB/C;;OAEG;IACI,MAAM;IAMb;;OAEG;IACH,SAAS,CAAC,MAAM;IAIhB;;OAEG;IACH,SAAS,CAAC,MAAM,IAAI,IAAI;IAExB;;OAEG;IACI,IAAI;IAMX;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,MAAM;CAkBhC"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/core/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAE/F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;GAGG;AACH,8BAAsB,QAAQ;IAC5B,8BAA8B;IAC9B,SAAS,CAAC,EAAE,EAAE,WAAW,CAAC;IAE1B,4BAA4B;IAC5B,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC;IAE3B,uBAAuB;IACvB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC;IAEpC,+CAA+C;IAC/C,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC;IAE3B,8BAA8B;IAC9B,SAAS,CAAC,MAAM,EAAG,IAAI,EAAE,CAAC;IAE1B;;;OAGG;IACH,SAAS,aAAa,MAAM,EAAE,iBAAiB;IAyB/C;;OAEG;IACI,MAAM;IAMb;;OAEG;IACH,SAAS,CAAC,MAAM;IAIhB;;OAEG;IACH,SAAS,CAAC,MAAM,IAAI,IAAI;IAExB;;OAEG;IACI,IAAI;IAMX;;;OAGG;IACI,SAAS,CAAC,MAAM,EAAE,MAAM;CAqBhC"}
package/dist/index.cjs.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("ogl");function v(t){const e=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("ogl");function p(s){const e=`
2
2
  attribute vec3 position;
3
3
  attribute vec3 normal;
4
4
  attribute vec2 uv;
@@ -15,7 +15,7 @@
15
15
  vNormal = normalize(normalMatrix * normal);
16
16
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
17
17
  }
18
- `,s=`
18
+ `,t=`
19
19
  precision highp float;
20
20
 
21
21
  uniform sampler2D tMap;
@@ -29,5 +29,5 @@
29
29
  gl_FragColor.rgb = tex + shading;
30
30
  gl_FragColor.a = 1.0;
31
31
  }
32
- `,r=new i.Texture(t);return new i.Program(t,{vertex:e,fragment:s,uniforms:{tMap:{value:r}}})}class l{gl;scene;camera;canvas;program;constructor(e){this.canvas=e,this.gl=new i.Renderer({canvas:e}),this.gl.setSize(e.clientWidth,e.clientHeight),this.gl.gl.clearColor(1,1,1,1),this.scene=new i.Transform,this.camera=new i.Camera(this.gl.gl,{fov:45}),this.camera.position.set(1,1,7),this.camera.lookAt([0,0,0]),this.program=v(this.gl.gl)}resize(){this.gl.setSize(this.canvas.width,this.canvas.height),this.camera.perspective({aspect:this.canvas.width/this.canvas.height})}render(){this.gl.render({scene:this.scene,camera:this.camera})}update(){}loop(){this.update(),this.render(),requestAnimationFrame(this.loop.bind(this))}addFigure(e){const s=new i.Geometry(this.gl.gl,{position:{size:3,data:new Float32Array(e.position)},normal:{size:3,data:new Float32Array(e.normal??[])},uv:{size:2,data:new Float32Array(e.uv??[])}}),r=new i.Mesh(this.gl.gl,{geometry:s,program:this.program});return r.setParent(this.scene),r}}class d extends l{orbit;constructor(e){super(e);const s=new i.GridHelper(this.gl.gl,{size:10,divisions:10});s.position.y=-.001,s.setParent(this.scene),new i.AxesHelper(this.gl.gl,{size:6,symmetric:!0}).setParent(this.scene),this.orbit=new i.Orbit(this.camera,{element:this.canvas})}update(){this.orbit?.update()}}class g extends l{orbit;constructor(e){super(e),this.orbit=new i.Orbit(this.camera,{element:this.canvas,target:new i.Vec3(0,0,0),minPolarAngle:Math.PI/2,maxPolarAngle:Math.PI/2,enableRotate:!0,enableZoom:!1,enablePan:!1})}update(){this.orbit?.update()}}class b{type;position;normal;uv;material;constructor(e){this.type=e.type,this.position=e.position,this.normal=e.normal??[],this.uv=e.uv??[],this.material=e.material}}var u=(t=>(t[t.Cube=0]="Cube",t[t.Sphere=1]="Sphere",t[t.Plane=2]="Plane",t[t.Cylinder=3]="Cylinder",t[t.Custom=4]="Custom",t))(u||{});class f{positions=[];normals=[];uvs=[];tmpPositions=[];tmpNormals=[];tmpUVs=[];load(e){const s=e.split(`
33
- `);for(const o of s){if(!o.trim()||o.startsWith("#"))continue;const a=o.trim().split(/\s+/);switch(a[0]){case"v":this.tmpPositions.push(a.slice(1).map(Number));break;case"vn":this.tmpNormals.push(a.slice(1).map(Number));break;case"vt":this.tmpUVs.push(a.slice(1).map(Number));break;case"f":this.processFaceLine(a);break}}const r={type:u.Custom,position:this.positions,...this.normals.length>0&&{normal:this.normals},...this.uvs.length>0&&{uv:this.uvs}};return new b(r)}processFaceLine(e){for(let s=1;s<e.length;s++){const r=e[s];if(!r)continue;const[o,a,c]=r.split("/"),m=o?parseInt(o,10):void 0,h=a?parseInt(a,10):void 0,p=c?parseInt(c,10):void 0;if(m!==void 0){const n=this.tmpPositions[m-1];n&&this.positions.push(...n)}if(h!==void 0){const n=this.tmpUVs[h-1];n&&this.uvs.push(...n)}if(p!==void 0){const n=this.tmpNormals[p-1];n&&this.normals.push(...n)}}}}exports.EditorRenderer=d;exports.ObjLoader=f;exports.PreviewRenderer=g;exports.Renderer=l;exports.createProgram=v;
32
+ `,i=new r.Texture(s);return new r.Program(s,{vertex:e,fragment:t,uniforms:{tMap:{value:i}}})}class h{gl;scene;camera;canvas;program;meshes;constructor(e){this.canvas=e,this.gl=new r.Renderer({canvas:e}),this.gl.setSize(e.clientWidth,e.clientHeight),this.gl.gl.clearColor(1,1,1,1),this.scene=new r.Transform,this.camera=new r.Camera(this.gl.gl,{fov:45}),this.camera.position.set(1,1,7),this.camera.lookAt([0,0,0]),this.program=p(this.gl.gl)}resize(){this.gl.setSize(this.canvas.width,this.canvas.height),this.camera.perspective({aspect:this.canvas.width/this.canvas.height})}render(){this.gl.render({scene:this.scene,camera:this.camera})}update(){}loop(){this.update(),this.render(),requestAnimationFrame(this.loop.bind(this))}addFigure(e){const t=new r.Geometry(this.gl.gl,{position:{size:3,data:new Float32Array(e.position)},normal:{size:3,data:new Float32Array(e.normal??[])},uv:{size:2,data:new Float32Array(e.uv??[])}}),i=new r.Mesh(this.gl.gl,{geometry:t,program:this.program});return i.setParent(this.scene),this.meshes.push(i),i}}class v extends h{orbit;raycast;mouse;constructor(e){super(e);const t=new r.GridHelper(this.gl.gl,{size:10,divisions:10});t.position.y=-.001,t.setParent(this.scene),new r.AxesHelper(this.gl.gl,{size:6,symmetric:!0}).setParent(this.scene),this.orbit=new r.Orbit(this.camera,{element:this.canvas}),this.raycast=new r.Raycast,this.mouse=new r.Vec2,this.initMouseListeners()}update(){this.orbit?.update()}addFigure(e){const t=super.addFigure(e);if(t.geometry){const i=t.geometry.constructor.name;t.geometry.raycast=i.includes("Sphere")?"sphere":"box"}return t.isHit=!1,t.onBeforeRender(({mesh:i})=>{this.updateHitUniform(i)}),t}updateHitUniform(e){this.program.uniforms.uHit.value=e.isHit?1:0}initMouseListeners(){window.addEventListener("load",()=>{document.addEventListener("mousemove",this.handleMouseMove,!1)})}handleMouseMove=e=>{this.mouse.set(2*(e.x/this.gl.width)-1,2*(1-e.y/this.gl.height)-1),this.raycast.castMouse(this.camera,this.mouse),this.meshes.forEach(i=>i.isHit=!1),this.raycast.intersectBounds(this.meshes).forEach(i=>i.isHit=!0)}}class g extends h{orbit;constructor(e){super(e),this.orbit=new r.Orbit(this.camera,{element:this.canvas,target:new r.Vec3(0,0,0),minPolarAngle:Math.PI/2,maxPolarAngle:Math.PI/2,enableRotate:!0,enableZoom:!1,enablePan:!1})}update(){this.orbit?.update()}}class f{type;position;normal;uv;material;constructor(e){this.type=e.type,this.position=e.position,this.normal=e.normal??[],this.uv=e.uv??[],this.material=e.material}}var d=(s=>(s[s.Cube=0]="Cube",s[s.Sphere=1]="Sphere",s[s.Plane=2]="Plane",s[s.Cylinder=3]="Cylinder",s[s.Custom=4]="Custom",s))(d||{});class b{positions=[];normals=[];uvs=[];tmpPositions=[];tmpNormals=[];tmpUVs=[];load(e){const t=e.split(`
33
+ `);for(const n of t){if(!n.trim()||n.startsWith("#"))continue;const a=n.trim().split(/\s+/);switch(a[0]){case"v":this.tmpPositions.push(a.slice(1).map(Number));break;case"vn":this.tmpNormals.push(a.slice(1).map(Number));break;case"vt":this.tmpUVs.push(a.slice(1).map(Number));break;case"f":this.processFaceLine(a);break}}const i={type:d.Custom,position:this.positions,...this.normals.length>0&&{normal:this.normals},...this.uvs.length>0&&{uv:this.uvs}};return new f(i)}processFaceLine(e){for(let t=1;t<e.length;t++){const i=e[t];if(!i)continue;const[n,a,l]=i.split("/"),m=n?parseInt(n,10):void 0,c=a?parseInt(a,10):void 0,u=l?parseInt(l,10):void 0;if(m!==void 0){const o=this.tmpPositions[m-1];o&&this.positions.push(...o)}if(c!==void 0){const o=this.tmpUVs[c-1];o&&this.uvs.push(...o)}if(u!==void 0){const o=this.tmpNormals[u-1];o&&this.normals.push(...o)}}}}exports.EditorRenderer=v;exports.ObjLoader=b;exports.PreviewRenderer=g;exports.Renderer=h;exports.createProgram=p;
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
- import { Texture as u, Program as d, Renderer as g, Transform as b, Camera as f, Geometry as x, Mesh as w, GridHelper as y, AxesHelper as P, Orbit as c, Vec3 as M } from "ogl";
2
- function z(e) {
3
- const t = (
1
+ import { Texture as v, Program as d, Renderer as g, Transform as f, Camera as b, Geometry as w, Mesh as x, GridHelper as y, AxesHelper as M, Orbit as c, Raycast as P, Vec2 as z, Vec3 as C } from "ogl";
2
+ function F(s) {
3
+ const e = (
4
4
  /* glsl */
5
5
  `
6
6
  attribute vec3 position;
@@ -20,7 +20,7 @@ function z(e) {
20
20
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
21
21
  }
22
22
  `
23
- ), s = (
23
+ ), t = (
24
24
  /* glsl */
25
25
  `
26
26
  precision highp float;
@@ -37,14 +37,14 @@ function z(e) {
37
37
  gl_FragColor.a = 1.0;
38
38
  }
39
39
  `
40
- ), i = new u(e);
41
- return new d(e, {
42
- vertex: t,
43
- fragment: s,
40
+ ), i = new v(s);
41
+ return new d(s, {
42
+ vertex: e,
43
+ fragment: t,
44
44
  uniforms: { tMap: { value: i } }
45
45
  });
46
46
  }
47
- class p {
47
+ class u {
48
48
  /** Экземпляр рендерера OGL */
49
49
  gl;
50
50
  /** Корневой объект сцены */
@@ -53,13 +53,16 @@ class p {
53
53
  camera;
54
54
  /** HTML-элемент canvas, на котором рендерится сцена */
55
55
  canvas;
56
+ /** Program для настройки рендеринга моделей */
56
57
  program;
58
+ /** Массив моделей на сцене */
59
+ meshes;
57
60
  /**
58
61
  * Конструктор рендерера
59
62
  * @param canvas - HTMLCanvasElement для рендеринга
60
63
  */
61
- constructor(t) {
62
- this.canvas = t, this.gl = new g({ canvas: t }), this.gl.setSize(t.clientWidth, t.clientHeight), this.gl.gl.clearColor(1, 1, 1, 1), this.scene = new b(), this.camera = new f(this.gl.gl, { fov: 45 }), this.camera.position.set(1, 1, 7), this.camera.lookAt([0, 0, 0]), this.program = z(this.gl.gl);
64
+ constructor(e) {
65
+ this.canvas = e, this.gl = new g({ canvas: e }), this.gl.setSize(e.clientWidth, e.clientHeight), this.gl.gl.clearColor(1, 1, 1, 1), this.scene = new f(), this.camera = new b(this.gl.gl, { fov: 45 }), this.camera.position.set(1, 1, 7), this.camera.lookAt([0, 0, 0]), this.program = F(this.gl.gl);
63
66
  }
64
67
  /**
65
68
  * Обновляет размер рендерера и камеры при изменении размеров canvas.
@@ -88,30 +91,34 @@ class p {
88
91
  * Публичный метод для добавления фигуры.
89
92
  * @param figure Данные фигуры: position, normal, uv
90
93
  */
91
- addFigure(t) {
92
- const s = new x(this.gl.gl, {
93
- position: { size: 3, data: new Float32Array(t.position) },
94
- normal: { size: 3, data: new Float32Array(t.normal ?? []) },
95
- uv: { size: 2, data: new Float32Array(t.uv ?? []) }
96
- }), i = new w(this.gl.gl, {
97
- geometry: s,
94
+ addFigure(e) {
95
+ const t = new w(this.gl.gl, {
96
+ position: { size: 3, data: new Float32Array(e.position) },
97
+ normal: { size: 3, data: new Float32Array(e.normal ?? []) },
98
+ uv: { size: 2, data: new Float32Array(e.uv ?? []) }
99
+ }), i = new x(this.gl.gl, {
100
+ geometry: t,
98
101
  program: this.program
99
102
  });
100
- return i.setParent(this.scene), i;
103
+ return i.setParent(this.scene), this.meshes.push(i), i;
101
104
  }
102
105
  }
103
- class N extends p {
106
+ class N extends u {
104
107
  /** Orbit-контроллер для управления камерой */
105
108
  orbit;
109
+ /** Raycast для подсветки моделей при наведении */
110
+ raycast;
111
+ /** Курсор мыши для остлеживания наведения на 3D-модель */
112
+ mouse;
106
113
  /**
107
114
  * Инициализация сцены редактора.
108
115
  * Создает сетку, оси координат и orbit-контроллер.
109
116
  * @param canvas - HTMLCanvasElement для рендеринга
110
117
  */
111
- constructor(t) {
112
- super(t);
113
- const s = new y(this.gl.gl, { size: 10, divisions: 10 });
114
- s.position.y = -1e-3, s.setParent(this.scene), new P(this.gl.gl, { size: 6, symmetric: !0 }).setParent(this.scene), this.orbit = new c(this.camera, { element: this.canvas });
118
+ constructor(e) {
119
+ super(e);
120
+ const t = new y(this.gl.gl, { size: 10, divisions: 10 });
121
+ t.position.y = -1e-3, t.setParent(this.scene), new M(this.gl.gl, { size: 6, symmetric: !0 }).setParent(this.scene), this.orbit = new c(this.camera, { element: this.canvas }), this.raycast = new P(), this.mouse = new z(), this.initMouseListeners();
115
122
  }
116
123
  /**
117
124
  * Обновление состояния рендерера.
@@ -119,18 +126,53 @@ class N extends p {
119
126
  update() {
120
127
  this.orbit?.update();
121
128
  }
129
+ /**
130
+ * Метод для добавления фигуры.
131
+ * Настройка raycast.
132
+ * @param figure Данные фигуры: position, normal, uv
133
+ */
134
+ addFigure(e) {
135
+ const t = super.addFigure(e);
136
+ if (t.geometry) {
137
+ const i = t.geometry.constructor.name;
138
+ t.geometry.raycast = i.includes("Sphere") ? "sphere" : "box";
139
+ }
140
+ return t.isHit = !1, t.onBeforeRender(({ mesh: i }) => {
141
+ this.updateHitUniform(i);
142
+ }), t;
143
+ }
144
+ /**
145
+ * Обновление uniform uHit для конкретной 3D-модели
146
+ */
147
+ updateHitUniform(e) {
148
+ this.program.uniforms.uHit.value = e.isHit ? 1 : 0;
149
+ }
150
+ /**
151
+ * Инициализация обработчиков мыши для raycast
152
+ */
153
+ initMouseListeners() {
154
+ window.addEventListener("load", () => {
155
+ document.addEventListener("mousemove", this.handleMouseMove, !1);
156
+ });
157
+ }
158
+ /**
159
+ * Обработчик движения мыши
160
+ */
161
+ handleMouseMove = (e) => {
162
+ this.mouse.set(2 * (e.x / this.gl.width) - 1, 2 * (1 - e.y / this.gl.height) - 1), this.raycast.castMouse(this.camera, this.mouse), this.meshes.forEach((i) => i.isHit = !1), this.raycast.intersectBounds(this.meshes).forEach((i) => i.isHit = !0);
163
+ };
122
164
  }
123
- class F extends p {
165
+ class U extends u {
124
166
  /** Orbit-контроллер для управления камерой */
125
167
  orbit;
126
168
  /**
127
169
  * Инициализация сцены предпросмотра.
128
170
  * @param canvas - HTMLCanvasElement для рендеринга
129
171
  */
130
- constructor(t) {
131
- super(t), this.orbit = new c(this.camera, {
172
+ constructor(e) {
173
+ super(e), this.orbit = new c(this.camera, {
132
174
  element: this.canvas,
133
- target: new M(0, 0, 0),
175
+ target: new C(0, 0, 0),
134
176
  minPolarAngle: Math.PI / 2,
135
177
  maxPolarAngle: Math.PI / 2,
136
178
  enableRotate: !0,
@@ -145,7 +187,7 @@ class F extends p {
145
187
  this.orbit?.update();
146
188
  }
147
189
  }
148
- class C {
190
+ class I {
149
191
  /** Тип фигуры */
150
192
  type;
151
193
  /** Позиции вершин */
@@ -160,11 +202,11 @@ class C {
160
202
  * Создаёт новую фигуру
161
203
  * @param data - исходные данные фигуры
162
204
  */
163
- constructor(t) {
164
- this.type = t.type, this.position = t.position, this.normal = t.normal ?? [], this.uv = t.uv ?? [], this.material = t.material;
205
+ constructor(e) {
206
+ this.type = e.type, this.position = e.position, this.normal = e.normal ?? [], this.uv = e.uv ?? [], this.material = e.material;
165
207
  }
166
208
  }
167
- var v = /* @__PURE__ */ ((e) => (e[e.Cube = 0] = "Cube", e[e.Sphere = 1] = "Sphere", e[e.Plane = 2] = "Plane", e[e.Cylinder = 3] = "Cylinder", e[e.Custom = 4] = "Custom", e))(v || {});
209
+ var p = /* @__PURE__ */ ((s) => (s[s.Cube = 0] = "Cube", s[s.Sphere = 1] = "Sphere", s[s.Plane = 2] = "Plane", s[s.Cylinder = 3] = "Cylinder", s[s.Custom = 4] = "Custom", s))(p || {});
168
210
  class A {
169
211
  /** Позиции вершин */
170
212
  positions = [];
@@ -180,12 +222,12 @@ class A {
180
222
  * Загружает OBJ-модель в Figure
181
223
  * @param objContent Строка содержимого .obj файла
182
224
  */
183
- load(t) {
184
- const s = t.split(`
225
+ load(e) {
226
+ const t = e.split(`
185
227
  `);
186
- for (const n of s) {
187
- if (!n.trim() || n.startsWith("#")) continue;
188
- const r = n.trim().split(/\s+/);
228
+ for (const o of t) {
229
+ if (!o.trim() || o.startsWith("#")) continue;
230
+ const r = o.trim().split(/\s+/);
189
231
  switch (r[0]) {
190
232
  case "v":
191
233
  this.tmpPositions.push(r.slice(1).map(Number));
@@ -202,31 +244,31 @@ class A {
202
244
  }
203
245
  }
204
246
  const i = {
205
- type: v.Custom,
247
+ type: p.Custom,
206
248
  position: this.positions,
207
249
  ...this.normals.length > 0 && { normal: this.normals },
208
250
  ...this.uvs.length > 0 && { uv: this.uvs }
209
251
  };
210
- return new C(i);
252
+ return new I(i);
211
253
  }
212
254
  /**
213
255
  * Обрабатывает строку face (f) и разворачивает индексы в массивы для рендеринга
214
256
  */
215
- processFaceLine(t) {
216
- for (let s = 1; s < t.length; s++) {
217
- const i = t[s];
257
+ processFaceLine(e) {
258
+ for (let t = 1; t < e.length; t++) {
259
+ const i = e[t];
218
260
  if (!i) continue;
219
- const [n, r, o] = i.split("/"), l = n ? parseInt(n, 10) : void 0, m = r ? parseInt(r, 10) : void 0, h = o ? parseInt(o, 10) : void 0;
220
- if (l !== void 0) {
221
- const a = this.tmpPositions[l - 1];
261
+ const [o, r, n] = i.split("/"), h = o ? parseInt(o, 10) : void 0, m = r ? parseInt(r, 10) : void 0, l = n ? parseInt(n, 10) : void 0;
262
+ if (h !== void 0) {
263
+ const a = this.tmpPositions[h - 1];
222
264
  a && this.positions.push(...a);
223
265
  }
224
266
  if (m !== void 0) {
225
267
  const a = this.tmpUVs[m - 1];
226
268
  a && this.uvs.push(...a);
227
269
  }
228
- if (h !== void 0) {
229
- const a = this.tmpNormals[h - 1];
270
+ if (l !== void 0) {
271
+ const a = this.tmpNormals[l - 1];
230
272
  a && this.normals.push(...a);
231
273
  }
232
274
  }
@@ -235,7 +277,7 @@ class A {
235
277
  export {
236
278
  N as EditorRenderer,
237
279
  A as ObjLoader,
238
- F as PreviewRenderer,
239
- p as Renderer,
240
- z as createProgram
280
+ U as PreviewRenderer,
281
+ u as Renderer,
282
+ F as createProgram
241
283
  };
package/dist/index.umd.js CHANGED
@@ -1,4 +1,4 @@
1
- (function(r,i){typeof exports=="object"&&typeof module<"u"?i(exports,require("ogl")):typeof define=="function"&&define.amd?define(["exports","ogl"],i):(r=typeof globalThis<"u"?globalThis:r||self,i(r.PlanaraCore={},r.OGL))})(this,(function(r,i){"use strict";function h(t){const e=`
1
+ (function(a,r){typeof exports=="object"&&typeof module<"u"?r(exports,require("ogl")):typeof define=="function"&&define.amd?define(["exports","ogl"],r):(a=typeof globalThis<"u"?globalThis:a||self,r(a.PlanaraCore={},a.OGL))})(this,(function(a,r){"use strict";function c(s){const e=`
2
2
  attribute vec3 position;
3
3
  attribute vec3 normal;
4
4
  attribute vec2 uv;
@@ -15,7 +15,7 @@
15
15
  vNormal = normalize(normalMatrix * normal);
16
16
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
17
17
  }
18
- `,s=`
18
+ `,t=`
19
19
  precision highp float;
20
20
 
21
21
  uniform sampler2D tMap;
@@ -29,5 +29,5 @@
29
29
  gl_FragColor.rgb = tex + shading;
30
30
  gl_FragColor.a = 1.0;
31
31
  }
32
- `,n=new i.Texture(t);return new i.Program(t,{vertex:e,fragment:s,uniforms:{tMap:{value:n}}})}class c{gl;scene;camera;canvas;program;constructor(e){this.canvas=e,this.gl=new i.Renderer({canvas:e}),this.gl.setSize(e.clientWidth,e.clientHeight),this.gl.gl.clearColor(1,1,1,1),this.scene=new i.Transform,this.camera=new i.Camera(this.gl.gl,{fov:45}),this.camera.position.set(1,1,7),this.camera.lookAt([0,0,0]),this.program=h(this.gl.gl)}resize(){this.gl.setSize(this.canvas.width,this.canvas.height),this.camera.perspective({aspect:this.canvas.width/this.canvas.height})}render(){this.gl.render({scene:this.scene,camera:this.camera})}update(){}loop(){this.update(),this.render(),requestAnimationFrame(this.loop.bind(this))}addFigure(e){const s=new i.Geometry(this.gl.gl,{position:{size:3,data:new Float32Array(e.position)},normal:{size:3,data:new Float32Array(e.normal??[])},uv:{size:2,data:new Float32Array(e.uv??[])}}),n=new i.Mesh(this.gl.gl,{geometry:s,program:this.program});return n.setParent(this.scene),n}}class g extends c{orbit;constructor(e){super(e);const s=new i.GridHelper(this.gl.gl,{size:10,divisions:10});s.position.y=-.001,s.setParent(this.scene),new i.AxesHelper(this.gl.gl,{size:6,symmetric:!0}).setParent(this.scene),this.orbit=new i.Orbit(this.camera,{element:this.canvas})}update(){this.orbit?.update()}}class f extends c{orbit;constructor(e){super(e),this.orbit=new i.Orbit(this.camera,{element:this.canvas,target:new i.Vec3(0,0,0),minPolarAngle:Math.PI/2,maxPolarAngle:Math.PI/2,enableRotate:!0,enableZoom:!1,enablePan:!1})}update(){this.orbit?.update()}}class b{type;position;normal;uv;material;constructor(e){this.type=e.type,this.position=e.position,this.normal=e.normal??[],this.uv=e.uv??[],this.material=e.material}}var m=(t=>(t[t.Cube=0]="Cube",t[t.Sphere=1]="Sphere",t[t.Plane=2]="Plane",t[t.Cylinder=3]="Cylinder",t[t.Custom=4]="Custom",t))(m||{});class w{positions=[];normals=[];uvs=[];tmpPositions=[];tmpNormals=[];tmpUVs=[];load(e){const s=e.split(`
33
- `);for(const l of s){if(!l.trim()||l.startsWith("#"))continue;const a=l.trim().split(/\s+/);switch(a[0]){case"v":this.tmpPositions.push(a.slice(1).map(Number));break;case"vn":this.tmpNormals.push(a.slice(1).map(Number));break;case"vt":this.tmpUVs.push(a.slice(1).map(Number));break;case"f":this.processFaceLine(a);break}}const n={type:m.Custom,position:this.positions,...this.normals.length>0&&{normal:this.normals},...this.uvs.length>0&&{uv:this.uvs}};return new b(n)}processFaceLine(e){for(let s=1;s<e.length;s++){const n=e[s];if(!n)continue;const[l,a,p]=n.split("/"),v=l?parseInt(l,10):void 0,u=a?parseInt(a,10):void 0,d=p?parseInt(p,10):void 0;if(v!==void 0){const o=this.tmpPositions[v-1];o&&this.positions.push(...o)}if(u!==void 0){const o=this.tmpUVs[u-1];o&&this.uvs.push(...o)}if(d!==void 0){const o=this.tmpNormals[d-1];o&&this.normals.push(...o)}}}}r.EditorRenderer=g,r.ObjLoader=w,r.PreviewRenderer=f,r.Renderer=c,r.createProgram=h,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
32
+ `,i=new r.Texture(s);return new r.Program(s,{vertex:e,fragment:t,uniforms:{tMap:{value:i}}})}class m{gl;scene;camera;canvas;program;meshes;constructor(e){this.canvas=e,this.gl=new r.Renderer({canvas:e}),this.gl.setSize(e.clientWidth,e.clientHeight),this.gl.gl.clearColor(1,1,1,1),this.scene=new r.Transform,this.camera=new r.Camera(this.gl.gl,{fov:45}),this.camera.position.set(1,1,7),this.camera.lookAt([0,0,0]),this.program=c(this.gl.gl)}resize(){this.gl.setSize(this.canvas.width,this.canvas.height),this.camera.perspective({aspect:this.canvas.width/this.canvas.height})}render(){this.gl.render({scene:this.scene,camera:this.camera})}update(){}loop(){this.update(),this.render(),requestAnimationFrame(this.loop.bind(this))}addFigure(e){const t=new r.Geometry(this.gl.gl,{position:{size:3,data:new Float32Array(e.position)},normal:{size:3,data:new Float32Array(e.normal??[])},uv:{size:2,data:new Float32Array(e.uv??[])}}),i=new r.Mesh(this.gl.gl,{geometry:t,program:this.program});return i.setParent(this.scene),this.meshes.push(i),i}}class g extends m{orbit;raycast;mouse;constructor(e){super(e);const t=new r.GridHelper(this.gl.gl,{size:10,divisions:10});t.position.y=-.001,t.setParent(this.scene),new r.AxesHelper(this.gl.gl,{size:6,symmetric:!0}).setParent(this.scene),this.orbit=new r.Orbit(this.camera,{element:this.canvas}),this.raycast=new r.Raycast,this.mouse=new r.Vec2,this.initMouseListeners()}update(){this.orbit?.update()}addFigure(e){const t=super.addFigure(e);if(t.geometry){const i=t.geometry.constructor.name;t.geometry.raycast=i.includes("Sphere")?"sphere":"box"}return t.isHit=!1,t.onBeforeRender(({mesh:i})=>{this.updateHitUniform(i)}),t}updateHitUniform(e){this.program.uniforms.uHit.value=e.isHit?1:0}initMouseListeners(){window.addEventListener("load",()=>{document.addEventListener("mousemove",this.handleMouseMove,!1)})}handleMouseMove=e=>{this.mouse.set(2*(e.x/this.gl.width)-1,2*(1-e.y/this.gl.height)-1),this.raycast.castMouse(this.camera,this.mouse),this.meshes.forEach(i=>i.isHit=!1),this.raycast.intersectBounds(this.meshes).forEach(i=>i.isHit=!0)}}class f extends m{orbit;constructor(e){super(e),this.orbit=new r.Orbit(this.camera,{element:this.canvas,target:new r.Vec3(0,0,0),minPolarAngle:Math.PI/2,maxPolarAngle:Math.PI/2,enableRotate:!0,enableZoom:!1,enablePan:!1})}update(){this.orbit?.update()}}class b{type;position;normal;uv;material;constructor(e){this.type=e.type,this.position=e.position,this.normal=e.normal??[],this.uv=e.uv??[],this.material=e.material}}var l=(s=>(s[s.Cube=0]="Cube",s[s.Sphere=1]="Sphere",s[s.Plane=2]="Plane",s[s.Cylinder=3]="Cylinder",s[s.Custom=4]="Custom",s))(l||{});class y{positions=[];normals=[];uvs=[];tmpPositions=[];tmpNormals=[];tmpUVs=[];load(e){const t=e.split(`
33
+ `);for(const h of t){if(!h.trim()||h.startsWith("#"))continue;const n=h.trim().split(/\s+/);switch(n[0]){case"v":this.tmpPositions.push(n.slice(1).map(Number));break;case"vn":this.tmpNormals.push(n.slice(1).map(Number));break;case"vt":this.tmpUVs.push(n.slice(1).map(Number));break;case"f":this.processFaceLine(n);break}}const i={type:l.Custom,position:this.positions,...this.normals.length>0&&{normal:this.normals},...this.uvs.length>0&&{uv:this.uvs}};return new b(i)}processFaceLine(e){for(let t=1;t<e.length;t++){const i=e[t];if(!i)continue;const[h,n,u]=i.split("/"),d=h?parseInt(h,10):void 0,p=n?parseInt(n,10):void 0,v=u?parseInt(u,10):void 0;if(d!==void 0){const o=this.tmpPositions[d-1];o&&this.positions.push(...o)}if(p!==void 0){const o=this.tmpUVs[p-1];o&&this.uvs.push(...o)}if(v!==void 0){const o=this.tmpNormals[v-1];o&&this.normals.push(...o)}}}}a.EditorRenderer=g,a.ObjLoader=y,a.PreviewRenderer=f,a.Renderer=m,a.createProgram=c,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planara/core",
3
- "version": "1.3.1",
3
+ "version": "1.4.1",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"