@jscad/x3d-serializer 2.4.4 → 2.4.5
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 +11 -0
- package/README.md +4 -1
- package/package.json +3 -3
- package/src/index.js +31 -4
- package/tests/geom2ToX3D.test.js +4 -5
- package/tests/geom3ToX3D.test.js +7 -4
- package/tests/path2ToX3D.test.js +2 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.4.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.4...@jscad/x3d-serializer@2.4.5) (2023-06-27)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **x3d-serializer:** added specular highlights and conversion of shape names ([ba26567](https://github.com/jscad/OpenJSCAD.org/commit/ba26567f207a3e7529778ec89436956cf03592bf))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
## [2.4.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/x3d-serializer@2.4.3...@jscad/x3d-serializer@2.4.4) (2023-04-30)
|
|
7
18
|
|
|
8
19
|
|
package/README.md
CHANGED
|
@@ -27,7 +27,10 @@ The serialization of the following geometries are possible.
|
|
|
27
27
|
- serialization of 2D geometries (geom2) to X3D Polyline2D
|
|
28
28
|
- serialization of 2D paths (path2) to X3D Polyline2D
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
The id attribute is used as the DEF name for the generated X3D shape when found on a geometry.
|
|
31
|
+
Material (color) is added to X3D shapes when found on a geometry.
|
|
32
|
+
|
|
33
|
+
All shapes are wrapped in a rotation transform to align the positive Z direction of JSCAD with the vertical up direction in X3D.
|
|
31
34
|
|
|
32
35
|
## Table of Contents
|
|
33
36
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/x3d-serializer",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.5",
|
|
4
4
|
"description": "X3D Serializer for JSCAD",
|
|
5
5
|
"homepage": "https://openjscad.xyz/",
|
|
6
6
|
"repository": "https://github.com/jscad/OpenJSCAD.org",
|
|
@@ -33,12 +33,12 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@jscad/array-utils": "2.1.4",
|
|
36
|
-
"@jscad/modeling": "2.
|
|
36
|
+
"@jscad/modeling": "2.12.0",
|
|
37
37
|
"onml": "1.3.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"ava": "3.15.0",
|
|
41
41
|
"nyc": "15.1.0"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "e269f212db5a00cda740d2f7ad3e5206d1eb839f"
|
|
44
44
|
}
|
package/src/index.js
CHANGED
|
@@ -43,11 +43,13 @@ const stringify = require('onml/lib/stringify')
|
|
|
43
43
|
// https://x3dgraphics.com/examples/X3dForWebAuthors/Chapter13GeometryTrianglesQuadrilaterals/
|
|
44
44
|
|
|
45
45
|
const mimeType = 'model/x3d+xml'
|
|
46
|
+
const defNames = new Map()
|
|
46
47
|
|
|
47
48
|
/**
|
|
48
49
|
* Serialize the give objects to X3D elements (XML).
|
|
49
50
|
* @param {Object} options - options for serialization, REQUIRED
|
|
50
51
|
* @param {Array} [options.color=[0,0,1,1]] - default color for objects
|
|
52
|
+
* @param {Number} [options.shininess=8/256] - x3d shininess for specular highlights
|
|
51
53
|
* @param {Boolean} [options.smooth=false] - use averaged vertex normals
|
|
52
54
|
* @param {Number} [options.decimals=1000] - multiplier before rounding to limit precision
|
|
53
55
|
* @param {Boolean} [options.metadata=true] - add metadata to 3MF contents, such at CreationDate
|
|
@@ -63,6 +65,7 @@ const mimeType = 'model/x3d+xml'
|
|
|
63
65
|
const serialize = (options, ...objects) => {
|
|
64
66
|
const defaults = {
|
|
65
67
|
color: [0, 0, 1, 1.0], // default colorRGBA specification
|
|
68
|
+
shininess: 8 / 256,
|
|
66
69
|
smooth: false,
|
|
67
70
|
decimals: 1000,
|
|
68
71
|
metadata: true,
|
|
@@ -141,7 +144,7 @@ const convertObjects = (objects, options) => {
|
|
|
141
144
|
const convertPath2 = (object, options) => {
|
|
142
145
|
const points = path2.toPoints(object).slice()
|
|
143
146
|
if (points.length > 1 && object.isClosed) points.push(points[0])
|
|
144
|
-
const shape = ['Shape',
|
|
147
|
+
const shape = ['Shape', shapeAttributes(object), convertPolyline2D(poly2.create(points), options)]
|
|
145
148
|
if (object.color) {
|
|
146
149
|
shape.push(convertAppearance(object, 'emissiveColor', options))
|
|
147
150
|
}
|
|
@@ -156,7 +159,7 @@ const convertGeom2 = (object, options) => {
|
|
|
156
159
|
const group = ['Group', {}]
|
|
157
160
|
outlines.forEach((outline) => {
|
|
158
161
|
if (outline.length > 1) outline.push(outline[0]) // close the outline for conversion
|
|
159
|
-
const shape = ['Shape',
|
|
162
|
+
const shape = ['Shape', shapeAttributes(object), convertPolyline2D(poly2.create(outline), options)]
|
|
160
163
|
if (object.color) {
|
|
161
164
|
shape.push(convertAppearance(object, 'emissiveColor', options))
|
|
162
165
|
}
|
|
@@ -165,6 +168,24 @@ const convertGeom2 = (object, options) => {
|
|
|
165
168
|
return group
|
|
166
169
|
}
|
|
167
170
|
|
|
171
|
+
/*
|
|
172
|
+
* generate attributes for Shape node
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
const shapeAttributes = (object, attributes = {}) => {
|
|
176
|
+
if (object.id) {
|
|
177
|
+
Object.assign(attributes, { DEF: checkDefName(object.id) })
|
|
178
|
+
}
|
|
179
|
+
return attributes
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const checkDefName = (defName) => {
|
|
183
|
+
const count = defNames.get(defName) || 0
|
|
184
|
+
defNames.set(defName, count + 1)
|
|
185
|
+
if (count > 0) console.warn(`Warning: object.id set as DEF but not unique. ${defName} set ${count + 1} times.`)
|
|
186
|
+
return defName
|
|
187
|
+
}
|
|
188
|
+
|
|
168
189
|
/*
|
|
169
190
|
* Convert the given object (poly2) to X3D source
|
|
170
191
|
*/
|
|
@@ -180,14 +201,20 @@ const convertAppearance = (object, colorField, options) => {
|
|
|
180
201
|
const colorRGB = object.color.slice(0, 3)
|
|
181
202
|
const color = colorRGB.join(' ')
|
|
182
203
|
const transparency = roundToDecimals(1.0 - object.color[3], options)
|
|
183
|
-
|
|
204
|
+
const materialFields = { [colorField]: color, transparency }
|
|
205
|
+
if (colorField === 'diffuseColor') {
|
|
206
|
+
Object.assign(
|
|
207
|
+
materialFields,
|
|
208
|
+
{ specularColor: '0.2 0.2 0.2', shininess: options.shininess })
|
|
209
|
+
}
|
|
210
|
+
return ['Appearance', ['Material', materialFields]]
|
|
184
211
|
}
|
|
185
212
|
|
|
186
213
|
/*
|
|
187
214
|
* Convert the given object (geom3) to X3D source
|
|
188
215
|
*/
|
|
189
216
|
const convertGeom3 = (object, options) => {
|
|
190
|
-
const shape = ['Shape',
|
|
217
|
+
const shape = ['Shape', shapeAttributes(object), convertMesh(object, options)]
|
|
191
218
|
let appearance = ['Appearance', {}, ['Material']]
|
|
192
219
|
if (object.color) {
|
|
193
220
|
appearance = convertAppearance(object, 'diffuseColor', options)
|
package/tests/geom2ToX3D.test.js
CHANGED
|
@@ -24,7 +24,7 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
|
|
|
24
24
|
|
|
25
25
|
const shape2 = primitives.rectangle()
|
|
26
26
|
|
|
27
|
-
results = serialize({metadata: false}, shape2)
|
|
27
|
+
results = serialize({ metadata: false }, shape2)
|
|
28
28
|
t.is(results.length, 1)
|
|
29
29
|
|
|
30
30
|
obs = results[0]
|
|
@@ -41,7 +41,7 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
|
|
|
41
41
|
|
|
42
42
|
const shape3 = colors.colorize([0, 0, 0], shape2)
|
|
43
43
|
|
|
44
|
-
results = serialize({metadata: false}, shape3)
|
|
44
|
+
results = serialize({ metadata: false }, shape3)
|
|
45
45
|
t.is(results.length, 1)
|
|
46
46
|
|
|
47
47
|
obs = results[0]
|
|
@@ -61,8 +61,7 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
|
|
|
61
61
|
t.is(countOf('diffuseColor', obs), 0)
|
|
62
62
|
t.is(countOf('emissiveColor', obs), 1)
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
results = serialize({metadata: false}, shape2, shape3)
|
|
64
|
+
results = serialize({ metadata: false }, shape2, shape3)
|
|
66
65
|
t.is(results.length, 1)
|
|
67
66
|
|
|
68
67
|
obs = results[0]
|
|
@@ -80,6 +79,6 @@ test('serialize 2D geometry to X3D Polyline2D', (t) => {
|
|
|
80
79
|
t.is(countOf('Appearance', obs), 2)
|
|
81
80
|
t.is(countOf('Material', obs), 1)
|
|
82
81
|
t.is(countOf('diffuseColor', obs), 0)
|
|
82
|
+
t.is(countOf('specularColor', obs), 0)
|
|
83
83
|
t.is(countOf('emissiveColor', obs), 1)
|
|
84
84
|
})
|
|
85
|
-
|
package/tests/geom3ToX3D.test.js
CHANGED
|
@@ -23,7 +23,7 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
|
|
|
23
23
|
|
|
24
24
|
const geom2 = primitives.cube()
|
|
25
25
|
|
|
26
|
-
results = serializer.serialize({metadata: false}, geom2)
|
|
26
|
+
results = serializer.serialize({ metadata: false }, geom2)
|
|
27
27
|
t.is(results.length, 1)
|
|
28
28
|
|
|
29
29
|
obs = results[0]
|
|
@@ -36,13 +36,15 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
|
|
|
36
36
|
t.is(countOf('Scene', obs), 2)
|
|
37
37
|
t.is(countOf('Transform', obs), 2)
|
|
38
38
|
t.is(countOf('Shape', obs), 2)
|
|
39
|
+
t.is(countOf('DEF', obs), 0)
|
|
39
40
|
t.is(countOf('IndexedTriangleSet', obs), 2)
|
|
40
41
|
t.is(countOf('Coordinate', obs), 1)
|
|
41
42
|
t.is(countOf('Color', obs), 1)
|
|
42
43
|
|
|
43
44
|
const geom3 = colors.colorize([0.5, 1, 0.5, 1.0], transforms.center({ relativeTo: [5, 5, 5] }, primitives.cube()))
|
|
45
|
+
geom2.id = geom3.id = 'g23'
|
|
44
46
|
|
|
45
|
-
results = serializer.serialize({metadata: false}, geom2, geom3)
|
|
47
|
+
results = serializer.serialize({ metadata: false }, geom2, geom3)
|
|
46
48
|
t.is(results.length, 1)
|
|
47
49
|
|
|
48
50
|
obs = results[0]
|
|
@@ -54,6 +56,7 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
|
|
|
54
56
|
t.is(countOf('Created by JSCAD', obs), 1)
|
|
55
57
|
t.is(countOf('Scene', obs), 2)
|
|
56
58
|
t.is(countOf('Shape', obs), 4)
|
|
59
|
+
t.is(countOf('DEF', obs), 2)
|
|
57
60
|
t.is(countOf('IndexedTriangleSet', obs), 4)
|
|
58
61
|
t.is(countOf('Coordinate', obs), 2)
|
|
59
62
|
// for color
|
|
@@ -61,7 +64,7 @@ test('serialize 3D geometry to X3D IndexedTriangleSet', (t) => {
|
|
|
61
64
|
t.is(countOf('Appearance', obs), 4)
|
|
62
65
|
// for RGB
|
|
63
66
|
t.is(countOf('diffuseColor="0.5 1 0.5"', obs), 1)
|
|
67
|
+
t.is(countOf('specularColor', obs), 1)
|
|
64
68
|
// for facets
|
|
65
69
|
t.is(countOf('normalPerVertex="false"', obs), 2)
|
|
66
|
-
|
|
67
|
-
})
|
|
70
|
+
})
|
package/tests/path2ToX3D.test.js
CHANGED
|
@@ -22,7 +22,7 @@ test('serialize 2D path to X3D Polyline2D', (t) => {
|
|
|
22
22
|
|
|
23
23
|
const path2 = primitives.arc({ center: [5, 5], endAngle: 45, segments: 16 })
|
|
24
24
|
|
|
25
|
-
results = serialize({metadata: false}, path2)
|
|
25
|
+
results = serialize({ metadata: false }, path2)
|
|
26
26
|
t.is(results.length, 1)
|
|
27
27
|
|
|
28
28
|
obs = results[0]
|
|
@@ -35,7 +35,7 @@ test('serialize 2D path to X3D Polyline2D', (t) => {
|
|
|
35
35
|
|
|
36
36
|
const path3 = colors.colorize([0, 0, 0], path2)
|
|
37
37
|
|
|
38
|
-
results = serialize({metadata: false}, path2, path3)
|
|
38
|
+
results = serialize({ metadata: false }, path2, path3)
|
|
39
39
|
t.is(results.length, 1)
|
|
40
40
|
|
|
41
41
|
obs = results[0]
|
|
@@ -50,6 +50,4 @@ test('serialize 2D path to X3D Polyline2D', (t) => {
|
|
|
50
50
|
t.is(countOf('Material', obs), 1)
|
|
51
51
|
t.is(countOf('diffuseColor', obs), 0)
|
|
52
52
|
t.is(countOf('emissiveColor', obs), 1)
|
|
53
|
-
|
|
54
53
|
})
|
|
55
|
-
|