forked from curv3d/curv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTODO
933 lines (848 loc) · 40.1 KB
/
TODO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
Big Themes:
1. language, subcurv, libraries
2. shape rep: pixl/voxl, v-rep, alg surf, exact offset, non-affine xforms
3. rendering: camera, shading, materials
4. export
5. visual programming: web GUI, WASM, graphical values
6. user engagement: documentation, web site, prebuilt exes
`render <render-record> <shape>` -- adds pickers for render params
* depends on Abstract Value proposal
Redesigned Rendering Parameters:
* camera
* shading (towards a universal, parameterized shading model)
* sf1: apply lighting on ray hit
* background colour: solid colour, or pattern (2D & 3D cases)
* shadows: none, ambient or traced. Can traced be made orthogonal to sf1?
Perhaps ambient occlusion is an independent term.
* light sources.
* Point sources. How to optimize lighting code: 1 source or multiple,
white light or coloured?
* Ambient. This should just be a single value.
* open source, F-Rep/SDF, universal shading model, preferably PBM:
* mTec (PBM, 1 light source, GL4.3), FragM?,
* Blender Eevee "Principled BSDF", aka PBM, compatible with Renderman,
Unreal Engine, etc. Real-time rendering. OpenGL 3.3.
https://docs.blender.org/manual/en/latest/render/shader_nodes/shader/principled.html
* tracing
Symbols:
* SC support for symbols
* variant_picker[#foo, #bar]
* align{x: #centre}
* make_symbol("foo") == #foo. Rationale: normalize JSON import.
Structures:
* struct!index, where struct is a list, string or record. Eg, {a:1}!#a
* 'symbol-expr => expr' as a field generator
* numeral patterns (positive, negative, infinite)
Mesh export:
* fix bug: treat Curv units as millimeters when generating X3D format.
* add support for full colour WRL format.
v0.5 Planning
-------------
* fix Intel GPU bug. v0.4.1
* Compiler/IR/VM changes for new features:
* `a[i] := x`, a[[X,Y]] := [x,y]
Assignment_Action::locative_, Locative::store_value()
* image import
* SC Refactor/Optimizer: common subexpression elimination, constant folding,
partial evaluation. AMD Mesa support. >Compiler changes.
* SubCurv: piecewise functions, functions with record & tuple arguments,
partial evaluation, matrix multiplication. >SC Refactor.
* Parametric shapes:
* constructor returns another parametric record.
* `curv -D param=value parametric.curv`
* colour_picker: convert between sRGB in the uniform variable,
and linear RGB in the Curv parameter.
* Unit testing for reactive values.
* Finish implementing reactive values.
* geometry engine/shape representation:
* image import
* voxel import/export
* alpha channel in colour functions
* `time` is a global reactive variable
* Ray-casting non-Lipschitz implicit surfaces
* Smart STL export with edge detection: try SHREC, compare to Libfive
* SHREC uses NRRD voxel data as input. >Voxel i/o.
* shape library
* noise library, >SC piecewise functions.
* fractals
* polyhedra
* WASM executable. Try Cheerp (faster smaller code than Emscripten)
* language:
* `pattern : expr`
* `a[i] := x`, a[[X,Y]] := [x,y]
Assignment_Action::locative_, Locative::store_value()
* random{,2,3,4}(seed)
* recursive piecewise functions
* Package manager; packages are referenced using URLs.
* Improved Viewer UI that can zoom in to 3D fractals.
* User defined lighting models can be written in Curv. >SC Refactor.
'Viewer' value can override fragment shader, maybe other viewer behaviour.
* Improved web site. cell-lang.org, hazel.org, racket-lang.org,
* REPL
* Interrupt a running program
* fix syntax colouring
* fix completion
* multi-line definitions (copypasta from a source file)
* REPL in live edit mode
* debugger
* v0.4 leftovers:
* Assignment statement:
* docs:
* Statements: quick characterization of assignment restrictions.
There is a statement language and an expression language. Local
variables are mutable within the statement language but immutable
within the expression language, which has pure functional semantics.
What we do support: unconditional assignment, conditional assignment,
iterative assignment within the body of a loop, a[i]:=x
* There are no procedures, only pure functions. Curv has imperative
features but is not a full procedural programming language.
* Relevance of ISPiaPFL to other DSLs: OpenSCAD, Jsonnet, Nix, etc.
* debug actions ignored by SC compiler
* no actions in a let clause. `a:=b` gives an error: did you mean `a=b`?
* no recursive definitions in a do clause. a=b error: did you mean a:=b?
* CLI token colouring: New string escapes. Special colour for string-escapes.
Bad token handling.
* better unit tests:
* cli tests, curvc
* detect console output from curv.curv
* full sc_test suite
Big Items
* graphical value pickers in the viewer
* standard libraries for some important techniques
* better documentation, a web site
More Big Items
* a GUI application
* Homebrew package, Mac Linux Windows
* a web GUI, a wasm executable
* common subexpression optimization and partial evaluation
* Stratasys J750 support
Language TODO:
* `a[i] := x` -- adds to ISPiaPFL story.
Assignment_Action::locative_, Locative::store_value()
* Shape Compiler: matrix multiplication
* mantissa(num), random{,2,3,4}(seed)
* Metafunctions are values, can only be called if constant. Remove Meaning.
TODO (value pickers impl)
* `(parametric param body) arg` should return another parametric record.
* BUG: While compiling a pattern, parameters are added to the scope as they are
found. This same uncompleted scope is used for analyzing subexpressions,
such as the predicate in pat::pred. Use parent environment instead.
* Precompute uniform ids, before entering main loop.
* Support all SC-compatible expressions over reactive values.
* Should picker predicates restrict their range to something more precise
than a SC_Type?
* Support multiple viewer windows.
* 'cube;sphere' in REPL opens 2 Viewers labelled REPL[0], REPL[1].
* The live edit mode has a REPL. There is a live-edit viewer (labelled with
source file name), and one or more REPL viewers.
Current TODO List:
* fix Power Saver button to work correctly
* graphical value pickers
* add more picker types
* `term` proposal
* -o glsl
* Refactor:
* batch mode uses curv::import, can input any source file type
* refactor Viewer + View_Server. View_Server should not know that Viewer uses
GLFW. Maybe Viewer has a single event queue that includes set_shape and quit
* Viewer_Opts
* mesh: geom::mesh_write & Mesh_Write_Opts
* dfmt -> <libcurv/format.h>
* Location ctor takes Shared<const Source>
* Source should contain a prefix length (don't put this in Scanner).
Location{Source} is a location spanning the entire program (mod prefix)
Program::location() uses above in case where program not compiled.
Program no longer needs to know about Scanner::ptr_.
* geom uses System::console(), not std::cerr
* remove global variables from geom::viewer
* Image Export.
* transparent background (exports RGBA, not RGB)
* speed up -O animate= (compile shape once)
* use OpenGL FBO to avoid unreliable semantics of framebuf of hidden window.
* macOS: don't create a menu bar during image export. GLFW enhancement?
* linux: don't use X server during image export. EGL?
* Image Import.
* file "foo.png" imports the PNG file, returns a shape value (no GL support).
* We return a standard record object with magic values in dist, colour.
* bbox: The smallest rectangle that fully covers a unit circle.
* dist: euclidean rectangle SDF for the bbox.
* colour: Initially, red (a stub). Bilinear interpolation.
* Should PNG files appear as source files in the stack trace?
Ideas:
* Ray-casting non-Lipschitz implicit surfaces:
* grid-tracer: -Otracer=grid (default sphere).
glsl-function-grapher by Michael Firmin on github
* http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.417.5616&rep=rep1&type=pdf
Real-Time Ray-Tracing of Implicit Surfaces on the GPU
* awesome progressive rendering for SDFs:
https://nshelton.github.io/vr/fractals/2017/12/30/RTA.html
* http://erleuchtet.org/~cupe/permanent/enhanced_sphere_tracing.pdf (2014)
* http://matter.media.mit.edu/publications/article/data-driven-material-modeling
Data-Driven Material Modeling for 3D-Printing of Materially Heterogeneous Objects
* Replace 'not an operation' analysis time error with useful message.
* Mesa driver bugs. Install latest Nouveau driver, report bugs to Mesa3D.org
* Install Ubuntu 18.04. Bleeding edge Mesa + 16.04 is likely a bad idea.
Also, the 18.04 version of Nouveau might work better than a black screen.
Language:
* better GLSL transliteration:
* v[X] := x; v[[X,Y,Z]] := v3;
* matrices
* all of the GLSL numeric functions
* better stdlib:
* mixed a=/a: record literals
* greatly expanded, modular stdlib
* packages, maybe `lib` if packages are delayed
# Release 0.2
Big Ideas:
* Ease of Use: funcall errors, function help, tutorial
* RSDF and RSIF (voxel) import and export
* Mesh Import via RSDF
* sharp and fractal Mesh Export
Ease of Use:
* Better error messages for bad function calls.
'f a b c' is a function call with 3 arguments.
Error message mentions name of function and ordinal number of bad argument,
and gives required type of argument if a parameter pattern is available.
* Too few arguments: currying returns a function, later function is used in
non-function context. At this point, we can report a missing argument.
* Too many arguments: a non-function is used in the function position of a
function call. If the non-function expression is a function call, then
report too many arguments.
* Function value contains extra information. Name of function and # of
arguments already applied to the function of that name (for a partial
application).
* in CLI, function value prints as usage info.
* Tutorial.
* Give beginning users a useful mental model.
* Explain advantages of Curv over competing systems.
* Pre-built executables.
Mesh Import:
* RSDF import and export.
* mesh to RSDF tool
look at https://github.com/InteractiveComputerGraphics/Discregrid
Mesh Export:
* smooth export: the current default.
* sharp export:
* refactor: abstract STL/OBJ file writing code as class Mesh_Export
* quick&dirty DC, with documented limitations. Test with Menger.
* fractal export: convolution & super sampling, test with MandelBulb.
* Mandelbulb export algorithm:
* export as 2048^3 density grid, 1 bit per voxel
* resample down to 512^3 density grid, 8 bits per voxel
* export as 2048^3 density grid, 1 bit per voxel.
* 3D median filter, 3x3x3 neighbourhood, zero padding at grid boundaries.
This means: find median of the 9 values: sort and take middle value.
* trilinear resampling down to 1024^3.
This means: take average of each 2*2*2 partition.
* another 3D median filter.
* trilinear resampling down to 512^3.
* marching cubes
* density grid export to RSIF. Compare to Trocola Mandelbulb voxels w. Inviwo.
Intensity Fields:
* 3D medical images use voxel density grids (which are just sampled "intensity
fields"). Isosurfaces are extracted to identity features (eg, bone is denser
than other tissues).
* In Curv, intensity fields are first class values. I could add new operations:
* Import and export of intensity fields as voxel grids.
* Convert density grid to SDF by extracting a level set.
* Convert SDF to density grid by sampling and antialiasing.
Language:
* Packages
# Release 0.1: "Mesh Export"
curv -o stl -O name=value file.curv >file.stl
We'll use a 2 pass algorithm: a grid based mesher, followed by a mesh
simplifier/optimizer.
Report an error if an unrecognized -O option is used.
parse_params(params, {
{"adaptive", adaptive_str, ""},
{"vsize", vsize_str, ""},
});
An ideal meshing algorithm has these features:
* It produces a defect free mesh.
* It performs sharp feature detection, so that the edges and corners
of a cube are sharp.
* It is adaptive. It uses lots of small triangles in regions of high
curvature. It uses fewer larger triangles in areas of low curvature.
Flat surfaces are rendered with a minimum number of triangles (eg,
a cube is rendered as 6 quads or 12 triangles,
regardless of the voxel size).
* It avoids generating needle shaped triangles, which can become degenerate
in the limiting case.
* There is only one parameter, an error tolerance.
I intend to implement this ideal meshing algorithm using two passes:
* First, a grid based mesher creates an initial mesh, which is defect free
and preserves sharp features.
* Second, a mesh optimizer simplifies the mesh and improves triangle quality,
controlled by an error tolerance and by querying the distance function,
without introducing defects, preserving sharp features.
Mesher:
* Currently, a marching cubes variant from openvdb. No sharp feature detection.
* Later, add 'Dual Marching Tetrahedra' (Simplicial Partition of Multiresolution
Grids).
Simplifier:
* Currently, using MeshLab "quadric edge collapse".
* Try: github.com/sp4cerat/Fast-Quadric-Mesh-Simplification
MIT licence, all code in a single header, used by other projects.
Limitations: speed over quality, controlled by target # of triangles.
* A better algorithm would query the distance field to ensure that new vertices
are on the isosurface, and would be controlled by an error tolerance.
Full Colour mesh export:
We export X3D files, accepted by Shapeways for "full colour sandstone",
which supports 3 ways to specify colour.
* Currently, we support 'per face' colours. Easy, less detail.
* There is also 'per vertex' colour. Probably rendered using interpolation,
better for gradients. Not mentioned by Shapeways documentation.
* As one or more separate UV texture map files (JPG or PNG, total resolution
< 2048^2). Geometry stored in X3D file. All files zipped together.
* "Least Squares Conformal Maps for Automatic Texture Atlas Generation"
https://www.cs.jhu.edu/~misha/Fall09/Levy02.pdf
Multi-Material models:
For multi-head FDM printers.
* Introduce a 'material' function. Or map colour to a material id.
* While generating mesh, partition model at material boundaries.
Some meshing algorithms (like DC) directly support this.
* Output to 3mf file format.
More future work:
* Speed up mesh generation.
* Provide an integrated, interactive GUI for tweaking the mesh generation
parameters until you get a good result.
* Provide a way to store machine-readable meshing parameters in a shape.
* Provide a way to mark a shape as mesh-only (it can't be visualized using
the standard sphere-tracing viewer, because the distance function is
not Lipschitz-continuous). The curv command will automatically preview
these shapes by constructing a mesh.
* In live mode, the Viewer window needs to dynamically switch between showing
a mesh and showing a fragment shader.
## 0.0 TODO List
0.0 Roadmap:
* New version of shape library, based on Shape_Atlas and Colour_Atlas.
Don't need new features, just refine the API, make it more useable.
* Tweak the core language, based on experience of writing and using the
new shape library.
* Documentation for core language and shape library.
* Export to STL, using marching cubes and OpenCL.
* High priority bug fixes.
* Meta: use https://opensource.guide/
* => First public release with a stable API.
Next changes:
* fix 3D lighting model.
* fix sphere tracer.
* remove atan2. phase is a rank 1 tensorized operation.
* mat2, mat3 and mat4 types in SC.
Proposed change: `include lib.shape` required to access shape library.
* Pros: as a temporary measure, it protects users against future redesigns
of the shape library, as I'll create a new library and maintain the old API.
* Cons: adds complexity to Curv scripts. Instead of
cube
you need
cube
where include lib.shape;
or
let include lib.shape;
in cube
3D Viewer: "arcball rotation" to replace my ad-hoc mouse rotation code.
Pattern project:
* cast patterns
* binder patterns
* features: [a,...b], {a,...}
* eg, {a,b,c,...} = file "foo.curv" is like from foo import a,b,c in Python.
* eg, f[a,...b]= is like f(a:b)= in Haskell.
* id && pat
* pat1 || pat2 -- eg, [x,y] || [x,y,0]
* SC: record patterns, predicate patterns
* `var` definitions and sequential assignments:
* `var pattern := expr` and `pattern := expr` *is* supported.
After `var (is_num x) := foo`, do subsequent assignments to `x`
enforce the is_num predicate? I'd say no, but then this is potentially
confusing.
* `f x := expr` function definition syntax is *not* supported.
* `a[i] := expr` *is* supported for assignments only.
* optional features: id==expr, pat if cond
Code cleanup:
* unit tests for: CLI supports compound definitions
* unit tests for: SC error messages
* clean up Recursive_Scope::analyse_unit
* clean up Record_Pattern::exec
* add std::move to curv namespace
Tensors:
* rank? Like ArrayDepth[t] in Mathematica?
* dimensions? Like Dimensions[t] in Mathematica?
weird error message: Should underline the default value expression.
curv> {a: [x,y] = []} = {}
ERROR: at field .a: list has wrong size: expected 2, got 0
line 1(columns 19-20)
{a: [x,y] = []} = {}
^-
weird error message: The "at field .colour" qualifier really applies to the
final item in the stack trace.
ERROR: at field .colour: this list constructor does not support the Shape Compiler
file "../examples/assert.curv", line 6(columns 24-25)
colour p : [1-bit(f()), bit(f()), 0],
^-
file "../examples/assert.curv", line 21(columns 1-30)
sc_assert(()->(fact 5 == 120))
^-----------------------------
-------------------------
Circumratio project:
Regular polytopes are prototypical shapes, with `map` and `circumratio` fields.
Primitive shapes from Conway notation:
* `prism n` -- prototypical version has inscribed unit sphere.
Note `prism 4` == `cube`.
* `antiprism n` -- prototypical version has inscribed unit sphere
* `pyramid n` -- prototypical version has inscribed unit sphere.
`pyramid 3` == `tetrahedron`. What is the base diameter/height ratio for
values of n > 3? As n approaches infinity, the pyramid approaches a cone.
* Ratio of pyramid height to diameter of inscribed circle of base is
1+1/3 to sqrt(8/9): 1.333333 to 0.942809. This gives a tall skinny cone.
* Ratio of pyramid height to diameter of circumscribed circle of base
is 1+1/3 to 2*sqrt(8/9). This gives a squatter cone that I like better.
* Smallest volume that circumscribes a unit sphere. Needs calculus.
* Maybe `cylinder`, `cone`.
Fix bug: {x=1} == {x:1} should be true.
SubCurv:
* call nonconstant functions
* print, assert, warning, error are ignored in GL.
* && || if use lazy evaluation
Shape Atlas: look at:
* http://grasshopperprimer.com/en/1-foundations/1-3/2_working-with-attractors.html
FXAA: cheap, simple anti-aliasing.
https://www.kotaku.com.au/2011/12/what-is-fxaa/
SMAA also good, may be faster, may be higher quality (due to temporal sampling).
Both work by post-processing the display buffer.
Weld, a Stanford research project, enables efficient composition of parallel
libraries on a single CPU or GPU. The usual way of composing libraries, through
function calls that exchange data through memory, can create order-of-magnitude
slowdowns. In contrast, Weld can transparently speed up applications using
NumPy, Pandas and TensorFlow by up to 30x through a novel API that lets it
optimize across the library calls used in each program.
-------------------------
BUG: bad Web GLSL (testing mandelbrot in shadertoy.com in Chrome on macOS):
float r1 = 1.0/0.0;
-- Divide by zero during constant folding
float r1 = 1e9999; // an alternative?
-- Float overflow
GLSL 4.1 and later support 1.0/0.0 to create infinity.
Before that is undefined behaviour.
Ideas:
* This works:
float zero = 0.0;
float r1 = 1.0/zero;
* No way to initialize a global variable 'inf', however.
* Compute infinity at run time, if it is an old version of GLSL.
* Rewrite the standard library to avoid outputting infinity. If it is output,
then set the GLSL version to 4.1.
BUG: Doesn't SC compile.
stereographic_projection plane = sphere 1 >> colourfield
((x,y,z)->plane.colour(x/(1-z), y/(1-z), 0));
display axes in 3D view
source reorganization:
* Split cmd/curv.cc into multiple source files
SubCurv:
* all math operations that are built-in SPIR-V operators
* `if_fast_case (C) E1 else E2`: E1 and E2 are equivalent, but E1 is faster
to compute if C is true. During SC compile, if C is a compile time constant,
pick E1 or E2, otherwise just emit E2.
* mat2, mat3, mat4
Viewer:
* HOME key resets view
* other ideas:
* SHIFT key constrains rotate and pan to one axis.
* Camera roll? Use ALT key + button1, button2 or scroll.
* not scroll, too imprecise.
* ALT + rotate button
* Maybe use keyboard for flight.
* up/down arrow: move eye forward/backward
* left/right arrow: rotate left/right around eye
library:
* blend operators
* positioning/alignment
* regular polytopes are specified using incircle radius.
`circumscale r RP` scales a regular polytope RP to specified circumcircle
or circumsphere radius r. RP stores its bounding circle/sphere radius.
curv:
* If SC compiler fails, or GLSL compiler fails, display an error message without
affecting what's currently displayed by the Viewer window.
3D viewer
* use bbox to ensure entire scene is visible
* zoom in on `cube 0.25`. WTF?
* bug: white is rendered as grey in a 3D shape interior. I prefer no lighting
transformation for interior points.
* The current sphere-tracer stops at distance 20 (hard coded). Use the bounding
box to compute a tmin and tmax value for a given ray (by intersecting the
bbox), or don't march at all if the ray doesn't intersect the bbox.
## Geometry
Math:
* Native 'trunc'? Isn't in WebGL, but is in later versions.
Use `#if __VERSION__` in SC code generator.
import, export PNG file.
basic documentation.
Ideas for 2D primitives:
OpenSCAD:
* polygon, text,
* hull, minkowski, mitred and rounded offset
* mitred offset is well defined for polytopes
* rounded offset is minkowski sum with sphere
* not all polytopes can be offset: http://mathoverflow.net/questions/206644/when-is-it-possible-to-shrink-a-polyhedron
* positioning/alignment
Antimony:
* text, 1 font only
* rounded rectangle(radius),
* blend(shape1,shape2,q), which is rounded-corner union for q>0&q<1.
* clearance(shape1,shape2,Num o) in which shape2 casts a "shadow" of thickness
`o` that is removed from shape1. Otherwise they are unioned.
* invert: subtract shape from its bounding box
* morph(s1,s2,weight) -- a kind of morph where there's no output unless the
shapes overlap
* offset(s,o) -- like inflate(s,o)
* shell(s,o) -- creates a shell of thickness o inside the perimeter of s
* 2D array (nx,ny,dx,dy,shape) -- repeats shapes in a grid pattern
* polar array(n, dx, dy, shape) -- repeat in a circular pattern
* deform:attract(shape, pt, Num r) -- warp shape so that it is pulled toward
the point with intensity r
* deform:repel -- see above
* 2D shear (shape, y0, y1, dx0, dx1) -- affine transform
* 2D cosine shear -- holy waviness!
* 2D function -- plot area under a function within a bbox
* map -- a shape and some functions for transforming X,Y,Z
* 2D cosine scale -- more waviness
* 2D taper
ImplicitCAD:
* regular polygon
* general polygon
* pack (size=[45,45], sep=2) { circle(10); circle(10); circle(10); circle(10); }
size of 2D box to pack objects in, separation between objects
* shell(w=width of shell) shape
* union, intersection, difference, square have a radius of rounding
# Nice To Have
* text (for debugging).
* a better sc_assert: multiple assertions, display text for each assertion.
sc_assert[["== works",()->t1==t2], ...]
* SC optimizer: hand-optimizing sample output reduced # of ops in main_dist
from 29 to 13 (16 fewer); exe size from 9928 to 9741 (187 fewer).
7574 in 'empty' shader, so 2354->2167, 12.6% fewer.
* improved error messages.
* <actual value>: not a list -- in Value::to etc.
* <actual argument to 'file'>: file can't be opened
* In At_Arg(), remove superfluous parens from arg expression
so that argument location is more precise.
* debugger
Create an interactive debugger, action to jump into the debugger,
debug command to dump a specified frame, showing exact contents of local
and non-local slots without evaluation.
* Lazy Modules:
Why?
* Make the language more expressive. Programs that now fail due to illegal
recursive reference will now succeed.
* Efficiency through deferred evaluation? Not for MVP.
Change the Module API so that Thunks are forced before Values escape.
I'll need to add Frame* or Context& arguments to provide exception context
if thunk forcing fails:
* in Module::print()
* in Module::begin()
* in Module::getfield()
I need a Context& for proper error messages, but I need a parent frame to
force a thunk. Maybe add `Frame* Context::get_frame()`. Won't work in SC
due to SC_Frames. Maybe Frame and SC_Frame share a common ancestor for
use in Context.
* Stdlib contains thunks. When are they forced?
* When stdlib is loaded. (As early as possible. Even for names that are
never referenced.)
* During analysis, in Builtin_Environ. The value is forced in the Namespace
object, which happens at most once.
* At runtime, in Constant (or Lazy_Constant). Problem: we'll make multiple
copies of the thunk then later force multiple copies. Fix?
Need to force a module slot before the value leaves the module.
Currently, all fields values are forced during module creation.
For true lazy modules, need to pass a Frame* through Ref_Value::getfield
and Module::get.
# Older Stuff
Live programming (curv -l):
* When curv -l is interrupted, the Viewer window should be closed.
* redraw if an included file changes. requires integration with libcurv.
* `fswatch` looks like a decent package on github (better than stat loop?).
https://github.com/emcrisostomo/fswatch/tree/master/libfswatch
Has both a CLI and a library with C and C++ bindings.
Supports all operating systems.
* `curv -l filename` has an interactive CLI for querying variables and
debugging. GNU readline has a callback-based API suitable for this:
rl_callback_handler_install etc.
2d subsystem: repetition operators, and others
Build up the standard library.
* There are many GLSL functions that ought to be supported by Curv.
* Some of them need to use the GLSL, not the Curv implementation.
Eg, GLSL `dot` is very efficient.
* Some GLSL functions are version dependent, like trunc.
* Hard coding this in C++ is tedious, can it be defined in `std.curv`?
* Maybe add GLSL metadata to a Curv function definition so that calls can be
translated to GLSL library calls.
* I'd like a peephole optimizer to recognize idioms like e^x and translate
them into more efficient/accurate operations like exp(x).
* The peephole optimizer could map idioms generated by inlining Curv functions
onto GLSL library functions.
Linear algebra:
pow(square_matrix,i),
determinant(square_matrix), inverse(square_matrix) -- difficult
ongoing research:
* list library
2D subsystem:
* polygon -- convex_polygon as Nef polygon, intersection of half planes
convex_polygon(vertices) -- vertices are in counterclockwise order, as this
seems to be the standard convention.
* align
* Repetition operators, which repeat a shape multiple or infinite times,
in constant time and memory, in accordance with some symmetry pattern.
These operators can be composed to describe more complex symmetries.
* row
* 7 frieze groups: https://en.wikipedia.org/wiki/Frieze_group
* grid
* 17 wallpaper groups: https://en.wikipedia.org/wiki/Wallpaper_group
* rotate tau/N, N copies
* rosette groups
* reflect
* glide reflection
* spiral -- not sure if this is symmetric -- might have trouble defining it?
http://www.mathematische-basteleien.de/spiral.htm
* The Symmetry of Things, orbifold notation
* An orbifold signature does not uniquely specify a repetition operator.
* Find a collection of ops that can be composed to generate
all the repetition patterns.
* pack or row
* crop
* crop(xmin=null,ymin=null,xmax=null,ymax=null)=...; // OpenSCAD style
* crop{xmin=null,ymin=null,xmax=null,ymax=null} shape =
intersection [shape,
if (xmin!=null) make_shape{dist p = xmin - p'0},
if (ymin!=null) make_shape{dist p = ymin - p'1},
if (xmax!=null) make_shape{dist p = p'0 - xmax},
if (ymax!=null) make_shape{dist p = p'1 - ymax},
];
* visualize the distance field using a colour_map
* text (steal from openjscad or antimony to begin with)
* rsquare, runion (rounded corners and fillets)
* infinite patterns
* grid (map shape onto infinite repeating shape)
* fractals
* fbm cloud colourmap (as seen in IQ's Elevated on shadertoy)
* fractal mountain: port IQ's Elevated
* Mandelbrot set
* Escher circle limit
* minkowski sum
* Sweep. Extends a 2D object along a path.
* Extrusion. Extends the shape of a 2D object in a perpendicular direction into 3D space.
* Revolve. Sweeps a 2D object around an axis.
* Loft. Extends the contours of a shape between one or more open or closed objects. Simple approach: linear_extrude which morphs between two 2D endpoints.
* Slice. Divides a solid object into two separate 3D objects.
Colour:
* spelling: "colour", as per en.oxforddictionaries.com
* [r,g,b] is a colour value.
* [x,y]->[r,g,b] and [x,y,z]->[r,g,b] are 2d and 3d colour fields.
* x->[r,g,b] is a colour map from [0...1) to a colour.
* 2D shape with colour[x,y] function.
* Either a shape has colour or it doesn't. Union requires either both args
have colour, or neither.
* When a coloured shape is transformed, the transformation is also applied
to the colour field.
* `colour(c) shape` applies a colour or a colour field to a shape.
* Colour operations:
* predefined colour values (red,green,blue,yellow,magenta,cyan,orange,green,...)
* colour operations (eg, light red)
* Geometric transforms can be applied to colour fields.
* Image import.
nary union:
* union shapes =
make_shape {
dist p = min [for (s in shapes) s.dist p],
bbox = [min[for (s in shapes) s.bbox'0], max[for(s in shapes)s.bbox'1]]
};
* SC: since shapes is a constant during inline expansion, we can expand the
for loop into a list of expressions.
* volumetric textures, like marble.
# refactoring
* use new Value access API throughout code
* value1==value2 performs a bitwise comparison (for performance),
to speed up code like val==true and val==missing.
The general (expensive) equality is val1.equals(val2)
# command line arguments
* command line export to different file formats (-o option)
curv [-i node] [-o format] [-D definition] filename
Evaluate filename as a Curv script file, yielding a module.
Write the module elements to stdout, unless -i name is specified, then
evaluate 'name' in the context of that module to get a value which is to
be output.
By default, the output format is to output each value as a Curv expression,
terminated by a newline, unless a different format is specified by -o.
Output formats: json, shadertoy.
The -D flag takes a legal Curv definition as an argument.
This definition is added to the module being read, overriding an
existing top level definition. This override happens during parsing.
* command line documentation
* docs/curv.1.md is converted to curv.1 by pandoc and installed
* curv --help
* curv --version
VM:
* debugger entry on exception
* System::error(const Exception&) -- throw an exception, but first, enter
the debugger.
* debugger: commands are bound as Curv metafunctions.
* `trace` print stack trace (with numbered call frames)
* `frame N` specify call frame
* inspect variables at current frame
* local and nonlocal symbol table pointers in Frame
* `exit`
* interrupt
OpenSCADbis proposal
# Simpler, More General Grammar
* Simple, yaccable grammar with no conflicts or precedence declarations.
* names: Phrase or Syntax?
Package Manager.
* How are packages named?
* URLs are flexible. We'll support a variety of geometry file formats:
images, meshes, *.curv, *.svg, and so on. We can reference internet
resources that weren't designed and packaged in a Curv-specific format.
* The Technetium namespace is a nice idea.
* Is there a formal notion of a package as an entity, as a collection of
files and metadata? (What is a package value?) Or do we just reference
individual files using their URLs?
* URLs are simple.
* Some notion of package versioning might be useful.
* Thingiverse doesn't support versioning. Github does, with a URL encoding.
* https://raw.githubusercontent.com/USER/PROJECT/BRANCH/PATH
* https://raw.githubusercontent.com/USER/PROJECT/COMMIT-HASH/PATH
* github://USER:PROJECT/PATH
* github://USER:PROJECT:BRANCH/PATH
* github://USER:PROJECT:HASH/PATH
* Is a package: a library, a shape or a library, or an arbitrary value?
Directory Syntax.
A directory containing a bunch of Curv source & resource files
is itself a source file denoting a module, one entry per file.
* I've considered much more complex versions of this, but this is simple
and good enough for MVP.
* This could mean: in foo.curv, you can refer to a sibling file bar.curv in the
same directory as simply `bar`, rather than as `file("bar.curv")`.
Other:
* Interactive curv: special variable `_` is last value. _1,_2, or $1,$2 ...
* Shared constructor is protected. share<T>(T&) aborts if use_count==0.
* Dynamically pluggable system abstraction. `System` class with system.echo(),
system.warning(), system.error(), system.open(), system.namespace, etc.
System object is refcounted, available during compile and run time.
* Scanner::system_
* Environ::system_. Just a single Environ object for the entire analysis
phase, which points to a chain of Scope objects.
* builtin_namespace(system) is a function that injects the system object into
certain builtin functions, like `file`, avoids the cost of making system
generally available in all evaluation contexts.
* Do we need the system object to be a VM register? Maybe needed if
system.error(Exception) is used to throw errors (so that debugger can be
triggered on error). So then:
* thread local variable
* store in Frame--more efficient than passing as argument to eval()
and Function::function_().
* interrupt.
* Periodically test a thread local variable known to the curv core,
curv::interrupt_requested. Throw an exception on interrupt, or call a System
function to do this. I don't like thread local variables for stylistic
reasons, but it seems legit to use one for IPC.
* Periodically test the variable System::interrupt_requested.
This is an extra pointer indirection more expensive than a thread-local var.
* Periodically call a System function. Inside this function provided by
the client is `if(thread_local_interrupt!=0)throw Interrupt()`.
This keeps the core "pure" (free of thread-local variables) at the cost
of a virtual function call at frequent intervals. The client will define
the thread-local variable instead.
* still need this?
- Environ must contain a Frame and a System. How?
- Every Environ contains a copy of the Frame and System pointers.
- A single mutable Environ object for the entire analysis phase,
which points to a stack of Scope objects.
Use RAII (in Scope class) to push/pop scopes.
So Scope contains a reference to Environ.
Environ::lookup calls Scope::lookup.
More complex, but a cleaner data model, since it doesn't make it look
like each Scope has an independent choice of Frame and System.
# CURV0 (expressions):
* x^y: right associative, -x^y==-(x^y), x^-y==x^(-y)
**: algolw, Python, Rexx, Simula, Cobol, Ruby, Tcl
^^: D
^: Eiffel, Icon, Mathematica, Maple, Matlab, Basic, Awk, Bc, Lua, Julia, R
* double-conversion based strtod
* broader unit testing
* smart pointers, see docs/Shared_Ptr.md
# CURV1 (scripts, LLVM)
* LLVM based evaluator. Compile Meaning to LLVM IR.
Embed raw function pointers and Values in IR as bit patterns.
* Benchmarks
# CURV2 (nested scopes)
* printing a function? currently, <function>, even for builtins
# CURV4 (geometry export)
* use dual contouring instead of marching cubes for STL export
* does OpenCL speed this up?
* SVX export? Does Shapeways still support this?
# Ongoing:
* more unit tests
* language reference manual
---------------------------------------------------------------------------
# Later:
* Rewrite scanner in re2c. Then add UTF-8 support.
* Parser: consider Boost::Spirit (recursive descent) or Lemon (similar to
Bison, thread safe, LALR(1)), or Bison with %pure-parser (thread safe).
Is Lemon better than Bison? Lemon:
* the tokenizer calls the parser (instead of vice versa)
* terminals/non-terminals don't need to be declared. Terminal name has
initial uppercase letter.
* productions are less error prone. Instead of $1, $2 (requires counting),
expr(A) ::= expr(B) PLUS expr(C). { A = B + C; }
* no mid-actions, one action per rule.
* no repetitions and optionals.
* small footprint: small code with no dependencies
* localization
* curv::String refactor
* String_Builder is rewritten to use a curv::String as the internal buffer
* User defined string literal constructs a Shared<String>:
underlying object is constructed at compile time with no mallocs,
and without two copies of the string literal data.
* dtostr() refactor
* put all 4 parameters into a DStyle struct.
Build system? Current candidates are:
* cmake. The popular standard, what I now use. Kind of horrible, but workable.
* I should use the ninja back end. It is fast and reliable.
* meson. Newer, seems inspired by cmake, hopefully less horrible.
Written in Python, so there's a big dependency. High profile automake
projects are moving to meson.
* build2. Looks very good: high quality and an excellent match to my needs.
New and not very popular. Not an Ubuntu package; users must download and
build it. At version 0.8 (as of Oct 2018). Re-examine this in 2019.
* Fast. Correct: auto track dependencies, rebuild on recipe change,
delete stale objects. High level: standard abstractions that are portable
across linux/osX/win. Cross project dependency discovery and configuration
(see pkg-config). Packageable: libcurv can be packaged for Ubuntu; build tools
are already in ubuntu repo.
* Should I use pkg-config for build-time dependency discovery and configuration?
Do I install a *.pc file that records compiler and linker flags required to
use the curv library? Can I build an Ubuntu package for libcurv?
* Google Bazel is fast, correct and high level. Still in beta. Missing some
platform support, cross project dependencies. Wait for 1.0 in 2017.
* cmake is popular and well supported on multiple platforms.
It has comprehensive portability abstractions.
It is more correct than expected, given that it generates makefiles.
Rebuilds on recipe change, tracks header dependencies. Doesn't delete stale
products. (Has an experimental option to generate ninja files.)
* ninja is fast. It rebuilds if recipe changes. Header dependencies depend
on the gcc feature to output dependencies (suboptimal, I'd rather it monitor
which files are opened by build tools).
Need a generator: ninja+cmake, ninja+gen, ninja+bash, ...
* tup is fast and correct. Tup determines hdr file dependencies automagically.
Tup rebuilds if recipe has changed. Tup deletes build products that can
no longer be generated. Tup has a high level command language (Lua).
* Tup is not in the Ubuntu package universe. There are PPAs...
Building from source isn't working...
* Tup is deeply magical and edgy. It uses FUSE, performs kernel magic to
overlay source and object directories, and makes tools confused
about what their current directory actually is, causing some things to
break. This can be overcome using the ^c chroot flag, which requires
setuid root. FUSE probably no longer works in MacOS ElCapitan due to SIP.
* So edgy it might discourage contributors. The automagic dependency tracking
requires deep magic that is also flaky: fuse, chroot, dynamic lib injection.
Eg, the ConEmu terminal emulator breaks DLL injection on Windows.
Tup is reported to not work on FreeBSD (fuse works differently).
* redo. Simple, powerful, elegant. Also slow (as fast or slower than make).
* So, probably cmake+ninja.