@jscad/regl-renderer 2.6.7 → 3.0.0-alpha.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +5 -189
  2. package/README.md +21 -11
  3. package/demo-cli.js +20 -16
  4. package/demo-web.js +6 -4
  5. package/demo.es.html +236 -0
  6. package/demo.html +21 -15
  7. package/dist/jscad-regl-renderer.es.js +13 -0
  8. package/dist/jscad-regl-renderer.min.js +13 -335
  9. package/package.json +41 -16
  10. package/rollup.config.js +27 -0
  11. package/src/bound-utils/boundingBox.js +1 -2
  12. package/src/bound-utils/boundingSphere.js +4 -5
  13. package/src/bound-utils/computeBounds.js +4 -6
  14. package/src/bound-utils/computeBounds.test.js +2 -2
  15. package/src/cameras/camera.js +15 -19
  16. package/src/cameras/index.js +8 -4
  17. package/src/cameras/orthographicCamera.js +4 -6
  18. package/src/cameras/perspectiveCamera.js +7 -9
  19. package/src/controls/index.js +6 -0
  20. package/src/controls/orbitControls.js +18 -27
  21. package/src/{geometry-utils-V2 → geometry-utils-V3}/entitiesFromSolids.js +7 -9
  22. package/src/{geometry-utils-V2 → geometry-utils-V3}/entitiesFromSolids.test.js +4 -4
  23. package/src/geometry-utils-V3/geom2ToGeometries.js +57 -0
  24. package/src/{geometry-utils-V2 → geometry-utils-V3}/geom2ToGeometries.test.js +16 -12
  25. package/src/{geometry-utils-V2 → geometry-utils-V3}/geom3ToGeometries.js +3 -5
  26. package/src/{geometry-utils-V2 → geometry-utils-V3}/geom3ToGeometries.test.js +2 -2
  27. package/src/{geometry-utils-V2 → geometry-utils-V3}/path2ToGeometries.js +4 -5
  28. package/src/{geometry-utils-V2 → geometry-utils-V3}/path2ToGeometries.test.js +2 -2
  29. package/src/index.js +5 -20
  30. package/src/rendering/commands/drawAxis/index.js +2 -4
  31. package/src/rendering/commands/drawExps/drawConnector/arcGeo.js +1 -3
  32. package/src/rendering/commands/drawExps/drawConnector/index.js +5 -7
  33. package/src/rendering/commands/drawExps/drawMesh.js +2 -4
  34. package/src/rendering/commands/drawExps/drawMeshNoNormals.js +2 -4
  35. package/src/rendering/commands/drawExps/drawNormals.js +2 -4
  36. package/src/rendering/commands/drawExps/drawNormals2.js +2 -4
  37. package/src/rendering/commands/drawGrid/{index.js → makeDrawGrid.js} +2 -4
  38. package/src/rendering/commands/drawGrid/{multi.js → makeDrawMultiGrid.js} +5 -5
  39. package/src/rendering/commands/drawLines/colorOnlyShaders.js +2 -2
  40. package/src/rendering/commands/drawLines/index.js +9 -7
  41. package/src/rendering/commands/drawLines/meshShaders.js +3 -3
  42. package/src/rendering/commands/drawLines/vColorShaders.js +3 -3
  43. package/src/rendering/commands/drawMesh/colorOnlyShaders.js +2 -2
  44. package/src/rendering/commands/drawMesh/index.js +8 -7
  45. package/src/rendering/commands/drawMesh/meshShaders.js +3 -3
  46. package/src/rendering/commands/drawMesh/vColorShaders.js +3 -3
  47. package/src/rendering/commands/index.js +11 -0
  48. package/src/rendering/render.js +10 -10
  49. package/src/rendering/renderContext.js +2 -4
  50. package/src/rendering/renderDefaults.js +9 -11
  51. package/src/utils.js +3 -6
  52. package/src/geometry-utils-V1/cagToGeometries.js +0 -52
  53. package/src/geometry-utils-V1/csgToGeometries.js +0 -220
  54. package/src/geometry-utils-V1/entitiesFromSolids.js +0 -75
  55. package/src/geometry-utils-V2/geom2ToGeometries.js +0 -66
@@ -1,220 +0,0 @@
1
- const vec3 = require('gl-vec3')
2
-
3
- const { toArray } = require('@jscad/array-utils')
4
-
5
- /**
6
- * convert a CSG from csg.js to an array of geometries with positions, normals, colors & indices
7
- * typically used for example to display the csg data in a webgl wiever
8
- * @param {Array} csgs single or an array of CSG object
9
- * @param {Object} options options hash
10
- * @param {Boolean} options.smoothLighting=false set to true if we want to use interpolated vertex normals
11
- * this creates nice round spheres but does not represent the shape of the actual model
12
- * @param {Float} options.normalThreshold=0.349066 threshold beyond which to split normals // 20 deg
13
- * @param {String} options.faceColor='#FF000' hex color
14
- * @returns {Object} {indices, positions, normals, colors}
15
- */
16
- const csgToGeometries = (csgs, options) => {
17
- const defaults = {
18
- smoothLighting: false, // set to true if we want to use interpolated vertex normals this creates nice round spheres but does not represent the shape of the actual model
19
- normalThreshold: 0.349066, // 20 deg
20
- faceColor: [1, 0.4, 0, 1]// default color
21
- }
22
- const { smoothLighting, normalThreshold, faceColor } = Object.assign({}, defaults, options)
23
- const faceColorRgb = faceColor === undefined ? undefined : normalizedColor(faceColor) // TODO : detect if hex or rgba
24
-
25
- const convert = (csg) => {
26
- const geometries = []
27
-
28
- const positions = []
29
- const colors = []
30
- const normals = []
31
- const indices = []
32
-
33
- // flag for transparency
34
- let isTransparent = false
35
-
36
- const polygons = csg.canonicalized().toPolygons()
37
-
38
- /* let positions = new Float32Array(faces * 3 * 3)
39
- let normals = new Float32Array(faces * 3 * 3) */
40
-
41
- let normalPositionLookup = []
42
- normalPositionLookup = {}
43
- let tupplesIndex = 0
44
-
45
- for (let i = 0; i < polygons.length; i++) {
46
- const polygon = polygons[i]
47
-
48
- const color = polygonColor(polygon, faceColorRgb)
49
- const rawNormal = polygon.plane.normal
50
- const normal = [rawNormal.x, rawNormal.y, rawNormal.z]
51
-
52
- if (color[3] !== 1) {
53
- isTransparent = true
54
- }
55
-
56
- const polygonIndices = []
57
- // we need unique tupples of normal + position , that gives us a specific index (indices)
58
- // if the angle between a given normal and another normal is less than X they are considered the same
59
- for (let j = 0; j < polygon.vertices.length; j++) {
60
- let index
61
-
62
- const vertex = polygon.vertices[j]
63
- const position = [vertex.pos.x, vertex.pos.y, vertex.pos.z]
64
-
65
- if (smoothLighting) {
66
- const candidateTupple = { normal, position }
67
- const existingTupple = fuzyNormalAndPositionLookup(normalPositionLookup, candidateTupple, normalThreshold)
68
- if (!existingTupple) {
69
- const existingPositing = normalPositionLookup[candidateTupple.position]
70
- const itemToAdd = [{ normal: candidateTupple.normal, index: tupplesIndex }]
71
- if (!existingPositing) {
72
- normalPositionLookup[candidateTupple.position] = itemToAdd
73
- } else {
74
- normalPositionLookup[candidateTupple.position] = normalPositionLookup[candidateTupple.position]
75
- .concat(itemToAdd)
76
- }
77
- index = tupplesIndex
78
- // normalPositionLookup.push(candidateTupple)
79
- // index = normalPositionLookup.length - 1
80
- if (faceColor !== undefined) {
81
- colors.push(color)
82
- }
83
- normals.push(normal)
84
- positions.push(position)
85
- tupplesIndex += 1
86
- } else {
87
- index = existingTupple.index
88
- }
89
- } else {
90
- if (faceColor !== undefined) {
91
- colors.push(color)
92
- }
93
- normals.push(normal)
94
- positions.push(position)
95
- index = positions.length - 1
96
- }
97
-
98
- // let prevcolor = colors[index]
99
- polygonIndices.push(index)
100
- }
101
-
102
- for (let j = 2; j < polygonIndices.length; j++) {
103
- indices.push([polygonIndices[0], polygonIndices[j - 1], polygonIndices[j]])
104
- }
105
-
106
- // if too many vertices or we are at the end, start a new geometry
107
- if (positions.length > 65000 || i === polygons.length - 1) {
108
- // special case to deal with face color SPECICIALLY SET TO UNDEFINED
109
- if (faceColor === undefined) {
110
- geometries.push({
111
- indices,
112
- positions,
113
- normals,
114
- isTransparent
115
- })
116
- } else {
117
- geometries.push({
118
- indices,
119
- positions,
120
- normals,
121
- colors,
122
- isTransparent
123
- })
124
- }
125
- }
126
- }
127
- return geometries
128
- }
129
-
130
- csgs = toArray(csgs)
131
- const geometriesPerCsg = csgs.map(convert)
132
-
133
- return geometriesPerCsg
134
- }
135
-
136
- /** determine if input is a hex (color) or not
137
- * @param {Object} object a string, array, object , whatever
138
- * @returns {Boolean} wether the input is a hex string or not
139
- */
140
- const isHexColor = (object) => {
141
- if (typeof sNum !== 'string') {
142
- return false
143
- }
144
- return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(object)
145
- }
146
-
147
- // modified from https://stackoverflow.com/questions/21646738/convert-hex-to-rgba
148
- const hexToRgbNormalized = (hex, alpha) => {
149
- hex = hex.replace('#', '')
150
- const r = parseInt(hex.length === 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16)
151
- const g = parseInt(hex.length === 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16)
152
- const b = parseInt(hex.length === 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16)
153
- return (alpha ? [r, g, b, alpha] : [r, g, b, 255]).map((x) => x / 255)
154
- }
155
-
156
- /** outputs a normalized [0...1] range, 4 component array color
157
- * @param {} input
158
- */
159
- const normalizedColor = (input) => {
160
- if (isHexColor(input)) {
161
- return hexToRgbNormalized(input)
162
- } else if (Array.isArray(input) && input.length >= 3) {
163
- input = input.length < 4 ? [input[0], input[1], input[2], 1] : input.slice(0, 4)
164
- if (input[0] > 1 || input[1] > 1 || input[2] > 1) {
165
- return input.map((x) => x / 255)
166
- }
167
- return input
168
- }
169
- }
170
-
171
- /**
172
- * return the color information of a polygon
173
- * @param {Object} polygon a csg.js polygon
174
- * @param {Object} faceColor a hex color value to default to
175
- * @returns {Array} `[r, g, b, a]`
176
- */
177
- const polygonColor = (polygon, faceColor) => {
178
- let color = faceColor
179
-
180
- if (polygon.shared && polygon.shared.color) {
181
- color = polygon.shared.color
182
- } else if (polygon.color) {
183
- color = polygon.color
184
- }
185
- // opaque is default
186
- if (color !== undefined && color.length < 4) {
187
- color.push(1.0)
188
- }
189
- return color
190
- }
191
-
192
- /**
193
- * determine if the two given normals are 'similar' ie if the distance/angle between the
194
- * two is less than the given threshold
195
- * @param {Array} normal a 3 component array normal
196
- * @param {Array} otherNormal another 3 component array normal
197
- * @returns {Boolean} true if the two normals are similar
198
- */
199
- const areNormalsSimilar = (normal, otherNormal, threshold) => vec3.distance(normal, otherNormal) <= threshold
200
- // angle computation is too slow but actually precise
201
- // return vec3.angle(normal, otherNormal) <= threshold
202
-
203
- const fuzyNormalAndPositionLookup = (normalPositionLookup, toCompare, normalThreshold = 0.349066) => {
204
- const normalsCandidates = normalPositionLookup[toCompare.position]
205
- if (normalsCandidates) {
206
- // normalPositionLookup[toCompare.position] = normalPositionLookup[toCompare.position].concat([toCompare.normal])
207
- // get array of normals with same position
208
- for (let i = 0; i < normalsCandidates.length; i++) {
209
- const normal = normalsCandidates[i].normal
210
- const similarNormal = areNormalsSimilar(normal, toCompare.normal, normalThreshold)
211
- const similar = similarNormal
212
- if (similar) {
213
- return { tupple: { position: toCompare.position, normal }, index: normalsCandidates[i].index }
214
- }
215
- }
216
- }
217
- return undefined
218
- }
219
-
220
- module.exports = csgToGeometries
@@ -1,75 +0,0 @@
1
- const mat4 = require('gl-mat4')
2
- const { flatten, toArray } = require('@jscad/array-utils')
3
- const csgToGeometries = require('./csgToGeometries')
4
- const cagToGeometries = require('./cagToGeometries')
5
- const computeBounds = require('../bound-utils/computeBounds')
6
-
7
- const entitiesFromSolids = (params, solids) => {
8
- const defaults = {
9
- meshColor: [0, 0.6, 1, 1],
10
- smoothNormals: true
11
- }
12
- const { meshColor, smoothNormals } = defaults
13
- // const defaultColor = params.rendering.meshColor
14
- solids = toArray(solids)
15
- // warning !!! fixTJunctions alters the csg and can result in visual issues ??
16
- // .fixTJunctions()
17
- // cachedSolids = solids
18
- // const start = performance.now()
19
- const entities = solids.map((solid) => {
20
- let geometry
21
- let type
22
- if ('sides' in solid) {
23
- type = '2d'
24
- geometry = cagToGeometries(solid, { color: meshColor })
25
- } else if ('polygons' in solid) {
26
- type = '3d'
27
- geometry = csgToGeometries(solid, {
28
- smoothLighting: smoothNormals,
29
- normalThreshold: 0.3,
30
- faceColor: meshColor
31
- })//, normalThreshold: 0})
32
- }
33
- // geometry = flatten(geometries)// FXIME : ACTUALLY deal with arrays since a single csg can
34
- // generate multiple geometries if positions count is >65535
35
- geometry = flatten(geometry)[0]
36
-
37
- // bounds
38
- const bounds = computeBounds({ geometry })// FXIME : ACTUALLY deal with arrays as inputs see above
39
-
40
- // transforms: for now not used, since all transformed are stored in the geometry
41
- // FIXME : for V2 we will be able to use the transfors provided by the solids directly
42
- const matrix = mat4.identity([])
43
-
44
- const transforms = {
45
- matrix
46
- /* const modelViewMatrix = mat4.multiply(mat4.create(), model, props.camera.view)
47
- const normalMatrix = mat4.create()
48
- mat4.invert(normalMatrix, modelViewMatrix)
49
- mat4.transpose(normalMatrix, normalMatrix)
50
- return normalMatrix */
51
- }
52
-
53
- const visuals = {
54
- drawCmd: 'drawMesh',
55
- show: true,
56
- color: meshColor,
57
- transparent: geometry.isTransparent, // not sure
58
- useVertexColors: true
59
- }
60
-
61
- const entity = {
62
- type,
63
- geometry,
64
- transforms,
65
- bounds,
66
- visuals,
67
- isTransparent: geometry.isTransparent
68
- }
69
- return entity
70
- })
71
- // }
72
- return entities
73
- }
74
-
75
- module.exports = entitiesFromSolids
@@ -1,66 +0,0 @@
1
- const mat4 = require('gl-mat4')
2
-
3
- const maxIndex = Math.floor(65535 / 2) // two vertices per segment
4
-
5
- /*
6
- * Convert the given solid into one or more geometries for rendering.
7
- * @param {Object} options - options for conversion
8
- * @param {Array} options.color - RGBA of solid
9
- * @param {geom2} solid - the solid to convert
10
- * @return {Array} list of new geometries
11
- */
12
- const geom2ToGeometries = (options, solid) => {
13
- let { color } = options
14
-
15
- const sides = solid.sides
16
- if (sides.length === 0) return []
17
-
18
- if ('color' in solid) color = solid.color
19
- const isTransparent = (color[3] < 1.0)
20
- const colors = []
21
- const numgeometries = Math.floor(sides.length / (maxIndex)) + 1
22
-
23
- const addColor = (startColor, endColor) => {
24
- // each line needs 2 colors: startColor and endColor
25
- // endColor is optional
26
- colors.push(startColor, endColor || startColor)
27
- }
28
-
29
- const geometries = []
30
- for (let g = 0; g < numgeometries; g++) {
31
- const offset = g * maxIndex
32
- const endset = Math.min(offset + maxIndex, sides.length)
33
- const positions = []
34
-
35
- for (let i = offset; i < endset; i++) {
36
- const side = sides[i]
37
- if (side.color) {
38
- // backfill colors, so colors array is not used unless at least one side has color defined
39
- if (colors.length === 0 && positions.length > 0) {
40
- const toFill = positions.length
41
- for (let j = 0; j < toFill; j++) {
42
- colors.push(color) // push default color
43
- }
44
- }
45
- // shader actually allows for gradient on the lines by design
46
- addColor(side.color, side.endColor)
47
- } else if (colors.length) {
48
- addColor(color)
49
- }
50
- positions.push([side[0][0], side[0][1], 0])
51
- positions.push([side[1][0], side[1][1], 0])
52
- }
53
- // assemble the geometry
54
- const normals = positions.map((x) => [0, 0, -1])
55
- const indices = positions.map((x, i) => i)
56
- const transforms = solid.transforms ? mat4.clone(solid.transforms) : mat4.create()
57
-
58
- // FIXME positions should be Float32Array buffers to eliminate another conversion
59
- // FIXME normals should be Float32Array buffers to eliminate another conversion
60
- // FIXME indices should be Uint16Array buffers to eliminate another conversion
61
- geometries.push({ type: '2d', positions, normals, indices, transforms, color, colors, isTransparent })
62
- }
63
- return geometries
64
- }
65
-
66
- module.exports = geom2ToGeometries