general smoothness
Getting gears to appear smooth by explicitly assigning indices to the generated facets got me thinking in more detail of how to accomplish this result in general, for any facets drawn in face mode by turtle graphics.
This is the result of applying a general method for reusing the same index for all point coordinates which are shared by multiple facets. The process works by going through all point coordinates, and checking for each if it was encounterd earlier. If not, the point is recorded in a property list (a sort of associative array, or key-value store) along with its index which will be the first one used for this point. If the point on the other hand was already recorded earlier, its index is recorded along with the index of already recorded point in a separate property list (or regular list).
Then the method simply goes through all indices and uses the second propery list to look up the index of the first recorded point.
There is a minor modification to the wordstolist procedure to deal with commas as separators, and another procedure to group coordinate triplets as lists within a list.
UPDATE: point coordinates
The process sofar only deals with the indices and as a result leaves all of the duplicated point coordinates unreferenced and therefore useless. In a second step these useless coordinates can be removed. However, removing entries in the point coordinate list will then require changes to the existing indices.
After thinking about this, a solution was to not go through a removal process but to recognize that we already have extracted the required list of unique point coordinates and the mapping from the existing indices to the new indices in the previous steps. The new coordinate list and the mapping just needed to be recorded in a list and additional property list. This just required a couple more lines of logo.
After that, it is simply a matter of replacing the existing point coordinates with the new list of unique point coordinets, and again going through the list of existing indices to look up the new index via the recorded map.
For the small helical gear above removing the unneeded points reduced the file size from 49kb to 26kb. Great !
For this detailed gear mesh file size reduces from 942 kb to 414 kb :
https://vrmath2.net/embed/?url=/sites/default/files/user/u342/x3d/helica...
Here are the updated and main procedures:
TO fence :positions :width PU SETPOS FIRST :positions FACE PCOFF PD SHOW REDUCE "quads :positions PU ;share indices for smooth shading LOCALMAKE "obj_face WORD OBJECT "_face optfacets OBJECT SET :obj_face "creaseAngle 3.14 LINE END TO optfacets :ifs LOCALMAKE "idx LISTTOARRAY wordstolist GET WORD :ifs "_face "coordindex LOCALMAKE "pts flattotuples wordstolist GET WORD :ifs "_coor "point ;local "coorlist ;not variables always global LOCAL "coorprop LOCALMAKE "coorlist WORD :ifs "_cplist LOCALMAKE "idxlist WORD :ifs "_iplist LOCALMAKE "i2uniq WORD :ifs "_uplist LOCALMAKE "coords [] ;show count remdup :pts ;construct property list FOR [i 1 COUNT :pts] [ MAKE "coorprop listtowords ITEM :i :pts IFELSE EMPTYP GPROP :coorlist :coorprop [ PPROP :coorlist :coorprop :i - 1 PPROP :idxlist (:i - 1) (:i - 1) ; also record in regular list for points QUEUE "coords ITEM :i :pts ; map old index to new index=count PPROP :i2uniq (:i - 1) ((COUNT :coords) - 1) ] [ PPROP :idxlist (:i - 1) GPROP :coorlist :coorprop ] ] ;replace indices FOR [i 1 COUNT :idx] [ IF NOTEQUALP ITEM :i :idx "-1 [ SETITEM :i :idx (GPROP :idxlist (ITEM :i :idx)) ] ] ; coords has all unique points SET WORD :ifs "_coor "point listtowords flatten :coords ;remap indices, could be combined with merging above FOR [i 1 COUNT :idx] [ IF NOTEQUALP ITEM :i :idx "-1 [ SETITEM :i :idx (GPROP :i2uniq (ITEM :i :idx)) ] ] SET WORD :ifs "_face "coordindex listtowords ARRAYTOLIST :idx ;output plist :idxlist END TO flatten :listoflists OUTPUT REDUCE "sentence :listoflists END TO flattotuples :flat ;too much recursion ;if emptyp :flat [output :flat] ;output fput (list first :flat item 2 :flat item 3 :flat) flattotuples bf bf bf :flat LOCALMAKE "tlist [] FOR [i 1 COUNT :flat 3] [ QUEUE "tlist (LIST ITEM :i :flat ITEM :i+1 :flat ITEM :i+2 :flat) ] OUTPUT :tlist END TO wordstolist :words LOCALMAKE "wlist [] LOCALMAKE "cword " LOCAL "i LOCAL "l FOR [i 0 ((COUNT :words) - 1)] [ MAKE "l ITEM :i :words IFELSE OR (EQUALP ASCII :l 32) (EQUALP :l ",) [ QUEUE "wlist :cword MAKE "cword "] [ MAKE "cword WORD :cword ITEM :i :words ] ] ;show :i IF NOT (OR (EQUALP ASCII :l 32) (EQUALP :l ",)) [QUEUE "wlist :cword] OUTPUT :wlist END
Here is a smooth band generated using the optfacet procedure:
Here is the logo for the band generation:
RESET CS RU 90 PCOFF SETMAT 0 25 FACE PD REPEAT 200 [ RD 90 FD 1 RD 90 FD 0.2 RD 90 FD 1 RD 90 JF 0.2 RT -20 + RANDOM 60 JF 0.2 ] PU optfacets OBJECT SET WORD OBJECT "_face "creaseAngle 3.14
Remember to save and reload the world to see the smoothed facets.
- aplesch's blog
- Login or register to post comments
- 3715 reads
Comments
Smooth band looks good
Thanks for explaining the ideas behind the codes. :-) I must implement this in my VRM2 (using javascript) to take advantage of the creaseAngle.
The comma separator is a direct result of dumping DOM or the use of toString(), not sure whether that is native in javascript or x3dom overwrites the toString. X3D validator does complains a lot, typical xml requirement.
Is the smooth bank a result of some random turtle movements? It reminds me some 3D molecule visualisations by Leonard Daly at http://realism.com/models.
Random
Yes, the smooth band is a result of turning right randomly between -20 and 40 degrees. I will add the short logo. It was a test to check if the procedure works on other face sets.
The comma is allowed between the coordinate triplets and was straightforward to check for.
It would be nice to have the crease angle option in logo.