@hatiolab/figure-model 0.1.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.
- package/CHANGELOG.md +45 -0
- package/README.md +163 -0
- package/dist/blueprint.d.ts +32 -0
- package/dist/blueprint.d.ts.map +1 -0
- package/dist/blueprint.js +163 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/cost-chart.d.ts +35 -0
- package/dist/cost-chart.d.ts.map +1 -0
- package/dist/cost-chart.js +150 -0
- package/dist/cost-chart.js.map +1 -0
- package/dist/cost.d.ts +160 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +170 -0
- package/dist/cost.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +38 -0
- package/dist/keys.d.ts.map +1 -0
- package/dist/keys.js +57 -0
- package/dist/keys.js.map +1 -0
- package/dist/types.d.ts +360 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +162 -0
- package/dist/types.js.map +1 -0
- package/dist/validate.d.ts +13 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +327 -0
- package/dist/validate.js.map +1 -0
- package/docs/design.md +192 -0
- package/docs/format-survey.md +108 -0
- package/docs/format.md +295 -0
- package/docs/validation.md +159 -0
- package/package.json +80 -0
package/dist/cost.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 원가 — 이 Figure 하나가 얼마나 무거운가, 그리고 **여러 개 놓으면 무엇이 늘어나나.**
|
|
3
|
+
*
|
|
4
|
+
* 저작자가 알아야 할 것은 삼각형 수 하나가 아니다. 진짜 물음은 이것이다 —
|
|
5
|
+
*
|
|
6
|
+
* 이걸 100개 놓으면 무엇이 100배가 되고 무엇이 그대로인가.
|
|
7
|
+
*
|
|
8
|
+
* 그대로인 것이 곧 **재활용되는 것**이다. geometry 와 재질은 타입당 한 벌이라 인스턴스
|
|
9
|
+
* 수와 무관하다. 반면 삼각형과 draw call 은 인스턴스에 비례한다. 이 둘을 갈라 보여
|
|
10
|
+
* 주면, 저작자가 「부품을 하나 더 넣을까」를 근거를 갖고 정할 수 있다.
|
|
11
|
+
*/
|
|
12
|
+
import type { FigureBlueprint } from './types.ts';
|
|
13
|
+
/** 인스턴스를 여럿 놓았을 때. */
|
|
14
|
+
export interface FigureCostAt {
|
|
15
|
+
/** 몇 개 기준인가. */
|
|
16
|
+
instances: number;
|
|
17
|
+
/**
|
|
18
|
+
* GPU 가 처리하는 삼각형. **인스턴스에 비례한다.**
|
|
19
|
+
*
|
|
20
|
+
* geometry 를 나눠 써도 이 값은 줄지 않는다 — 공유는 메모리와 업로드를 아끼는 것이지
|
|
21
|
+
* 그리는 양을 아끼는 것이 아니다.
|
|
22
|
+
*/
|
|
23
|
+
triangles: number;
|
|
24
|
+
/**
|
|
25
|
+
* 지금 방식의 draw call. **인스턴스에 비례한다** — 인스턴스마다 묶음 수만큼 mesh 가
|
|
26
|
+
* 생기기 때문이다. three.js 에서 한 객체는 부모가 하나뿐이라 Mesh 객체 자체는 나눠
|
|
27
|
+
* 쓸 수 없다.
|
|
28
|
+
*/
|
|
29
|
+
drawCalls: number;
|
|
30
|
+
/**
|
|
31
|
+
* 실제로 만들어지는 정점 버퍼 수. **인스턴스와 무관하다.**
|
|
32
|
+
*
|
|
33
|
+
* 100개를 놓아도 이 값은 그대로다. 이것이 「재활용되는 것」의 실체다.
|
|
34
|
+
*/
|
|
35
|
+
geometries: number;
|
|
36
|
+
/** 실제로 만들어지는 재질 수. **인스턴스와 무관하다.** */
|
|
37
|
+
materials: number;
|
|
38
|
+
/**
|
|
39
|
+
* 올라가는 텍스처 수. **인스턴스와 무관하다** — 이름으로 가리키는 자산이라 같은
|
|
40
|
+
* `ref` 는 한 번만 올라간다.
|
|
41
|
+
*/
|
|
42
|
+
textures: number;
|
|
43
|
+
/**
|
|
44
|
+
* `InstancedMesh` 를 쓰면 도달할 수 있는 draw call.
|
|
45
|
+
*
|
|
46
|
+
* 지금은 쓰지 않는다 — 인스턴스별 선택·컬링·재질을 다르게 다뤄야 해서 별개
|
|
47
|
+
* 결정이다. 이 값과 `drawCalls` 의 차이가 그 결정으로 얻을 수 있는 몫이다.
|
|
48
|
+
*/
|
|
49
|
+
drawCallsIfInstanced: number;
|
|
50
|
+
}
|
|
51
|
+
export interface FigureCost {
|
|
52
|
+
type: string;
|
|
53
|
+
/** 부품 자리 수. */
|
|
54
|
+
parts: number;
|
|
55
|
+
/** 이 Figure 하나의 삼각형 수. */
|
|
56
|
+
triangles: number;
|
|
57
|
+
/** 묶음 수 = 인스턴스 하나당 draw call. */
|
|
58
|
+
groups: number;
|
|
59
|
+
/**
|
|
60
|
+
* 서로 다른 **형상**의 수(`geometryKeyOf` 기준).
|
|
61
|
+
*
|
|
62
|
+
* 부품 자리보다 적으면 그만큼 같은 형상을 되쓰고 있다는 뜻이다. 선반 단이나 롤러처럼
|
|
63
|
+
* 같은 것이 여러 번 나오는 형상에서 이 값이 크게 벌어진다.
|
|
64
|
+
*/
|
|
65
|
+
distinctShapes: number;
|
|
66
|
+
/** 서로 다른 재질의 수(`materialKeyOf` 기준). */
|
|
67
|
+
distinctMaterials: number;
|
|
68
|
+
/**
|
|
69
|
+
* 팔레트 밖 표면(무늬·그라디언트)의 **종류 수.**
|
|
70
|
+
*
|
|
71
|
+
* 같은 `ref` 는 한 텍스처이므로 부품 수가 아니라 종류를 센다. 0 이 정상이다.
|
|
72
|
+
* 재질은 나눠 쓰지만 텍스처마다 GPU 메모리를 쓴다.
|
|
73
|
+
*/
|
|
74
|
+
surfaceTextures: number;
|
|
75
|
+
/**
|
|
76
|
+
* 형상 재활용 비 — `distinctShapes / parts`.
|
|
77
|
+
*
|
|
78
|
+
* 1 이면 부품마다 형상이 다르다(재활용 없음). 낮을수록 같은 형상을 많이 되쓴다.
|
|
79
|
+
* 부품이 없으면 0.
|
|
80
|
+
*/
|
|
81
|
+
shapeReuse: number;
|
|
82
|
+
/** 여럿 놓았을 때. 기본 100개. */
|
|
83
|
+
at: FigureCostAt;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* 청사진 하나의 원가를 낸다.
|
|
87
|
+
*
|
|
88
|
+
* **삼각형 수는 추정치다.** `trianglesOf` 의 식에서 나오며 실제 정점 버퍼의 삼각형
|
|
89
|
+
* 수와 다를 수 있다 — 특히 `polygon` 의 cap 삼각분할이 그렇다. 정확한 값은 형상을
|
|
90
|
+
* 실제로 만들어 봐야 알 수 있고, 그것은 이 모듈이 아니라 렌더러의 몫이다.
|
|
91
|
+
*
|
|
92
|
+
* @param blueprint 컴파일된 청사진
|
|
93
|
+
* @param instances 몇 개를 놓았을 때로 볼 것인가. 기본 100
|
|
94
|
+
*/
|
|
95
|
+
export declare function costOf(blueprint: FigureBlueprint, instances?: number): FigureCost;
|
|
96
|
+
/**
|
|
97
|
+
* 사람이 읽는 한 줄들. 저작 화면과 진단 출력에 그대로 쓸 수 있다.
|
|
98
|
+
*
|
|
99
|
+
* 값을 다시 계산하지 않는다 — `costOf` 가 낸 것을 문장으로 옮기기만 한다.
|
|
100
|
+
*/
|
|
101
|
+
export declare function describeCost(cost: FigureCost): string[];
|
|
102
|
+
/**
|
|
103
|
+
* 한도 하나를 얼마나 쓰고 있나.
|
|
104
|
+
*
|
|
105
|
+
* `limit` 은 **이 모듈이 이미 선언해 둔 값**이다(`LIMITS` · `PART_LIMIT`). 점수를
|
|
106
|
+
* 내려고 새로 지어낸 수가 아니다 — 지어내면 「왜 그 수인가」에 답할 수 없다.
|
|
107
|
+
*/
|
|
108
|
+
export interface FigureBudgetUse {
|
|
109
|
+
key: 'groups' | 'parts' | 'animations' | 'transparent' | 'surface';
|
|
110
|
+
label: string;
|
|
111
|
+
used: number;
|
|
112
|
+
limit: number;
|
|
113
|
+
/** `used / limit`. 1 을 넘으면 위반이다. */
|
|
114
|
+
ratio: number;
|
|
115
|
+
/** 이 한도가 무엇을 지키는가. 저작자에게 그대로 보여 준다. */
|
|
116
|
+
why: string;
|
|
117
|
+
}
|
|
118
|
+
export type FigureGrade = 'A' | 'B' | 'C' | 'D';
|
|
119
|
+
export interface FigureScore {
|
|
120
|
+
/**
|
|
121
|
+
* 0–100. **선언된 한도에 남은 여유**다.
|
|
122
|
+
*
|
|
123
|
+
* 가장 빠듯한 한도 하나로 정한다 — 넷 중 하나만 꽉 차 있어도 대량 배치에서는 그것이
|
|
124
|
+
* 병목이 되기 때문이다. 평균을 내면 빠듯한 하나가 여유 있는 셋에 묻힌다.
|
|
125
|
+
*/
|
|
126
|
+
score: number;
|
|
127
|
+
/**
|
|
128
|
+
* A 여유 절반 이상 · B 4분의 1 이상 · C 한도 안 · D 한도 초과
|
|
129
|
+
*
|
|
130
|
+
* D 는 곧 위반이 있다는 뜻이다 — `blueprint.violations` 에 사유가 들어 있다.
|
|
131
|
+
*/
|
|
132
|
+
grade: FigureGrade;
|
|
133
|
+
/** 가장 빠듯한 한도. **여기부터 고치면 된다.** */
|
|
134
|
+
tightest: FigureBudgetUse;
|
|
135
|
+
budgets: FigureBudgetUse[];
|
|
136
|
+
/**
|
|
137
|
+
* 형상 되쓰기 — 한도가 아니라 덤이다. 점수에 넣지 않는다.
|
|
138
|
+
*
|
|
139
|
+
* 되쓰기는 많을수록 좋지만 **한도가 없다.** 부품마다 형상이 달라도 잘못이 아니다.
|
|
140
|
+
* 점수에 섞으면 「형상을 억지로 같게 만들라」는 신호가 되어 저작을 왜곡한다.
|
|
141
|
+
*/
|
|
142
|
+
reuse: {
|
|
143
|
+
/** 서로 다른 형상 수. */
|
|
144
|
+
distinct: number;
|
|
145
|
+
/** 부품 자리 수. */
|
|
146
|
+
parts: number;
|
|
147
|
+
/** `distinct / parts`. 낮을수록 많이 되쓴다. */
|
|
148
|
+
ratio: number;
|
|
149
|
+
/** 되써서 아낀 형상 수. */
|
|
150
|
+
saved: number;
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 대량 배치 적합도를 점수로 낸다.
|
|
155
|
+
*
|
|
156
|
+
* **점수의 근거는 전부 선언된 한도다.** 새로 지어낸 기준은 없다. 등급이 D 면
|
|
157
|
+
* `blueprint.violations` 에 그 사유가 들어 있다.
|
|
158
|
+
*/
|
|
159
|
+
export declare function scoreOf(blueprint: FigureBlueprint): FigureScore;
|
|
160
|
+
//# sourceMappingURL=cost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,sBAAsB;AACtB,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAA;IAEjB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,UAAU,EAAE,MAAM,CAAA;IAElB,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAA;IAEjB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;;;;OAKG;IACH,oBAAoB,EAAE,MAAM,CAAA;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAA;IAEZ,eAAe;IACf,KAAK,EAAE,MAAM,CAAA;IAEb,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAA;IAEjB,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAA;IAEd;;;;;OAKG;IACH,cAAc,EAAE,MAAM,CAAA;IAEtB,uCAAuC;IACvC,iBAAiB,EAAE,MAAM,CAAA;IAEzB;;;;;OAKG;IACH,eAAe,EAAE,MAAM,CAAA;IAEvB;;;;;OAKG;IACH,UAAU,EAAE,MAAM,CAAA;IAElB,yBAAyB;IACzB,EAAE,EAAE,YAAY,CAAA;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,SAAS,EAAE,eAAe,EAAE,SAAS,SAAM,GAAG,UAAU,CA0C9E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAwBvD;AAID;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,aAAa,GAAG,SAAS,CAAA;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,MAAM,WAAW,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE/C,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;;;OAIG;IACH,KAAK,EAAE,WAAW,CAAA;IAElB,kCAAkC;IAClC,QAAQ,EAAE,eAAe,CAAA;IAEzB,OAAO,EAAE,eAAe,EAAE,CAAA;IAE1B;;;;;OAKG;IACH,KAAK,EAAE;QACL,kBAAkB;QAClB,QAAQ,EAAE,MAAM,CAAA;QAChB,eAAe;QACf,KAAK,EAAE,MAAM,CAAA;QACb,uCAAuC;QACvC,KAAK,EAAE,MAAM,CAAA;QACb,mBAAmB;QACnB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAaD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE,eAAe,GAAG,WAAW,CAoE/D"}
|
package/dist/cost.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 원가 — 이 Figure 하나가 얼마나 무거운가, 그리고 **여러 개 놓으면 무엇이 늘어나나.**
|
|
3
|
+
*
|
|
4
|
+
* 저작자가 알아야 할 것은 삼각형 수 하나가 아니다. 진짜 물음은 이것이다 —
|
|
5
|
+
*
|
|
6
|
+
* 이걸 100개 놓으면 무엇이 100배가 되고 무엇이 그대로인가.
|
|
7
|
+
*
|
|
8
|
+
* 그대로인 것이 곧 **재활용되는 것**이다. geometry 와 재질은 타입당 한 벌이라 인스턴스
|
|
9
|
+
* 수와 무관하다. 반면 삼각형과 draw call 은 인스턴스에 비례한다. 이 둘을 갈라 보여
|
|
10
|
+
* 주면, 저작자가 「부품을 하나 더 넣을까」를 근거를 갖고 정할 수 있다.
|
|
11
|
+
*/
|
|
12
|
+
import { LIMITS, PART_LIMIT } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* 청사진 하나의 원가를 낸다.
|
|
15
|
+
*
|
|
16
|
+
* **삼각형 수는 추정치다.** `trianglesOf` 의 식에서 나오며 실제 정점 버퍼의 삼각형
|
|
17
|
+
* 수와 다를 수 있다 — 특히 `polygon` 의 cap 삼각분할이 그렇다. 정확한 값은 형상을
|
|
18
|
+
* 실제로 만들어 봐야 알 수 있고, 그것은 이 모듈이 아니라 렌더러의 몫이다.
|
|
19
|
+
*
|
|
20
|
+
* @param blueprint 컴파일된 청사진
|
|
21
|
+
* @param instances 몇 개를 놓았을 때로 볼 것인가. 기본 100
|
|
22
|
+
*/
|
|
23
|
+
export function costOf(blueprint, instances = 100) {
|
|
24
|
+
const n = Math.max(0, Math.floor(instances));
|
|
25
|
+
const shapes = new Set();
|
|
26
|
+
const materials = new Set();
|
|
27
|
+
let parts = 0;
|
|
28
|
+
let triangles = 0;
|
|
29
|
+
const surfaces = new Set();
|
|
30
|
+
for (const group of blueprint.groups) {
|
|
31
|
+
materials.add(group.materialKey);
|
|
32
|
+
const surface = group.material?.surface;
|
|
33
|
+
if (surface)
|
|
34
|
+
surfaces.add(`${surface.kind}:${surface.ref}`);
|
|
35
|
+
for (const member of group.members) {
|
|
36
|
+
parts++;
|
|
37
|
+
triangles += member.triangles;
|
|
38
|
+
shapes.add(member.geometryKey);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const groups = blueprint.groups.length;
|
|
42
|
+
return {
|
|
43
|
+
type: blueprint.type,
|
|
44
|
+
parts,
|
|
45
|
+
triangles,
|
|
46
|
+
groups,
|
|
47
|
+
distinctShapes: shapes.size,
|
|
48
|
+
distinctMaterials: materials.size,
|
|
49
|
+
surfaceTextures: surfaces.size,
|
|
50
|
+
shapeReuse: parts === 0 ? 0 : shapes.size / parts,
|
|
51
|
+
at: {
|
|
52
|
+
instances: n,
|
|
53
|
+
triangles: triangles * n,
|
|
54
|
+
drawCalls: groups * n,
|
|
55
|
+
// 병합된 geometry 는 (타입, 묶음)당 하나다 — 인스턴스가 몇이든 늘지 않는다.
|
|
56
|
+
geometries: groups,
|
|
57
|
+
materials: materials.size,
|
|
58
|
+
textures: surfaces.size,
|
|
59
|
+
drawCallsIfInstanced: groups
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* 사람이 읽는 한 줄들. 저작 화면과 진단 출력에 그대로 쓸 수 있다.
|
|
65
|
+
*
|
|
66
|
+
* 값을 다시 계산하지 않는다 — `costOf` 가 낸 것을 문장으로 옮기기만 한다.
|
|
67
|
+
*/
|
|
68
|
+
export function describeCost(cost) {
|
|
69
|
+
const { at } = cost;
|
|
70
|
+
const lines = [
|
|
71
|
+
`${cost.type} — 부품 ${cost.parts} · 삼각형 ${cost.triangles} · 묶음 ${cost.groups}`,
|
|
72
|
+
`형상 ${cost.distinctShapes}종 · 재질 ${cost.distinctMaterials}종`
|
|
73
|
+
];
|
|
74
|
+
if (cost.distinctShapes < cost.parts) {
|
|
75
|
+
lines.push(`부품 ${cost.parts} 자리를 형상 ${cost.distinctShapes}종으로 채운다 — 나머지는 되쓴다`);
|
|
76
|
+
}
|
|
77
|
+
lines.push(`${at.instances}개를 놓으면 — 삼각형 ${at.triangles} · draw call ${at.drawCalls}`);
|
|
78
|
+
lines.push(`그래도 정점 버퍼는 ${at.geometries}개, 재질은 ${at.materials}개 그대로다`);
|
|
79
|
+
if (cost.surfaceTextures > 0) {
|
|
80
|
+
lines.push(`팔레트 밖 표면이 ${cost.surfaceTextures}종 있다 — 재질은 나눠 쓰지만 텍스처 메모리를 쓴다`);
|
|
81
|
+
}
|
|
82
|
+
if (at.drawCallsIfInstanced < at.drawCalls) {
|
|
83
|
+
lines.push(`InstancedMesh 를 쓰면 draw call 이 ${at.drawCallsIfInstanced}까지 내려간다`);
|
|
84
|
+
}
|
|
85
|
+
return lines;
|
|
86
|
+
}
|
|
87
|
+
const GRADE_BOUNDS = [
|
|
88
|
+
['A', 0.5],
|
|
89
|
+
['B', 0.75],
|
|
90
|
+
['C', 1]
|
|
91
|
+
];
|
|
92
|
+
function gradeOf(ratio) {
|
|
93
|
+
for (const [grade, bound] of GRADE_BOUNDS)
|
|
94
|
+
if (ratio <= bound)
|
|
95
|
+
return grade;
|
|
96
|
+
return 'D';
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 대량 배치 적합도를 점수로 낸다.
|
|
100
|
+
*
|
|
101
|
+
* **점수의 근거는 전부 선언된 한도다.** 새로 지어낸 기준은 없다. 등급이 D 면
|
|
102
|
+
* `blueprint.violations` 에 그 사유가 들어 있다.
|
|
103
|
+
*/
|
|
104
|
+
export function scoreOf(blueprint) {
|
|
105
|
+
const cost = costOf(blueprint, 1);
|
|
106
|
+
const animations = blueprint.groups.filter(g => g.animated).length;
|
|
107
|
+
const transparent = new Set(blueprint.groups.filter(g => g.material.transparent).map(g => g.materialKey)).size;
|
|
108
|
+
const partLimit = blueprint.detailLevel === undefined ? undefined : PART_LIMIT[blueprint.detailLevel];
|
|
109
|
+
const budgets = [
|
|
110
|
+
{
|
|
111
|
+
key: 'groups',
|
|
112
|
+
label: '묶음',
|
|
113
|
+
used: cost.groups,
|
|
114
|
+
limit: LIMITS.materialGroups,
|
|
115
|
+
ratio: cost.groups / LIMITS.materialGroups,
|
|
116
|
+
why: '인스턴스 하나마다 이만큼 draw call 이 든다'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
key: 'animations',
|
|
120
|
+
label: '애니메이션',
|
|
121
|
+
used: animations,
|
|
122
|
+
limit: LIMITS.animationPoints,
|
|
123
|
+
ratio: animations / LIMITS.animationPoints,
|
|
124
|
+
why: '포인트마다 묶음이 하나 늘고, 프레임마다 갱신이 는다'
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
key: 'transparent',
|
|
128
|
+
label: '투명 재질',
|
|
129
|
+
used: transparent,
|
|
130
|
+
limit: LIMITS.transparentMaterials,
|
|
131
|
+
ratio: transparent / LIMITS.transparentMaterials,
|
|
132
|
+
why: '투명은 별도 정렬 경로를 탄다'
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: 'surface',
|
|
136
|
+
label: '팔레트 밖 표면',
|
|
137
|
+
used: cost.surfaceTextures,
|
|
138
|
+
limit: LIMITS.surfaceTextures,
|
|
139
|
+
ratio: cost.surfaceTextures / LIMITS.surfaceTextures,
|
|
140
|
+
why: '단색 규칙의 예외다. 텍스처마다 GPU 메모리와 샘플러를 쓴다'
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
if (partLimit !== undefined) {
|
|
144
|
+
budgets.push({
|
|
145
|
+
key: 'parts',
|
|
146
|
+
label: '부품 수',
|
|
147
|
+
used: cost.parts,
|
|
148
|
+
limit: partLimit,
|
|
149
|
+
ratio: cost.parts / partLimit,
|
|
150
|
+
why: `디테일 등급 ${blueprint.detailLevel} 이 정한 상한이다`
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
let tightest = budgets[0];
|
|
154
|
+
for (const b of budgets)
|
|
155
|
+
if (b.ratio > tightest.ratio)
|
|
156
|
+
tightest = b;
|
|
157
|
+
return {
|
|
158
|
+
score: Math.max(0, Math.round(100 * (1 - tightest.ratio))),
|
|
159
|
+
grade: gradeOf(tightest.ratio),
|
|
160
|
+
tightest,
|
|
161
|
+
budgets,
|
|
162
|
+
reuse: {
|
|
163
|
+
distinct: cost.distinctShapes,
|
|
164
|
+
parts: cost.parts,
|
|
165
|
+
ratio: cost.shapeReuse,
|
|
166
|
+
saved: cost.parts - cost.distinctShapes
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=cost.js.map
|
package/dist/cost.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './types.ts';
|
|
2
|
+
export { validate, type ValidateResult } from './validate.ts';
|
|
3
|
+
export { compile, FigureCompileError, geometryKeyOf, materialKeyOf, trianglesOf, usesSegments } from './blueprint.ts';
|
|
4
|
+
export { costOf, describeCost, scoreOf, type FigureBudgetUse, type FigureCost, type FigureCostAt, type FigureGrade, type FigureScore } from './cost.ts';
|
|
5
|
+
export { costCurve, costCurveSvg, type CostCurveOptions, type CostCurvePoint } from './cost-chart.ts';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACrH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,OAAO,EACP,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © HatioLab Inc. All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
* @hatiolab/figure-model
|
|
5
|
+
*
|
|
6
|
+
* Figure 저작 결과의 형식과 검증. 의존이 없다 — 서버가 검증하고, 저작도구가 만들고,
|
|
7
|
+
* 보드가 소비한다. 특정 렌더러의 것이 아니다.
|
|
8
|
+
*
|
|
9
|
+
* 형식 레퍼런스: docs/format.md · 오류·위반 코드: docs/validation.md
|
|
10
|
+
* 설계: docs/design.md · 포맷 검토: docs/format-survey.md
|
|
11
|
+
*/
|
|
12
|
+
export * from "./types.js";
|
|
13
|
+
export { validate } from "./validate.js";
|
|
14
|
+
export { compile, FigureCompileError, geometryKeyOf, materialKeyOf, trianglesOf, usesSegments } from "./blueprint.js";
|
|
15
|
+
export { costOf, describeCost, scoreOf } from "./cost.js";
|
|
16
|
+
export { costCurve, costCurveSvg } from "./cost-chart.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,cAAc,YAAY,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAuB,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AACrH,OAAO,EACL,MAAM,EACN,YAAY,EACZ,OAAO,EAMR,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,YAAY,EAA8C,MAAM,iBAAiB,CAAA"}
|
package/dist/keys.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 키 — 무엇을 무엇과 나눠 쓰는지, 무엇을 무엇과 합치는지를 정하는 식.
|
|
3
|
+
*
|
|
4
|
+
* **이 파일이 유일한 정본이다.** 검사(`validate.ts`)와 컴파일(`blueprint.ts`)이 같은
|
|
5
|
+
* 식을 써야 한다. 다르면 「묶음 수 한도를 지켰다」고 검사가 말한 것과 실제로 만들어지는
|
|
6
|
+
* 묶음 수가 어긋나고, 그 어긋남은 오류 없이 성능으로만 나타난다.
|
|
7
|
+
*
|
|
8
|
+
* 여기 있는 이유는 순환 참조 때문이기도 하다 — `blueprint.ts` 가 `validate.ts` 를
|
|
9
|
+
* 부르므로 반대 방향으로 부를 수 없다.
|
|
10
|
+
*/
|
|
11
|
+
import type { FigurePart, PrimitiveKind } from './types.ts';
|
|
12
|
+
/** 부동소수 오차로 키가 갈리지 않게 자릿수를 맞춘다. */
|
|
13
|
+
export declare function q(n: number): number;
|
|
14
|
+
/** 이 프리미티브가 분할 수를 쓰는가 — 곡면이 있는 것만. */
|
|
15
|
+
export declare function usesSegments(primitive: PrimitiveKind): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* GeometryBank 키.
|
|
18
|
+
*
|
|
19
|
+
* **치수가 키에 들어 있다.** 경로에서 오는 형상(rect·polygon)은 단위로 정규화하면
|
|
20
|
+
* 모서리 반경 비율이 망가지므로 치수를 굽고, 대신 같은 치수끼리만 공유한다.
|
|
21
|
+
*/
|
|
22
|
+
export declare function geometryKeyOf(part: FigurePart): string;
|
|
23
|
+
/**
|
|
24
|
+
* MaterialBank 키. 색은 토큰 이름으로 둔다 — 값을 구우면 테마를 바꿔도 안 따라온다.
|
|
25
|
+
*
|
|
26
|
+
* `transparent` 가 키에 든다. 투명 재질은 별도 정렬 경로를 타므로 불투명과 합칠 수 없다.
|
|
27
|
+
*/
|
|
28
|
+
export declare function materialKeyOf(part: FigurePart): string;
|
|
29
|
+
/**
|
|
30
|
+
* 병합 단위 키 — 이 키가 같은 부품끼리 한 묶음(= draw call 하나)이 된다.
|
|
31
|
+
*
|
|
32
|
+
* 재질에 슬롯을 더한 것이다. 슬롯이 다르면 재질 인덱스가 달라 합칠 수 없다.
|
|
33
|
+
*
|
|
34
|
+
* **검사와 컴파일이 반드시 이 함수를 쓴다.** 정책이 세는 묶음 수와 실제로 만들어지는
|
|
35
|
+
* 묶음 수가 같아야 「한도를 지켰다」는 말이 뜻을 갖는다.
|
|
36
|
+
*/
|
|
37
|
+
export declare function groupKeyOf(part: FigurePart): string;
|
|
38
|
+
//# sourceMappingURL=keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAG3D,mCAAmC;AACnC,wBAAgB,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnC;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAOtD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAMtD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEnD"}
|
package/dist/keys.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 키 — 무엇을 무엇과 나눠 쓰는지, 무엇을 무엇과 합치는지를 정하는 식.
|
|
3
|
+
*
|
|
4
|
+
* **이 파일이 유일한 정본이다.** 검사(`validate.ts`)와 컴파일(`blueprint.ts`)이 같은
|
|
5
|
+
* 식을 써야 한다. 다르면 「묶음 수 한도를 지켰다」고 검사가 말한 것과 실제로 만들어지는
|
|
6
|
+
* 묶음 수가 어긋나고, 그 어긋남은 오류 없이 성능으로만 나타난다.
|
|
7
|
+
*
|
|
8
|
+
* 여기 있는 이유는 순환 참조 때문이기도 하다 — `blueprint.ts` 가 `validate.ts` 를
|
|
9
|
+
* 부르므로 반대 방향으로 부를 수 없다.
|
|
10
|
+
*/
|
|
11
|
+
import { SEGMENTED_PRIMITIVES } from "./types.js";
|
|
12
|
+
/** 부동소수 오차로 키가 갈리지 않게 자릿수를 맞춘다. */
|
|
13
|
+
export function q(n) {
|
|
14
|
+
return Math.round(n * 1000) / 1000;
|
|
15
|
+
}
|
|
16
|
+
/** 이 프리미티브가 분할 수를 쓰는가 — 곡면이 있는 것만. */
|
|
17
|
+
export function usesSegments(primitive) {
|
|
18
|
+
return SEGMENTED_PRIMITIVES.includes(primitive);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* GeometryBank 키.
|
|
22
|
+
*
|
|
23
|
+
* **치수가 키에 들어 있다.** 경로에서 오는 형상(rect·polygon)은 단위로 정규화하면
|
|
24
|
+
* 모서리 반경 비율이 망가지므로 치수를 굽고, 대신 같은 치수끼리만 공유한다.
|
|
25
|
+
*/
|
|
26
|
+
export function geometryKeyOf(part) {
|
|
27
|
+
const { width, height, depth } = part.transform;
|
|
28
|
+
const dims = `${q(width)}x${q(height)}x${q(depth)}`;
|
|
29
|
+
const seg = part.segments === undefined ? '' : `|s${part.segments}`;
|
|
30
|
+
const round = part.shape?.round ? `|r${q(part.shape.round)}` : '';
|
|
31
|
+
const pathLen = part.primitive === 'polygon' ? `|p${part.shape?.path?.length ?? 0}` : '';
|
|
32
|
+
return `${part.primitive}|${dims}${seg}${round}${pathLen}`;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* MaterialBank 키. 색은 토큰 이름으로 둔다 — 값을 구우면 테마를 바꿔도 안 따라온다.
|
|
36
|
+
*
|
|
37
|
+
* `transparent` 가 키에 든다. 투명 재질은 별도 정렬 경로를 타므로 불투명과 합칠 수 없다.
|
|
38
|
+
*/
|
|
39
|
+
export function materialKeyOf(part) {
|
|
40
|
+
const m = part.material;
|
|
41
|
+
// 표면이 키에 든다 — 같은 색이라도 표면이 다르면 다른 재질이다. 같은 표면끼리는
|
|
42
|
+
// 한 재질을 나눠 쓴다(이름으로 가리키는 고정 자산이라 인스턴스와 무관하다).
|
|
43
|
+
const surface = m.surface ? `s${m.surface.kind}:${m.surface.ref}` : '-';
|
|
44
|
+
return [m.token ?? '-', m.preset ?? '-', m.flatShading ? 'f' : '-', m.transparent ? 't' : '-', surface].join('|');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 병합 단위 키 — 이 키가 같은 부품끼리 한 묶음(= draw call 하나)이 된다.
|
|
48
|
+
*
|
|
49
|
+
* 재질에 슬롯을 더한 것이다. 슬롯이 다르면 재질 인덱스가 달라 합칠 수 없다.
|
|
50
|
+
*
|
|
51
|
+
* **검사와 컴파일이 반드시 이 함수를 쓴다.** 정책이 세는 묶음 수와 실제로 만들어지는
|
|
52
|
+
* 묶음 수가 같아야 「한도를 지켰다」는 말이 뜻을 갖는다.
|
|
53
|
+
*/
|
|
54
|
+
export function groupKeyOf(part) {
|
|
55
|
+
return `${materialKeyOf(part)}||${part.slot ?? '-'}`;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=keys.js.map
|
package/dist/keys.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../src/keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEjD,mCAAmC;AACnC,MAAM,UAAU,CAAC,CAAC,CAAS;IACzB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAA;AACpC,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,YAAY,CAAC,SAAwB;IACnD,OAAO,oBAAoB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,CAAA;IAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAA;IACnE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACxF,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG,GAAG,GAAG,KAAK,GAAG,OAAO,EAAE,CAAA;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC5C,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAA;IACvB,gDAAgD;IAChD,6CAA6C;IAC7C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAA;IACvE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACnH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAgB;IACzC,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAAA;AACtD,CAAC"}
|