diff --git a/README.md b/README.md index 5ca56be..1459236 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,11 @@ +# Simple L-System +A very basic and futile attempt at doing a tree generator. -The objective of this assignment is to create an L System parser and generate interesting looking plants. Start by forking and then cloning this repository: [https://github.com/CIS700-Procedural-Graphics/Project3-LSystems](https://github.com/CIS700-Procedural-Graphics/Project3-LSystems) +## Details -# L-System Parser - -lsystem.js contains classes for L-system, Rule, and LinkedList. Here’s our suggested structure: - -**The Symbol Nodes/Linked List:** - -Rather than representing our symbols as a string like in many L-system implementations, we prefer to use a linked list. This allows us to store additional information about each symbol at time of parsing (e.g. what iteration was this symbol added in?) Since we’re adding and replacing symbols at each iteration, we also save on the overhead of creating and destroying strings, since linked lists of course make it easy to add and remove nodes. You should write a Linked List class with Nodes that contain at least the following information: - -- The next node in the linked list -- The previous node in the linked list -- The grammar symbol at theis point in the overal string - -We also recommend that you write the following functions to interact with your linked list: - -- A function to symmetrically link two nodes together (e.g. Node A’s next is Node B, and Node B’s prev is Node A) -- A function to expand one of the symbol nodes of the linked list by replacing it with several new nodes. This function should look at the list of rules associated with the symbol in the linked list’s grammar dictionary, then generate a uniform random number between 0 and 1 in order to determine which of the Rules should be used to expand the symbol node. You will refer to a Rule’s probability and compare it to your random number in order to determine which Rule should be chosen. - -**Rules:** - -These are containers for the preconditions, postconditions and probability of a single replacement operation. They should operate on a symbol node in your linked list. - -**L-system:** - -This is the parser, which will loop through your linked list of symbol nodes and apply rules at each iteration. - -Implement the following functions in L-System so that you can apply grammar rules to your axiom given some number of iterations. More details and implementation suggestions about functions can be found in the TODO comments - -- `stringToLinkedList(input_string)` -- `linkedListToString(linkedList)` -- `replaceNode(linkedList, node, replacementString)` -- `doIterations(num)` - -## Turtle - -`turtle.js` has a function called renderSymbol that takes in a single node of a linked list and performs an operation to change the turtle’s state based on the symbol contained in the node. Usually, the turtle’s change in state will result in some sort of rendering output, such as drawing a cylinder when the turtle moves forward. We have provided you with a few example functions to illustrate how to write your own functions to be called by renderSymbol; these functions are rotateTurtle, moveTurtle, moveForward, and makeCylinder. If you inspect the constructor of the Turtle class, you can see how to associate an operation with a grammar symbol. - -- Modify turtle.js to support operations associated with the symbols `[` and `]` - - When you parse `[` you need to store the current turtle state somewhere - - When you parse `]` you need to set your turtle’s state to the most recently stored state. Think of this a pushing and popping turtle states on and off a stack. For example, given `F[+F][-F]`, the turtle should draw a Y shape. Note that your program must be capable of storing many turtle states at once in a stack. - -- In addition to operations for `[` and `]`, you must invent operations for any three symbols of your choosing. - - -## Interactivity - -Using dat.GUI and the examples provided in the reference code, make some aspect of your demo an interactive variable. For example, you could modify: - -1. the axiom -2. Your input grammer rules and their probability -3. the angle of rotation of the turtle -4. the size or color or material of the cylinder the turtle draws, etc! - -## L-System Plants - -Design a grammar for a new procedural plant! As the preceding parts of this assignment are basic computer science tasks, this is where you should spend the bulk of your time on this assignment. Come up with new grammar rules and include screenshots of your plants in your README. For inspiration, take a look at Example 7: Fractal Plant in Wikipedia: https://en.wikipedia.org/wiki/L-system Your procedural plant must have the following features - -1. Grow in 3D. Take advantage of three.js! -2. Have flowers or leaves that are added as a part of the grammar -3. Variation. Different instances of your plant should look distinctly different! -4. A twist. Broccoli trees are cool and all, but we hope to see sometime a little more surprising in your grammars - -# Publishing Your code - -Running `npm run deploy` will automatically build your project and push it to gh-pages where it will be visible at `username.github.io/repo-name`. NOTE: You MUST commit AND push all changes to your MASTER branch before doing this or you may lose your work. The `git` command must also be available in your terminal or command prompt. If you're using Windows, it's a good idea to use Git Bash. \ No newline at end of file +* The internal LSystem generator, expander and evaluator is somewhat generic and can be easily extended. It is essentially a doubly linked list with some pattern matching. A distinction is made between expanding and evaluating a system, however. +* There are three examples of different grammars and their rules. Details can be found in the code, specifically in plants.js +* Most of the work went into generating the tree mesh, which currently has some problems, and tweaking the instructions, as always is with procedural content. +* The branches use an elaborate formula to define the cross section. This is useful to do complicated surfaces, such as a cactus (shown in the demo). Certain instructions can change the parameters to this formula, so these changes can be seen in the same tree (The anemone looking tree shows this) +* Interesting instructions are the root symbols, which simulate the growing branches going into the floor, and cactus branches, which tend to go upwards and stop rotating. +* It uses random-js and a mersenne twister to assure reproducibility, but seeds are regenerated when the user desires. diff --git a/images/fun1.png b/images/fun1.png new file mode 100644 index 0000000..c391539 Binary files /dev/null and b/images/fun1.png differ diff --git a/images/fun2.png b/images/fun2.png new file mode 100644 index 0000000..faa8c9a Binary files /dev/null and b/images/fun2.png differ diff --git a/images/fun3.png b/images/fun3.png new file mode 100644 index 0000000..6a6a552 Binary files /dev/null and b/images/fun3.png differ diff --git a/images/fun4.png b/images/fun4.png new file mode 100644 index 0000000..e20556f Binary files /dev/null and b/images/fun4.png differ diff --git a/models/pot.obj b/models/pot.obj new file mode 100644 index 0000000..8672cb7 --- /dev/null +++ b/models/pot.obj @@ -0,0 +1,1675 @@ +# This file uses centimeters as units for non-parametric coordinates. + +v 0.681716 -0.000000 -0.221503 +v 0.579902 -0.000000 -0.421324 +v 0.421323 -0.000000 -0.579902 +v 0.221503 -0.000000 -0.681716 +v -0.000000 -0.000000 -0.716798 +v -0.221503 -0.000000 -0.681716 +v -0.421323 -0.000000 -0.579902 +v -0.579902 -0.000000 -0.421323 +v -0.681715 -0.000000 -0.221503 +v -0.716798 -0.000000 -0.000000 +v -0.681715 -0.000000 0.221503 +v -0.579902 -0.000000 0.421323 +v -0.421323 -0.000000 0.579902 +v -0.221503 -0.000000 0.681715 +v -0.000000 -0.000000 0.716798 +v 0.221503 -0.000000 0.681715 +v 0.421323 -0.000000 0.579902 +v 0.579902 -0.000000 0.421323 +v 0.681715 -0.000000 0.221503 +v 0.716798 -0.000000 -0.000000 +v -0.000000 -0.000000 -0.000000 +v 0.675060 1.577389 -0.219340 +v 0.574241 1.577389 -0.417210 +v 0.417210 1.577389 -0.574241 +v 0.219340 1.577389 -0.675060 +v -0.000000 1.577389 -0.709800 +v -0.219340 1.577389 -0.675060 +v -0.417210 1.577389 -0.574241 +v -0.574240 1.577389 -0.417210 +v -0.675060 1.577389 -0.219340 +v -0.709800 1.577389 -0.000000 +v -0.675060 1.577389 0.219340 +v -0.574240 1.577389 0.417210 +v -0.417210 1.577389 0.574240 +v -0.219340 1.577389 0.675060 +v -0.000000 1.577389 0.709800 +v 0.219340 1.577389 0.675060 +v 0.417210 1.577389 0.574240 +v 0.574240 1.577389 0.417210 +v 0.675060 1.577389 0.219340 +v 0.709800 1.577389 -0.000000 +v 0.216758 1.577389 -0.070429 +v 0.184385 1.577389 -0.133964 +v -0.000000 1.577389 -0.000000 +v 0.133964 1.577389 -0.184385 +v 0.070429 1.577389 -0.216758 +v -0.000000 1.577389 -0.227912 +v -0.070429 1.577389 -0.216758 +v -0.133964 1.577389 -0.184385 +v -0.184385 1.577389 -0.133964 +v -0.216758 1.577389 -0.070429 +v -0.227912 1.577389 -0.000000 +v -0.216758 1.577389 0.070429 +v -0.184385 1.577389 0.133964 +v -0.133964 1.577389 0.184385 +v -0.070429 1.577389 0.216758 +v -0.000000 1.577389 0.227912 +v 0.070429 1.577389 0.216758 +v 0.133964 1.577389 0.184385 +v 0.184385 1.577389 0.133964 +v 0.216758 1.577389 0.070429 +v 0.227912 1.577389 -0.000000 +v 0.583513 0.061182 0.423947 +v 0.423947 0.061182 0.583513 +v 0.222882 0.061182 0.685961 +v -0.000000 0.061182 0.721262 +v -0.222882 0.061182 0.685961 +v -0.423947 0.061182 0.583513 +v -0.583513 0.061182 0.423947 +v -0.685961 0.061182 0.222882 +v -0.721262 0.061182 -0.000000 +v -0.685961 0.061182 -0.222882 +v -0.583513 0.061182 -0.423947 +v -0.423947 0.061182 -0.583513 +v -0.222882 0.061182 -0.685961 +v -0.000000 0.061182 -0.721262 +v 0.222882 0.061182 -0.685961 +v 0.423947 0.061182 -0.583513 +v 0.583514 0.061182 -0.423947 +v 0.685961 0.061182 -0.222882 +v 0.721262 0.061182 -0.000000 +v 0.685961 0.061182 0.222882 +v 0.813963 1.454270 -0.264472 +v 0.791025 1.444903 -0.257020 +v 0.780380 1.421816 -0.253561 +v 0.692398 1.454270 -0.503057 +v 0.672886 1.444903 -0.488880 +v 0.663831 1.421816 -0.482301 +v 0.503057 1.454270 -0.692398 +v 0.488880 1.444903 -0.672886 +v 0.482301 1.421816 -0.663831 +v 0.264472 1.454270 -0.813963 +v 0.257019 1.444903 -0.791025 +v 0.253561 1.421816 -0.780380 +v -0.000000 1.454270 -0.855851 +v -0.000000 1.444903 -0.831733 +v -0.000000 1.421816 -0.820540 +v -0.264472 1.454270 -0.813963 +v -0.257019 1.444903 -0.791025 +v -0.253561 1.421816 -0.780380 +v -0.503057 1.454270 -0.692398 +v -0.488880 1.444903 -0.672886 +v -0.482301 1.421816 -0.663831 +v -0.692398 1.454270 -0.503057 +v -0.672886 1.444903 -0.488880 +v -0.663831 1.421816 -0.482301 +v -0.813963 1.454270 -0.264472 +v -0.791025 1.444903 -0.257019 +v -0.780380 1.421816 -0.253561 +v -0.855851 1.454270 0.000000 +v -0.831732 1.444903 -0.000000 +v -0.820540 1.421816 -0.000000 +v -0.813963 1.454270 0.264472 +v -0.791025 1.444903 0.257019 +v -0.780380 1.421816 0.253561 +v -0.692398 1.454270 0.503056 +v -0.672886 1.444903 0.488880 +v -0.663831 1.421816 0.482301 +v -0.503056 1.454270 0.692398 +v -0.488880 1.444903 0.672886 +v -0.482301 1.421816 0.663831 +v -0.264472 1.454270 0.813962 +v -0.257019 1.444903 0.791024 +v -0.253561 1.421816 0.780380 +v -0.000000 1.454270 0.855851 +v -0.000000 1.444903 0.831732 +v -0.000000 1.421816 0.820540 +v 0.264472 1.454270 0.813962 +v 0.257019 1.444903 0.791024 +v 0.253561 1.421816 0.780380 +v 0.503056 1.454270 0.692398 +v 0.488880 1.444903 0.672886 +v 0.482301 1.421816 0.663831 +v 0.692398 1.454270 0.503056 +v 0.672885 1.444903 0.488880 +v 0.663831 1.421816 0.482301 +v 0.813962 1.454270 0.264472 +v 0.791024 1.444903 0.257019 +v 0.780380 1.421816 0.253561 +v 0.855851 1.454270 0.000000 +v 0.831732 1.444903 0.000000 +v 0.820540 1.421816 -0.000000 +v 0.879956 1.454270 -0.285915 +v 0.902893 1.464136 -0.293368 +v 0.912393 1.487956 -0.296455 +v 0.748536 1.454270 -0.543843 +v 0.768047 1.464136 -0.558019 +v 0.776128 1.487956 -0.563890 +v 0.543843 1.454270 -0.748536 +v 0.558019 1.464136 -0.768046 +v 0.563890 1.487956 -0.776128 +v 0.285915 1.454270 -0.879956 +v 0.293368 1.464136 -0.902893 +v 0.296455 1.487956 -0.912393 +v 0.000000 1.454270 -0.925241 +v 0.000000 1.464136 -0.949358 +v 0.000000 1.487956 -0.959347 +v -0.285915 1.454270 -0.879956 +v -0.293368 1.464136 -0.902893 +v -0.296455 1.487956 -0.912393 +v -0.543843 1.454270 -0.748536 +v -0.558018 1.464136 -0.768046 +v -0.563890 1.487956 -0.776128 +v -0.748535 1.454270 -0.543843 +v -0.768046 1.464136 -0.558018 +v -0.776128 1.487956 -0.563890 +v -0.879956 1.454270 -0.285915 +v -0.902893 1.464136 -0.293368 +v -0.912393 1.487956 -0.296454 +v -0.925241 1.454270 0.000000 +v -0.949357 1.464136 0.000000 +v -0.959347 1.487956 0.000000 +v -0.879956 1.454270 0.285915 +v -0.902893 1.464136 0.293368 +v -0.912393 1.487956 0.296455 +v -0.748535 1.454270 0.543843 +v -0.768046 1.464136 0.558018 +v -0.776128 1.487956 0.563890 +v -0.543843 1.454270 0.748535 +v -0.558018 1.464136 0.768046 +v -0.563890 1.487956 0.776128 +v -0.285915 1.454270 0.879956 +v -0.293368 1.464136 0.902892 +v -0.296454 1.487956 0.912393 +v -0.000000 1.454270 0.925241 +v -0.000000 1.464136 0.949357 +v -0.000000 1.487956 0.959347 +v 0.285915 1.454270 0.879956 +v 0.293368 1.464136 0.902892 +v 0.296454 1.487956 0.912393 +v 0.543843 1.454270 0.748535 +v 0.558018 1.464136 0.768046 +v 0.563890 1.487956 0.776128 +v 0.748535 1.454270 0.543843 +v 0.768046 1.464136 0.558018 +v 0.776128 1.487956 0.563890 +v 0.879956 1.454270 0.285915 +v 0.902892 1.464136 0.293368 +v 0.912393 1.487956 0.296454 +v 0.925240 1.454270 -0.000000 +v 0.949357 1.464136 0.000000 +v 0.959347 1.487956 0.000000 +v 0.912393 1.736411 -0.296455 +v 0.902893 1.760231 -0.293368 +v 0.879956 1.770097 -0.285915 +v 0.776128 1.736411 -0.563890 +v 0.768047 1.760231 -0.558019 +v 0.748536 1.770097 -0.543843 +v 0.563890 1.736411 -0.776128 +v 0.558019 1.760231 -0.768046 +v 0.543843 1.770097 -0.748536 +v 0.296455 1.736411 -0.912393 +v 0.293368 1.760231 -0.902893 +v 0.285915 1.770097 -0.879956 +v 0.000000 1.736411 -0.959347 +v 0.000000 1.760231 -0.949358 +v 0.000000 1.770097 -0.925241 +v -0.296455 1.736411 -0.912393 +v -0.293368 1.760231 -0.902893 +v -0.285915 1.770097 -0.879956 +v -0.563890 1.736411 -0.776128 +v -0.558018 1.760231 -0.768046 +v -0.543843 1.770097 -0.748536 +v -0.776128 1.736411 -0.563890 +v -0.768046 1.760231 -0.558018 +v -0.748535 1.770097 -0.543843 +v -0.912393 1.736411 -0.296454 +v -0.902893 1.760231 -0.293368 +v -0.879956 1.770097 -0.285915 +v -0.959347 1.736411 0.000000 +v -0.949357 1.760231 0.000000 +v -0.925241 1.770097 0.000000 +v -0.912393 1.736411 0.296455 +v -0.902893 1.760231 0.293368 +v -0.879956 1.770097 0.285915 +v -0.776128 1.736411 0.563890 +v -0.768046 1.760231 0.558018 +v -0.748535 1.770097 0.543843 +v -0.563890 1.736411 0.776128 +v -0.558018 1.760231 0.768046 +v -0.543843 1.770097 0.748535 +v -0.296454 1.736411 0.912393 +v -0.293368 1.760231 0.902892 +v -0.285915 1.770097 0.879956 +v -0.000000 1.736411 0.959347 +v -0.000000 1.760231 0.949357 +v -0.000000 1.770097 0.925241 +v 0.296454 1.736411 0.912393 +v 0.293368 1.760231 0.902892 +v 0.285915 1.770097 0.879956 +v 0.563890 1.736411 0.776128 +v 0.558018 1.760231 0.768046 +v 0.543843 1.770097 0.748535 +v 0.776128 1.736411 0.563890 +v 0.768046 1.760231 0.558018 +v 0.748535 1.770097 0.543843 +v 0.912393 1.736411 0.296454 +v 0.902892 1.760231 0.293368 +v 0.879956 1.770097 0.285915 +v 0.959347 1.736411 0.000000 +v 0.949357 1.760231 0.000000 +v 0.925240 1.770097 -0.000000 +v 0.787623 1.770097 -0.255914 +v 0.764683 1.763124 -0.248461 +v 0.749000 1.744393 -0.243365 +v 0.669992 1.770097 -0.486778 +v 0.650478 1.763124 -0.472600 +v 0.637138 1.744393 -0.462908 +v 0.486778 1.770097 -0.669992 +v 0.472600 1.763124 -0.650478 +v 0.462908 1.744393 -0.637138 +v 0.255914 1.770097 -0.787623 +v 0.248461 1.763124 -0.764683 +v 0.243365 1.744393 -0.749000 +v -0.000000 1.770097 -0.828155 +v -0.000000 1.763124 -0.804035 +v -0.000000 1.744393 -0.787545 +v -0.255914 1.770097 -0.787623 +v -0.248461 1.763124 -0.764683 +v -0.243365 1.744393 -0.749000 +v -0.486778 1.770097 -0.669992 +v -0.472600 1.763124 -0.650478 +v -0.462907 1.744393 -0.637137 +v -0.669992 1.770097 -0.486778 +v -0.650478 1.763124 -0.472600 +v -0.637137 1.744393 -0.462907 +v -0.787623 1.770097 -0.255914 +v -0.764683 1.763124 -0.248461 +v -0.749000 1.744393 -0.243365 +v -0.828155 1.770097 0.000000 +v -0.804035 1.763124 0.000000 +v -0.787545 1.744393 0.000000 +v -0.787623 1.770097 0.255914 +v -0.764683 1.763124 0.248461 +v -0.749000 1.744393 0.243365 +v -0.669992 1.770097 0.486777 +v -0.650478 1.763124 0.472600 +v -0.637137 1.744393 0.462907 +v -0.486778 1.770097 0.669992 +v -0.472600 1.763124 0.650478 +v -0.462907 1.744393 0.637137 +v -0.255914 1.770097 0.787623 +v -0.248461 1.763124 0.764683 +v -0.243365 1.744393 0.749000 +v -0.000000 1.770097 0.828155 +v -0.000000 1.763124 0.804035 +v -0.000000 1.744393 0.787545 +v 0.255914 1.770097 0.787622 +v 0.248461 1.763124 0.764683 +v 0.243365 1.744393 0.749000 +v 0.486777 1.770097 0.669992 +v 0.472600 1.763124 0.650478 +v 0.462907 1.744393 0.637137 +v 0.669992 1.770097 0.486777 +v 0.650478 1.763124 0.472600 +v 0.637137 1.744393 0.462907 +v 0.787622 1.770097 0.255914 +v 0.764683 1.763124 0.248461 +v 0.749000 1.744393 0.243365 +v 0.828155 1.770097 0.000000 +v 0.804035 1.763124 0.000000 +v 0.787545 1.744393 0.000000 +vt 0.648603 0.107966 +vt 0.626409 0.064408 +vt 0.591842 0.029841 +vt 0.548284 0.007647 +vt 0.500000 -0.000000 +vt 0.451716 0.007647 +vt 0.408159 0.029841 +vt 0.373591 0.064409 +vt 0.351397 0.107966 +vt 0.343750 0.156250 +vt 0.351397 0.204534 +vt 0.373591 0.248091 +vt 0.408159 0.282659 +vt 0.451716 0.304853 +vt 0.500000 0.312500 +vt 0.548284 0.304853 +vt 0.591841 0.282659 +vt 0.626409 0.248091 +vt 0.648603 0.204534 +vt 0.656250 0.156250 +vt 0.375000 0.312500 +vt 0.387500 0.312500 +vt 0.400000 0.312500 +vt 0.412500 0.312500 +vt 0.425000 0.312500 +vt 0.437500 0.312500 +vt 0.450000 0.312500 +vt 0.462500 0.312500 +vt 0.475000 0.312500 +vt 0.487500 0.312500 +vt 0.500000 0.312500 +vt 0.512500 0.312500 +vt 0.525000 0.312500 +vt 0.537500 0.312500 +vt 0.550000 0.312500 +vt 0.562500 0.312500 +vt 0.575000 0.312500 +vt 0.587500 0.312500 +vt 0.600000 0.312500 +vt 0.612500 0.312500 +vt 0.625000 0.312500 +vt 0.500000 0.150000 +vt 0.500000 0.837500 +vt 0.648603 0.892034 +vt 0.626409 0.935591 +vt 0.591841 0.970159 +vt 0.548284 0.992353 +vt 0.500000 1.000000 +vt 0.451716 0.992353 +vt 0.408159 0.970159 +vt 0.373591 0.935591 +vt 0.351397 0.892034 +vt 0.343750 0.843750 +vt 0.351397 0.795466 +vt 0.373591 0.751909 +vt 0.408159 0.717341 +vt 0.451716 0.695147 +vt 0.500000 0.687500 +vt 0.548284 0.695147 +vt 0.591842 0.717341 +vt 0.626409 0.751908 +vt 0.648603 0.795466 +vt 0.656250 0.843750 +vt 0.375000 0.328316 +vt 0.626409 0.935591 +vt 0.648603 0.892034 +vt 0.591841 0.970159 +vt 0.626409 0.935592 +vt 0.548284 0.992353 +vt 0.591841 0.970159 +vt 0.500000 1.000000 +vt 0.548284 0.992353 +vt 0.451716 0.992353 +vt 0.500000 1.000000 +vt 0.408159 0.970159 +vt 0.451716 0.992353 +vt 0.373591 0.935591 +vt 0.408159 0.970159 +vt 0.351397 0.892034 +vt 0.373591 0.935592 +vt 0.343750 0.843750 +vt 0.351397 0.892034 +vt 0.351397 0.795466 +vt 0.343750 0.843750 +vt 0.373591 0.751909 +vt 0.351397 0.795466 +vt 0.408159 0.717341 +vt 0.373591 0.751909 +vt 0.451716 0.695147 +vt 0.408159 0.717341 +vt 0.500000 0.687500 +vt 0.451716 0.695147 +vt 0.548284 0.695147 +vt 0.500000 0.687500 +vt 0.591842 0.717341 +vt 0.548284 0.695147 +vt 0.626409 0.751908 +vt 0.591842 0.717341 +vt 0.648603 0.795466 +vt 0.626409 0.751908 +vt 0.656250 0.843750 +vt 0.648603 0.795466 +vt 0.648603 0.892034 +vt 0.656250 0.843750 +vt 0.626409 0.935591 +vt 0.648603 0.892034 +vt 0.591841 0.970159 +vt 0.626409 0.935591 +vt 0.548284 0.992353 +vt 0.591841 0.970159 +vt 0.500000 1.000000 +vt 0.548284 0.992353 +vt 0.451716 0.992353 +vt 0.500000 1.000000 +vt 0.408159 0.970159 +vt 0.451716 0.992353 +vt 0.373591 0.935591 +vt 0.408159 0.970159 +vt 0.351397 0.892034 +vt 0.373591 0.935591 +vt 0.343750 0.843750 +vt 0.351397 0.892034 +vt 0.351397 0.795466 +vt 0.343750 0.843750 +vt 0.373591 0.751909 +vt 0.351397 0.795466 +vt 0.408159 0.717341 +vt 0.373591 0.751909 +vt 0.451716 0.695147 +vt 0.408159 0.717341 +vt 0.500000 0.687500 +vt 0.451716 0.695147 +vt 0.548284 0.695147 +vt 0.500000 0.687500 +vt 0.591842 0.717341 +vt 0.548284 0.695147 +vt 0.626409 0.751908 +vt 0.591842 0.717341 +vt 0.648603 0.795466 +vt 0.626409 0.751908 +vt 0.656250 0.843750 +vt 0.648603 0.795466 +vt 0.648603 0.892034 +vt 0.656250 0.843750 +vt 0.626409 0.935591 +vt 0.648603 0.892034 +vt 0.591841 0.970159 +vt 0.626409 0.935591 +vt 0.548284 0.992353 +vt 0.591841 0.970159 +vt 0.500000 1.000000 +vt 0.548284 0.992353 +vt 0.451716 0.992353 +vt 0.500000 1.000000 +vt 0.408159 0.970159 +vt 0.451716 0.992353 +vt 0.373591 0.935591 +vt 0.408159 0.970159 +vt 0.351397 0.892034 +vt 0.373591 0.935591 +vt 0.343750 0.843750 +vt 0.351397 0.892034 +vt 0.351397 0.795466 +vt 0.343750 0.843750 +vt 0.373591 0.751909 +vt 0.351397 0.795466 +vt 0.408159 0.717341 +vt 0.373591 0.751909 +vt 0.451716 0.695147 +vt 0.408159 0.717341 +vt 0.500000 0.687500 +vt 0.451716 0.695147 +vt 0.548284 0.695147 +vt 0.500000 0.687500 +vt 0.591842 0.717341 +vt 0.548284 0.695147 +vt 0.626409 0.751908 +vt 0.591842 0.717341 +vt 0.648603 0.795466 +vt 0.626409 0.751908 +vt 0.656250 0.843750 +vt 0.648603 0.795466 +vt 0.648603 0.892034 +vt 0.656250 0.843750 +vt 0.626409 0.935591 +vt 0.648603 0.892034 +vt 0.591841 0.970159 +vt 0.626409 0.935591 +vt 0.548284 0.992353 +vt 0.591841 0.970159 +vt 0.500000 1.000000 +vt 0.548284 0.992353 +vt 0.451716 0.992353 +vt 0.500000 1.000000 +vt 0.408159 0.970159 +vt 0.451716 0.992353 +vt 0.373591 0.935591 +vt 0.408159 0.970159 +vt 0.351397 0.892034 +vt 0.373591 0.935591 +vt 0.343750 0.843750 +vt 0.351397 0.892034 +vt 0.351397 0.795466 +vt 0.343750 0.843750 +vt 0.373591 0.751909 +vt 0.351397 0.795466 +vt 0.408159 0.717341 +vt 0.373591 0.751909 +vt 0.451716 0.695147 +vt 0.408159 0.717341 +vt 0.500000 0.687500 +vt 0.451716 0.695147 +vt 0.548284 0.695147 +vt 0.500000 0.687500 +vt 0.591842 0.717341 +vt 0.548284 0.695147 +vt 0.626409 0.751908 +vt 0.591842 0.717341 +vt 0.648603 0.795466 +vt 0.626409 0.751908 +vt 0.656250 0.843750 +vt 0.648603 0.795466 +vt 0.648603 0.892034 +vt 0.656250 0.843750 +vt 0.587500 0.328316 +vt 0.575000 0.680050 +vt 0.575000 0.328316 +vt 0.562500 0.680050 +vt 0.562500 0.328316 +vt 0.550000 0.680050 +vt 0.550000 0.328316 +vt 0.537500 0.680050 +vt 0.537500 0.328316 +vt 0.525000 0.680050 +vt 0.525000 0.328316 +vt 0.512500 0.680050 +vt 0.512500 0.328316 +vt 0.500000 0.680050 +vt 0.500000 0.328316 +vt 0.487500 0.680050 +vt 0.487500 0.328316 +vt 0.475000 0.680050 +vt 0.475000 0.328316 +vt 0.462500 0.680050 +vt 0.462500 0.328316 +vt 0.450000 0.680050 +vt 0.450000 0.328316 +vt 0.437500 0.680050 +vt 0.437500 0.328316 +vt 0.425000 0.680050 +vt 0.425000 0.328316 +vt 0.412500 0.680050 +vt 0.412500 0.328316 +vt 0.400000 0.680050 +vt 0.400000 0.328316 +vt 0.387500 0.680050 +vt 0.387500 0.328316 +vt 0.375000 0.680050 +vt 0.625000 0.328316 +vt 0.612500 0.680050 +vt 0.612500 0.328316 +vt 0.600000 0.680050 +vt 0.600000 0.328316 +vt 0.587500 0.680050 +vt 0.625000 0.680050 +vt 0.648603 0.892034 +vt 0.625000 0.688440 +vt 0.375000 0.688440 +vt 0.387500 0.688440 +vt 0.626409 0.935591 +vt 0.400000 0.688440 +vt 0.591841 0.970159 +vt 0.412500 0.688440 +vt 0.548284 0.992353 +vt 0.425000 0.688440 +vt 0.500000 1.000000 +vt 0.437500 0.688440 +vt 0.451716 0.992353 +vt 0.450000 0.688440 +vt 0.408159 0.970159 +vt 0.462500 0.688440 +vt 0.373591 0.935591 +vt 0.475000 0.688440 +vt 0.351397 0.892034 +vt 0.487500 0.688440 +vt 0.343750 0.843750 +vt 0.500000 0.688440 +vt 0.351397 0.795466 +vt 0.512500 0.688440 +vt 0.373591 0.751909 +vt 0.525000 0.688440 +vt 0.408159 0.717341 +vt 0.537500 0.688440 +vt 0.451716 0.695147 +vt 0.550000 0.688440 +vt 0.500000 0.687500 +vt 0.562500 0.688440 +vt 0.548284 0.695147 +vt 0.575000 0.688440 +vt 0.591842 0.717341 +vt 0.587500 0.688440 +vt 0.626409 0.751908 +vt 0.600000 0.688440 +vt 0.648603 0.795466 +vt 0.612500 0.688440 +vt 0.656250 0.843750 +vt 0.648603 0.892034 +vt 0.626409 0.935591 +vt 0.591841 0.970159 +vt 0.548284 0.992353 +vt 0.500000 1.000000 +vt 0.451716 0.992353 +vt 0.408159 0.970159 +vt 0.373591 0.935591 +vt 0.351397 0.892034 +vt 0.343750 0.843750 +vt 0.351397 0.795466 +vt 0.373591 0.751909 +vt 0.408159 0.717341 +vt 0.451716 0.695147 +vt 0.500000 0.687500 +vt 0.548284 0.695147 +vt 0.591842 0.717341 +vt 0.626409 0.751908 +vt 0.648603 0.795466 +vt 0.656250 0.843750 +vt 0.648603 0.892034 +vt 0.626409 0.935591 +vt 0.591841 0.970159 +vt 0.548284 0.992353 +vt 0.500000 1.000000 +vt 0.451716 0.992353 +vt 0.408159 0.970159 +vt 0.373591 0.935591 +vt 0.351397 0.892034 +vt 0.343750 0.843750 +vt 0.351397 0.795466 +vt 0.373591 0.751909 +vt 0.408159 0.717341 +vt 0.451716 0.695147 +vt 0.500000 0.687500 +vt 0.548284 0.695147 +vt 0.591842 0.717341 +vt 0.626409 0.751908 +vt 0.648603 0.795466 +vt 0.656250 0.843750 +vt 0.648603 0.892034 +vt 0.626409 0.935591 +vt 0.591841 0.970159 +vt 0.548284 0.992353 +vt 0.500000 1.000000 +vt 0.451716 0.992353 +vt 0.408159 0.970159 +vt 0.373591 0.935591 +vt 0.351397 0.892034 +vt 0.343750 0.843750 +vt 0.351397 0.795466 +vt 0.373591 0.751909 +vt 0.408159 0.717341 +vt 0.451716 0.695147 +vt 0.500000 0.687500 +vt 0.548284 0.695147 +vt 0.591842 0.717341 +vt 0.626409 0.751908 +vt 0.648603 0.795466 +vt 0.656250 0.843750 +vn 0.176627 -0.982604 -0.057389 +vn 0.150247 -0.982604 -0.109161 +vn 0.806872 -0.072771 -0.586227 +vn 0.948535 -0.072771 -0.308197 +vn 0.109161 -0.982604 -0.150247 +vn 0.586227 -0.072771 -0.806872 +vn 0.057389 -0.982603 -0.176626 +vn 0.308198 -0.072771 -0.948535 +vn -0.000000 -0.982603 -0.185716 +vn -0.000000 -0.072771 -0.997349 +vn -0.057389 -0.982603 -0.176626 +vn -0.308198 -0.072771 -0.948535 +vn -0.109161 -0.982604 -0.150247 +vn -0.586227 -0.072771 -0.806872 +vn -0.150247 -0.982604 -0.109161 +vn -0.806872 -0.072771 -0.586227 +vn -0.176626 -0.982603 -0.057389 +vn -0.948535 -0.072771 -0.308198 +vn -0.185716 -0.982603 0.000000 +vn -0.997349 -0.072771 -0.000000 +vn -0.176626 -0.982603 0.057389 +vn -0.948535 -0.072771 0.308198 +vn -0.150247 -0.982604 0.109161 +vn -0.806872 -0.072771 0.586227 +vn -0.109161 -0.982604 0.150247 +vn -0.586227 -0.072771 0.806872 +vn -0.057389 -0.982603 0.176627 +vn -0.308198 -0.072771 0.948535 +vn 0.000000 -0.982603 0.185716 +vn 0.000000 -0.072771 0.997349 +vn 0.057389 -0.982603 0.176626 +vn 0.308198 -0.072771 0.948535 +vn 0.109161 -0.982604 0.150247 +vn 0.586227 -0.072771 0.806872 +vn 0.150247 -0.982604 0.109161 +vn 0.806872 -0.072771 0.586227 +vn 0.176626 -0.982603 0.057389 +vn 0.948535 -0.072771 0.308198 +vn 0.185716 -0.982603 0.000000 +vn 0.997349 -0.072771 0.000001 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000002 +vn 0.000000 1.000000 0.000002 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000001 +vn 0.000000 1.000000 0.000001 +vn 0.000000 1.000000 0.000001 +vn 0.000000 1.000000 0.000001 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 -0.000001 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.078597 -0.996579 -0.025537 +vn 0.066858 -0.996579 -0.048575 +vn 0.100980 -0.992180 -0.073366 +vn 0.118709 -0.992180 -0.038571 +vn 0.048575 -0.996579 -0.066858 +vn 0.073366 -0.992180 -0.100980 +vn 0.025538 -0.996579 -0.078597 +vn 0.038571 -0.992180 -0.118708 +vn -0.000000 -0.996579 -0.082641 +vn 0.000000 -0.992180 -0.124818 +vn -0.025538 -0.996579 -0.078597 +vn -0.038571 -0.992180 -0.118709 +vn -0.048575 -0.996579 -0.066858 +vn -0.073366 -0.992180 -0.100980 +vn -0.066858 -0.996579 -0.048576 +vn -0.100980 -0.992180 -0.073366 +vn -0.078597 -0.996579 -0.025538 +vn -0.118709 -0.992180 -0.038571 +vn -0.082642 -0.996579 0.000000 +vn -0.124818 -0.992180 -0.000000 +vn -0.078597 -0.996579 0.025538 +vn -0.118709 -0.992180 0.038571 +vn -0.066858 -0.996579 0.048575 +vn -0.100980 -0.992180 0.073366 +vn -0.048575 -0.996579 0.066858 +vn -0.073366 -0.992180 0.100980 +vn -0.025538 -0.996579 0.078597 +vn -0.038571 -0.992180 0.118710 +vn 0.000000 -0.996579 0.082641 +vn 0.000000 -0.992180 0.124818 +vn 0.025538 -0.996579 0.078597 +vn 0.038571 -0.992180 0.118709 +vn 0.048575 -0.996579 0.066858 +vn 0.073366 -0.992180 0.100980 +vn 0.066858 -0.996579 0.048575 +vn 0.100980 -0.992180 0.073366 +vn 0.078597 -0.996579 0.025538 +vn 0.118709 -0.992180 0.038571 +vn 0.082642 -0.996579 -0.000000 +vn 0.124818 -0.992180 0.000000 +vn 0.950467 -0.035204 -0.308825 +vn 0.808516 -0.035204 -0.587421 +vn 0.808516 0.035204 -0.587421 +vn 0.950467 0.035204 -0.308824 +vn 0.587421 -0.035204 -0.808516 +vn 0.587421 0.035204 -0.808516 +vn 0.308825 -0.035204 -0.950467 +vn 0.308825 0.035204 -0.950467 +vn -0.000000 -0.035204 -0.999380 +vn 0.000000 0.035204 -0.999380 +vn -0.308825 -0.035204 -0.950467 +vn -0.308825 0.035204 -0.950467 +vn -0.587421 -0.035204 -0.808515 +vn -0.587421 0.035204 -0.808515 +vn -0.808516 -0.035204 -0.587421 +vn -0.808516 0.035204 -0.587421 +vn -0.950467 -0.035204 -0.308825 +vn -0.950467 0.035204 -0.308825 +vn -0.999380 -0.035204 0.000000 +vn -0.999380 0.035204 0.000000 +vn -0.950467 -0.035204 0.308825 +vn -0.950467 0.035204 0.308825 +vn -0.808515 -0.035204 0.587421 +vn -0.808516 0.035204 0.587421 +vn -0.587421 -0.035204 0.808516 +vn -0.587421 0.035204 0.808516 +vn -0.308825 -0.035204 0.950467 +vn -0.308825 0.035204 0.950467 +vn 0.000000 -0.035204 0.999380 +vn 0.000000 0.035204 0.999380 +vn 0.308825 -0.035204 0.950467 +vn 0.308825 0.035204 0.950467 +vn 0.587421 -0.035204 0.808516 +vn 0.587421 0.035204 0.808516 +vn 0.808516 -0.035204 0.587421 +vn 0.808516 0.035204 0.587421 +vn 0.950467 -0.035203 0.308825 +vn 0.950467 0.035203 0.308825 +vn 0.999380 -0.035204 0.000001 +vn 0.999380 0.035204 0.000001 +vn 0.094388 0.995063 -0.030669 +vn 0.080291 0.995063 -0.058335 +vn -0.037311 0.998936 0.027108 +vn -0.043861 0.998936 0.014251 +vn 0.058335 0.995063 -0.080291 +vn -0.027108 0.998936 0.037311 +vn 0.030668 0.995063 -0.094387 +vn -0.014251 0.998936 0.043862 +vn 0.000000 0.995063 -0.099244 +vn -0.000000 0.998936 0.046119 +vn -0.030668 0.995063 -0.094387 +vn 0.014251 0.998936 0.043862 +vn -0.058335 0.995063 -0.080291 +vn 0.027108 0.998936 0.037310 +vn -0.080291 0.995063 -0.058335 +vn 0.037311 0.998936 0.027108 +vn -0.094388 0.995063 -0.030668 +vn 0.043861 0.998936 0.014251 +vn -0.099245 0.995063 0.000000 +vn 0.046119 0.998936 0.000000 +vn -0.094388 0.995063 0.030669 +vn 0.043861 0.998936 -0.014251 +vn -0.080291 0.995063 0.058335 +vn 0.037311 0.998936 -0.027108 +vn -0.058335 0.995063 0.080291 +vn 0.027108 0.998936 -0.037310 +vn -0.030668 0.995063 0.094387 +vn 0.014251 0.998936 -0.043860 +vn 0.000000 0.995063 0.099246 +vn -0.000000 0.998936 -0.046118 +vn 0.030668 0.995063 0.094389 +vn -0.014251 0.998936 -0.043861 +vn 0.058335 0.995063 0.080290 +vn -0.027108 0.998936 -0.037311 +vn 0.080291 0.995063 0.058334 +vn -0.037311 0.998936 -0.027107 +vn 0.094388 0.995063 0.030668 +vn -0.043861 0.998936 -0.014251 +vn 0.099245 0.995063 0.000000 +vn -0.046119 0.998936 -0.000000 +vn -0.845822 0.457228 0.274823 +vn -0.719499 0.457227 0.522747 +vn -0.733437 0.422039 0.532873 +vn -0.862207 0.422039 0.280147 +vn -0.522747 0.457227 0.719499 +vn -0.532873 0.422038 0.733437 +vn -0.274824 0.457227 0.845822 +vn -0.280148 0.422038 0.862207 +vn 0.000000 0.457227 0.889350 +vn 0.000000 0.422038 0.906578 +vn 0.274824 0.457227 0.845822 +vn 0.280148 0.422038 0.862207 +vn 0.522747 0.457227 0.719499 +vn 0.532874 0.422038 0.733437 +vn 0.719500 0.457227 0.522747 +vn 0.733437 0.422038 0.532873 +vn 0.845822 0.457227 0.274824 +vn 0.862207 0.422039 0.280148 +vn 0.889350 0.457227 -0.000000 +vn 0.906578 0.422039 -0.000000 +vn 0.845822 0.457227 -0.274824 +vn 0.862207 0.422038 -0.280148 +vn 0.719499 0.457227 -0.522747 +vn 0.733437 0.422038 -0.532873 +vn 0.522747 0.457227 -0.719499 +vn 0.532873 0.422038 -0.733437 +vn 0.274824 0.457227 -0.845822 +vn 0.280148 0.422038 -0.862207 +vn -0.000000 0.457227 -0.889350 +vn -0.000000 0.422038 -0.906578 +vn -0.274825 0.457227 -0.845822 +vn -0.280148 0.422038 -0.862207 +vn -0.522747 0.457227 -0.719499 +vn -0.532873 0.422038 -0.733437 +vn -0.719499 0.457227 -0.522747 +vn -0.733437 0.422038 -0.532873 +vn -0.845822 0.457227 -0.274824 +vn -0.862207 0.422038 -0.280148 +vn -0.889350 0.457227 -0.000000 +vn -0.906578 0.422038 -0.000000 +vn 0.806396 -0.080427 0.585881 +vn 0.585881 -0.080427 0.806396 +vn 0.308016 -0.080427 0.947976 +vn 0.000000 -0.080427 0.996761 +vn -0.308016 -0.080427 0.947976 +vn -0.585881 -0.080427 0.806396 +vn -0.806396 -0.080427 0.585881 +vn -0.947976 -0.080427 0.308016 +vn -0.996761 -0.080427 0.000000 +vn -0.947976 -0.080427 -0.308016 +vn -0.806396 -0.080427 -0.585881 +vn -0.585881 -0.080427 -0.806396 +vn -0.308016 -0.080427 -0.947976 +vn -0.000000 -0.080427 -0.996761 +vn 0.308016 -0.080427 -0.947976 +vn 0.585881 -0.080427 -0.806396 +vn 0.806396 -0.080427 -0.585881 +vn 0.947976 -0.080427 -0.308015 +vn 0.996761 -0.080427 0.000001 +vn 0.947976 -0.080427 0.308016 +vn 0.344301 -0.932171 -0.111870 +vn 0.292880 -0.932171 -0.212790 +vn 0.855789 -0.436242 -0.278062 +vn 0.727977 -0.436242 -0.528907 +vn 0.212789 -0.932171 -0.292880 +vn 0.528906 -0.436242 -0.727977 +vn 0.111870 -0.932170 -0.344302 +vn 0.278062 -0.436241 -0.855789 +vn -0.000000 -0.932170 -0.362021 +vn -0.000000 -0.436241 -0.899830 +vn -0.111870 -0.932171 -0.344300 +vn -0.278063 -0.436241 -0.855789 +vn -0.212789 -0.932171 -0.292878 +vn -0.528907 -0.436241 -0.727978 +vn -0.292879 -0.932171 -0.212789 +vn -0.727977 -0.436241 -0.528907 +vn -0.344300 -0.932171 -0.111870 +vn -0.855789 -0.436241 -0.278063 +vn -0.362018 -0.932171 0.000000 +vn -0.899830 -0.436240 0.000000 +vn -0.344300 -0.932171 0.111870 +vn -0.855789 -0.436241 0.278064 +vn -0.292879 -0.932171 0.212789 +vn -0.727978 -0.436242 0.528905 +vn -0.212789 -0.932171 0.292878 +vn -0.528906 -0.436241 0.727978 +vn -0.111870 -0.932172 0.344298 +vn -0.278062 -0.436240 0.855790 +vn 0.000000 -0.932171 0.362017 +vn 0.000000 -0.436241 0.899830 +vn 0.111870 -0.932172 0.344298 +vn 0.278063 -0.436241 0.855789 +vn 0.212789 -0.932171 0.292878 +vn 0.528906 -0.436241 0.727978 +vn 0.292880 -0.932171 0.212790 +vn 0.727977 -0.436241 0.528907 +vn 0.344300 -0.932171 0.111870 +vn 0.855789 -0.436242 0.278063 +vn 0.362019 -0.932171 0.000001 +vn 0.899830 -0.436242 0.000001 +vn 0.360118 -0.925540 -0.117009 +vn 0.378649 -0.925540 0.000000 +vn 0.877053 -0.386743 -0.284971 +vn 0.922189 -0.386740 0.000001 +vn 0.746065 -0.386742 -0.542050 +vn 0.306334 -0.925540 -0.222566 +vn 0.542047 -0.386743 -0.746066 +vn 0.222565 -0.925540 -0.306334 +vn 0.284971 -0.386743 -0.877053 +vn 0.117009 -0.925540 -0.360117 +vn -0.000000 -0.386743 -0.922188 +vn 0.000000 -0.925540 -0.378650 +vn -0.284971 -0.386743 -0.877053 +vn -0.117009 -0.925540 -0.360117 +vn -0.542047 -0.386742 -0.746067 +vn -0.222565 -0.925540 -0.306334 +vn -0.746065 -0.386742 -0.542050 +vn -0.306334 -0.925540 -0.222564 +vn -0.877053 -0.386742 -0.284972 +vn -0.360117 -0.925541 -0.117008 +vn -0.922189 -0.386740 0.000000 +vn -0.378649 -0.925541 -0.000001 +vn -0.877053 -0.386742 0.284972 +vn -0.360117 -0.925541 0.117008 +vn -0.746065 -0.386742 0.542050 +vn -0.306334 -0.925540 0.222564 +vn -0.542047 -0.386742 0.746067 +vn -0.222564 -0.925540 0.306334 +vn -0.284972 -0.386743 0.877052 +vn -0.117009 -0.925540 0.360118 +vn 0.000000 -0.386744 0.922187 +vn 0.000000 -0.925541 0.378648 +vn 0.284972 -0.386744 0.877052 +vn 0.117009 -0.925541 0.360115 +vn 0.542048 -0.386742 0.746066 +vn 0.222564 -0.925540 0.306336 +vn 0.746065 -0.386742 0.542050 +vn 0.306334 -0.925540 0.222564 +vn 0.877054 -0.386740 0.284973 +vn 0.360117 -0.925541 0.117008 +vn 0.877053 0.386743 -0.284970 +vn 0.922189 0.386740 0.000001 +vn 0.360118 0.925540 -0.117010 +vn 0.378649 0.925540 0.000000 +vn 0.306334 0.925540 -0.222566 +vn 0.746066 0.386743 -0.542048 +vn 0.222565 0.925539 -0.306336 +vn 0.542048 0.386744 -0.746065 +vn 0.117009 0.925540 -0.360118 +vn 0.284970 0.386742 -0.877054 +vn 0.000000 0.925540 -0.378650 +vn 0.000000 0.386740 -0.922189 +vn -0.117009 0.925540 -0.360117 +vn -0.284970 0.386741 -0.877054 +vn -0.222565 0.925540 -0.306334 +vn -0.542048 0.386742 -0.746066 +vn -0.306334 0.925540 -0.222566 +vn -0.746066 0.386743 -0.542047 +vn -0.360116 0.925540 -0.117010 +vn -0.877053 0.386742 -0.284970 +vn -0.378649 0.925541 -0.000000 +vn -0.922189 0.386740 0.000001 +vn -0.360116 0.925540 0.117010 +vn -0.877053 0.386742 0.284971 +vn -0.306334 0.925540 0.222564 +vn -0.746066 0.386743 0.542048 +vn -0.222565 0.925541 0.306332 +vn -0.542048 0.386742 0.746066 +vn -0.117009 0.925542 0.360113 +vn -0.284971 0.386743 0.877053 +vn 0.000000 0.925540 0.378650 +vn -0.000000 0.386743 0.922188 +vn 0.117009 0.925539 0.360120 +vn 0.284971 0.386743 0.877053 +vn 0.222565 0.925541 0.306332 +vn 0.542048 0.386742 0.746066 +vn 0.306334 0.925541 0.222563 +vn 0.746066 0.386742 0.542048 +vn 0.360116 0.925540 0.117009 +vn 0.877054 0.386740 0.284971 +vn -0.264124 0.960663 0.085817 +vn -0.277716 0.960663 -0.000001 +vn -0.713848 0.660774 0.231944 +vn -0.750585 0.660774 -0.000000 +vn -0.607237 0.660773 0.441184 +vn -0.224677 0.960663 0.163236 +vn -0.441183 0.660774 0.607236 +vn -0.163237 0.960663 0.224677 +vn -0.231944 0.660773 0.713849 +vn -0.085819 0.960663 0.264124 +vn -0.000000 0.660772 0.750587 +vn -0.000000 0.960663 0.277717 +vn 0.231944 0.660773 0.713849 +vn 0.085819 0.960664 0.264122 +vn 0.441183 0.660774 0.607236 +vn 0.163238 0.960664 0.224675 +vn 0.607237 0.660773 0.441184 +vn 0.224677 0.960663 0.163236 +vn 0.713851 0.660772 0.231944 +vn 0.264124 0.960663 0.085818 +vn 0.750588 0.660771 -0.000000 +vn 0.277717 0.960663 0.000000 +vn 0.713850 0.660773 -0.231944 +vn 0.264124 0.960663 -0.085820 +vn 0.607236 0.660774 -0.441184 +vn 0.224677 0.960663 -0.163237 +vn 0.441183 0.660773 -0.607236 +vn 0.163238 0.960663 -0.224677 +vn 0.231944 0.660773 -0.713850 +vn 0.085819 0.960663 -0.264124 +vn -0.000000 0.660772 -0.750587 +vn -0.000000 0.960663 -0.277718 +vn -0.231944 0.660773 -0.713850 +vn -0.085819 0.960663 -0.264124 +vn -0.441183 0.660774 -0.607236 +vn -0.163238 0.960663 -0.224677 +vn -0.607235 0.660775 -0.441183 +vn -0.224678 0.960663 -0.163236 +vn -0.713849 0.660774 -0.231944 +vn -0.264124 0.960663 -0.085818 +s 1 +f 1/21/1 2/22/2 79/257/3 80/64/4 +f 2/22/2 3/23/5 78/255/6 79/257/3 +f 3/23/5 4/24/7 77/253/8 78/255/6 +f 4/24/7 5/25/9 76/251/10 77/253/8 +f 5/25/9 6/26/11 75/249/12 76/251/10 +f 6/26/11 7/27/13 74/247/14 75/249/12 +f 7/27/13 8/28/15 73/245/16 74/247/14 +f 8/28/15 9/29/17 72/243/18 73/245/16 +f 9/29/17 10/30/19 71/241/20 72/243/18 +f 10/30/19 11/31/21 70/239/22 71/241/20 +f 11/31/21 12/32/23 69/237/24 70/239/22 +f 12/32/23 13/33/25 68/235/26 69/237/24 +f 13/33/25 14/34/27 67/233/28 68/235/26 +f 14/34/27 15/35/29 66/231/30 67/233/28 +f 15/35/29 16/36/31 65/229/32 66/231/30 +f 16/36/31 17/37/33 64/227/34 65/229/32 +f 17/37/33 18/38/35 63/225/36 64/227/34 +f 18/38/35 19/39/37 82/263/38 63/225/36 +f 19/39/37 20/40/39 81/261/40 82/263/38 +f 20/40/39 1/41/1 80/259/4 81/261/40 +f 2/2/2 1/1/1 21/42/41 +f 3/3/5 2/2/2 21/42/41 +f 4/4/7 3/3/5 21/42/41 +f 5/5/9 4/4/7 21/42/41 +f 6/6/11 5/5/9 21/42/41 +f 7/7/13 6/6/11 21/42/41 +f 8/8/15 7/7/13 21/42/41 +f 9/9/17 8/8/15 21/42/41 +f 10/10/19 9/9/17 21/42/41 +f 11/11/21 10/10/19 21/42/41 +f 12/12/23 11/11/21 21/42/41 +f 13/13/25 12/12/23 21/42/41 +f 14/14/27 13/13/25 21/42/41 +f 15/15/29 14/14/27 21/42/41 +f 16/16/31 15/15/29 21/42/41 +f 17/17/33 16/16/31 21/42/41 +f 18/18/35 17/17/33 21/42/41 +f 19/19/37 18/18/35 21/42/41 +f 20/20/39 19/19/37 21/42/41 +f 1/1/1 20/20/39 21/42/41 +s 2 +f 42/44/42 43/45/43 44/43/44 +f 43/45/43 45/46/45 44/43/44 +f 45/46/45 46/47/46 44/43/44 +f 46/47/46 47/48/47 44/43/44 +f 47/48/47 48/49/48 44/43/44 +f 48/49/48 49/50/49 44/43/44 +f 49/50/49 50/51/50 44/43/44 +f 50/51/50 51/52/51 44/43/44 +f 51/52/51 52/53/52 44/43/44 +f 52/53/52 53/54/53 44/43/44 +f 53/54/53 54/55/54 44/43/44 +f 54/55/54 55/56/55 44/43/44 +f 55/56/55 56/57/56 44/43/44 +f 56/57/56 57/58/57 44/43/44 +f 57/58/57 58/59/58 44/43/44 +f 58/59/58 59/60/59 44/43/44 +f 59/60/59 60/61/60 44/43/44 +f 60/61/60 61/62/61 44/43/44 +f 61/62/61 62/63/62 44/43/44 +f 62/63/62 42/44/42 44/43/44 +s off +f 22/186/63 23/188/64 43/45/65 42/44/66 +f 23/188/67 24/190/68 45/46/69 43/45/70 +f 24/190/71 25/192/72 46/47/73 45/46/74 +f 25/192/75 26/194/76 47/48/77 46/47/78 +f 26/194/79 27/196/80 48/49/81 47/48/82 +f 27/196/83 28/198/84 49/50/85 48/49/86 +f 28/198/87 29/200/88 50/51/89 49/50/90 +f 29/200/91 30/202/92 51/52/93 50/51/94 +f 30/202/95 31/204/96 52/53/97 51/52/98 +f 31/204/99 32/206/100 53/54/101 52/53/102 +f 32/206/103 33/208/104 54/55/105 53/54/106 +f 33/208/107 34/210/108 55/56/109 54/55/110 +f 34/210/111 35/212/112 56/57/113 55/56/114 +f 35/212/115 36/214/116 57/58/117 56/57/118 +f 36/214/119 37/216/120 58/59/121 57/58/122 +f 37/216/123 38/218/124 59/60/125 58/59/126 +f 38/218/127 39/220/128 60/61/129 59/60/130 +f 39/220/131 40/222/132 61/62/133 60/61/134 +f 40/222/135 41/224/136 62/63/137 61/62/138 +f 41/224/139 22/186/140 42/44/141 62/63/142 +s 3 +f 83/103/143 86/65/144 146/68/145 143/66/146 +f 86/65/144 89/67/147 149/70/148 146/68/145 +f 89/67/147 92/69/149 152/72/150 149/70/148 +f 92/69/149 95/71/151 155/74/152 152/72/150 +f 95/71/151 98/73/153 158/76/154 155/74/152 +f 98/73/153 101/75/155 161/78/156 158/76/154 +f 101/75/155 104/77/157 164/80/158 161/78/156 +f 104/77/157 107/79/159 167/82/160 164/80/158 +f 107/79/159 110/81/161 170/84/162 167/82/160 +f 110/81/161 113/83/163 173/86/164 170/84/162 +f 113/83/163 116/85/165 176/88/166 173/86/164 +f 116/85/165 119/87/167 179/90/168 176/88/166 +f 119/87/167 122/89/169 182/92/170 179/90/168 +f 122/89/169 125/91/171 185/94/172 182/92/170 +f 125/91/171 128/93/173 188/96/174 185/94/172 +f 128/93/173 131/95/175 191/98/176 188/96/174 +f 131/95/175 134/97/177 194/100/178 191/98/176 +f 134/97/177 137/99/179 197/102/180 194/100/178 +f 137/99/179 140/101/181 200/104/182 197/102/180 +f 140/101/181 83/103/143 143/66/146 200/104/182 +s 4 +f 145/143/183 148/105/184 206/108/185 203/106/186 +f 148/105/184 151/107/187 209/110/188 206/108/185 +f 151/107/187 154/109/189 212/112/190 209/110/188 +f 154/109/189 157/111/191 215/114/192 212/112/190 +f 157/111/191 160/113/193 218/116/194 215/114/192 +f 160/113/193 163/115/195 221/118/196 218/116/194 +f 163/115/195 166/117/197 224/120/198 221/118/196 +f 166/117/197 169/119/199 227/122/200 224/120/198 +f 169/119/199 172/121/201 230/124/202 227/122/200 +f 172/121/201 175/123/203 233/126/204 230/124/202 +f 175/123/203 178/125/205 236/128/206 233/126/204 +f 178/125/205 181/127/207 239/130/208 236/128/206 +f 181/127/207 184/129/209 242/132/210 239/130/208 +f 184/129/209 187/131/211 245/134/212 242/132/210 +f 187/131/211 190/133/213 248/136/214 245/134/212 +f 190/133/213 193/135/215 251/138/216 248/136/214 +f 193/135/215 196/137/217 254/140/218 251/138/216 +f 196/137/217 199/139/219 257/142/220 254/140/218 +f 199/139/219 202/141/221 260/144/222 257/142/220 +f 202/141/221 145/143/183 203/106/186 260/144/222 +s 5 +f 205/183/223 208/145/224 266/148/225 263/146/226 +f 208/145/224 211/147/227 269/150/228 266/148/225 +f 211/147/227 214/149/229 272/152/230 269/150/228 +f 214/149/229 217/151/231 275/154/232 272/152/230 +f 217/151/231 220/153/233 278/156/234 275/154/232 +f 220/153/233 223/155/235 281/158/236 278/156/234 +f 223/155/235 226/157/237 284/160/238 281/158/236 +f 226/157/237 229/159/239 287/162/240 284/160/238 +f 229/159/239 232/161/241 290/164/242 287/162/240 +f 232/161/241 235/163/243 293/166/244 290/164/242 +f 235/163/243 238/165/245 296/168/246 293/166/244 +f 238/165/245 241/167/247 299/170/248 296/168/246 +f 241/167/247 244/169/249 302/172/250 299/170/248 +f 244/169/249 247/171/251 305/174/252 302/172/250 +f 247/171/251 250/173/253 308/176/254 305/174/252 +f 250/173/253 253/175/255 311/178/256 308/176/254 +f 253/175/255 256/177/257 314/180/258 311/178/256 +f 256/177/257 259/179/259 317/182/260 314/180/258 +f 259/179/259 262/181/261 320/184/262 317/182/260 +f 262/181/261 205/183/223 263/146/226 320/184/262 +s 6 +f 265/223/263 268/185/264 23/188/265 22/186/266 +f 268/185/264 271/187/267 24/190/268 23/188/265 +f 271/187/267 274/189/269 25/192/270 24/190/268 +f 274/189/269 277/191/271 26/194/272 25/192/270 +f 277/191/271 280/193/273 27/196/274 26/194/272 +f 280/193/273 283/195/275 28/198/276 27/196/274 +f 283/195/275 286/197/277 29/200/278 28/198/276 +f 286/197/277 289/199/279 30/202/280 29/200/278 +f 289/199/279 292/201/281 31/204/282 30/202/280 +f 292/201/281 295/203/283 32/206/284 31/204/282 +f 295/203/283 298/205/285 33/208/286 32/206/284 +f 298/205/285 301/207/287 34/210/288 33/208/286 +f 301/207/287 304/209/289 35/212/290 34/210/288 +f 304/209/289 307/211/291 36/214/292 35/212/290 +f 307/211/291 310/213/293 37/216/294 36/214/292 +f 310/213/293 313/215/295 38/218/296 37/216/294 +f 313/215/295 316/217/297 39/220/298 38/218/296 +f 316/217/297 319/219/299 40/222/300 39/220/298 +f 319/219/299 322/221/301 41/224/302 40/222/300 +f 322/221/301 265/223/263 22/186/266 41/224/302 +s 1 +f 64/227/34 63/225/36 136/264/303 133/226/304 +f 65/229/32 64/227/34 133/226/304 130/228/305 +f 66/231/30 65/229/32 130/228/305 127/230/306 +f 67/233/28 66/231/30 127/230/306 124/232/307 +f 68/235/26 67/233/28 124/232/307 121/234/308 +f 69/237/24 68/235/26 121/234/308 118/236/309 +f 70/239/22 69/237/24 118/236/309 115/238/310 +f 71/241/20 70/239/22 115/238/310 112/240/311 +f 72/243/18 71/241/20 112/240/311 109/242/312 +f 73/245/16 72/243/18 109/242/312 106/244/313 +f 74/247/14 73/245/16 106/244/313 103/246/314 +f 75/249/12 74/247/14 103/246/314 100/248/315 +f 76/251/10 75/249/12 100/248/315 97/250/316 +f 77/253/8 76/251/10 97/250/316 94/252/317 +f 78/255/6 77/253/8 94/252/317 91/254/318 +f 79/257/3 78/255/6 91/254/318 88/256/319 +f 80/64/4 79/257/3 88/256/319 85/258/320 +f 81/261/40 80/259/4 85/265/320 142/260/321 +f 82/263/38 81/261/40 142/260/321 139/262/322 +f 63/225/36 82/263/38 139/262/322 136/264/303 +s 3 +f 83/103/143 84/266/323 87/270/324 86/65/144 +s 1 +f 84/268/325 85/258/320 88/256/319 87/269/326 +s 3 +f 86/65/144 87/270/324 90/272/327 89/67/147 +s 1 +f 87/269/326 88/256/319 91/254/318 90/271/328 +s 3 +f 89/67/147 90/272/327 93/274/329 92/69/149 +s 1 +f 90/271/328 91/254/318 94/252/317 93/273/330 +s 3 +f 92/69/149 93/274/329 96/276/331 95/71/151 +s 1 +f 93/273/330 94/252/317 97/250/316 96/275/332 +s 3 +f 95/71/151 96/276/331 99/278/333 98/73/153 +s 1 +f 96/275/332 97/250/316 100/248/315 99/277/334 +s 3 +f 98/73/153 99/278/333 102/280/335 101/75/155 +s 1 +f 99/277/334 100/248/315 103/246/314 102/279/336 +s 3 +f 101/75/155 102/280/335 105/282/337 104/77/157 +s 1 +f 102/279/336 103/246/314 106/244/313 105/281/338 +s 3 +f 104/77/157 105/282/337 108/284/339 107/79/159 +s 1 +f 105/281/338 106/244/313 109/242/312 108/283/340 +s 3 +f 107/79/159 108/284/339 111/286/341 110/81/161 +s 1 +f 108/283/340 109/242/312 112/240/311 111/285/342 +s 3 +f 110/81/161 111/286/341 114/288/343 113/83/163 +s 1 +f 111/285/342 112/240/311 115/238/310 114/287/344 +s 3 +f 113/83/163 114/288/343 117/290/345 116/85/165 +s 1 +f 114/287/344 115/238/310 118/236/309 117/289/346 +s 3 +f 116/85/165 117/290/345 120/292/347 119/87/167 +s 1 +f 117/289/346 118/236/309 121/234/308 120/291/348 +s 3 +f 119/87/167 120/292/347 123/294/349 122/89/169 +s 1 +f 120/291/348 121/234/308 124/232/307 123/293/350 +s 3 +f 122/89/169 123/294/349 126/296/351 125/91/171 +s 1 +f 123/293/350 124/232/307 127/230/306 126/295/352 +s 3 +f 125/91/171 126/296/351 129/298/353 128/93/173 +s 1 +f 126/295/352 127/230/306 130/228/305 129/297/354 +s 3 +f 128/93/173 129/298/353 132/300/355 131/95/175 +s 1 +f 129/297/354 130/228/305 133/226/304 132/299/356 +s 3 +f 131/95/175 132/300/355 135/302/357 134/97/177 +s 1 +f 132/299/356 133/226/304 136/264/303 135/301/358 +s 3 +f 134/97/177 135/302/357 138/304/359 137/99/179 +s 1 +f 135/301/358 136/264/303 139/262/322 138/303/360 +s 3 +f 137/99/179 138/304/359 141/306/361 140/101/181 +s 1 +f 138/303/360 139/262/322 142/260/321 141/305/362 +f 85/265/320 84/267/325 141/305/362 142/260/321 +s 3 +f 84/266/323 83/103/143 140/101/181 141/306/361 +f 143/66/146 144/307/363 201/326/364 200/104/182 +s 4 +f 144/307/365 145/143/183 202/141/221 201/326/366 +f 145/143/183 144/307/365 147/308/367 148/105/184 +s 3 +f 144/307/363 143/66/146 146/68/145 147/308/368 +s 4 +f 148/105/184 147/308/367 150/309/369 151/107/187 +s 3 +f 147/308/368 146/68/145 149/70/148 150/309/370 +s 4 +f 151/107/187 150/309/369 153/310/371 154/109/189 +s 3 +f 150/309/370 149/70/148 152/72/150 153/310/372 +s 4 +f 154/109/189 153/310/371 156/311/373 157/111/191 +s 3 +f 153/310/372 152/72/150 155/74/152 156/311/374 +s 4 +f 157/111/191 156/311/373 159/312/375 160/113/193 +s 3 +f 156/311/374 155/74/152 158/76/154 159/312/376 +s 4 +f 160/113/193 159/312/375 162/313/377 163/115/195 +s 3 +f 159/312/376 158/76/154 161/78/156 162/313/378 +s 4 +f 163/115/195 162/313/377 165/314/379 166/117/197 +s 3 +f 162/313/378 161/78/156 164/80/158 165/314/380 +s 4 +f 166/117/197 165/314/379 168/315/381 169/119/199 +s 3 +f 165/314/380 164/80/158 167/82/160 168/315/382 +s 4 +f 169/119/199 168/315/381 171/316/383 172/121/201 +s 3 +f 168/315/382 167/82/160 170/84/162 171/316/384 +s 4 +f 172/121/201 171/316/383 174/317/385 175/123/203 +s 3 +f 171/316/384 170/84/162 173/86/164 174/317/386 +s 4 +f 175/123/203 174/317/385 177/318/387 178/125/205 +s 3 +f 174/317/386 173/86/164 176/88/166 177/318/388 +s 4 +f 178/125/205 177/318/387 180/319/389 181/127/207 +s 3 +f 177/318/388 176/88/166 179/90/168 180/319/390 +s 4 +f 181/127/207 180/319/389 183/320/391 184/129/209 +s 3 +f 180/319/390 179/90/168 182/92/170 183/320/392 +s 4 +f 184/129/209 183/320/391 186/321/393 187/131/211 +s 3 +f 183/320/392 182/92/170 185/94/172 186/321/394 +s 4 +f 187/131/211 186/321/393 189/322/395 190/133/213 +s 3 +f 186/321/394 185/94/172 188/96/174 189/322/396 +s 4 +f 190/133/213 189/322/395 192/323/397 193/135/215 +s 3 +f 189/322/396 188/96/174 191/98/176 192/323/398 +s 4 +f 193/135/215 192/323/397 195/324/399 196/137/217 +s 3 +f 192/323/398 191/98/176 194/100/178 195/324/400 +s 4 +f 196/137/217 195/324/399 198/325/401 199/139/219 +s 3 +f 195/324/400 194/100/178 197/102/180 198/325/402 +s 4 +f 199/139/219 198/325/401 201/326/366 202/141/221 +s 3 +f 198/325/402 197/102/180 200/104/182 201/326/364 +s 4 +f 203/106/186 204/327/403 261/346/404 260/144/222 +s 5 +f 204/327/405 205/183/223 262/181/261 261/346/406 +f 205/183/223 204/327/405 207/328/407 208/145/224 +s 4 +f 204/327/403 203/106/186 206/108/185 207/328/408 +s 5 +f 208/145/224 207/328/407 210/329/409 211/147/227 +s 4 +f 207/328/408 206/108/185 209/110/188 210/329/410 +s 5 +f 211/147/227 210/329/409 213/330/411 214/149/229 +s 4 +f 210/329/410 209/110/188 212/112/190 213/330/412 +s 5 +f 214/149/229 213/330/411 216/331/413 217/151/231 +s 4 +f 213/330/412 212/112/190 215/114/192 216/331/414 +s 5 +f 217/151/231 216/331/413 219/332/415 220/153/233 +s 4 +f 216/331/414 215/114/192 218/116/194 219/332/416 +s 5 +f 220/153/233 219/332/415 222/333/417 223/155/235 +s 4 +f 219/332/416 218/116/194 221/118/196 222/333/418 +s 5 +f 223/155/235 222/333/417 225/334/419 226/157/237 +s 4 +f 222/333/418 221/118/196 224/120/198 225/334/420 +s 5 +f 226/157/237 225/334/419 228/335/421 229/159/239 +s 4 +f 225/334/420 224/120/198 227/122/200 228/335/422 +s 5 +f 229/159/239 228/335/421 231/336/423 232/161/241 +s 4 +f 228/335/422 227/122/200 230/124/202 231/336/424 +s 5 +f 232/161/241 231/336/423 234/337/425 235/163/243 +s 4 +f 231/336/424 230/124/202 233/126/204 234/337/426 +s 5 +f 235/163/243 234/337/425 237/338/427 238/165/245 +s 4 +f 234/337/426 233/126/204 236/128/206 237/338/428 +s 5 +f 238/165/245 237/338/427 240/339/429 241/167/247 +s 4 +f 237/338/428 236/128/206 239/130/208 240/339/430 +s 5 +f 241/167/247 240/339/429 243/340/431 244/169/249 +s 4 +f 240/339/430 239/130/208 242/132/210 243/340/432 +s 5 +f 244/169/249 243/340/431 246/341/433 247/171/251 +s 4 +f 243/340/432 242/132/210 245/134/212 246/341/434 +s 5 +f 247/171/251 246/341/433 249/342/435 250/173/253 +s 4 +f 246/341/434 245/134/212 248/136/214 249/342/436 +s 5 +f 250/173/253 249/342/435 252/343/437 253/175/255 +s 4 +f 249/342/436 248/136/214 251/138/216 252/343/438 +s 5 +f 253/175/255 252/343/437 255/344/439 256/177/257 +s 4 +f 252/343/438 251/138/216 254/140/218 255/344/440 +s 5 +f 256/177/257 255/344/439 258/345/441 259/179/259 +s 4 +f 255/344/440 254/140/218 257/142/220 258/345/442 +s 5 +f 259/179/259 258/345/441 261/346/406 262/181/261 +s 4 +f 258/345/442 257/142/220 260/144/222 261/346/404 +s 5 +f 263/146/226 264/347/443 321/366/444 320/184/262 +s 6 +f 264/347/445 265/223/263 322/221/301 321/366/446 +f 265/223/263 264/347/445 267/348/447 268/185/264 +s 5 +f 264/347/443 263/146/226 266/148/225 267/348/448 +s 6 +f 268/185/264 267/348/447 270/349/449 271/187/267 +s 5 +f 267/348/448 266/148/225 269/150/228 270/349/450 +s 6 +f 271/187/267 270/349/449 273/350/451 274/189/269 +s 5 +f 270/349/450 269/150/228 272/152/230 273/350/452 +s 6 +f 274/189/269 273/350/451 276/351/453 277/191/271 +s 5 +f 273/350/452 272/152/230 275/154/232 276/351/454 +s 6 +f 277/191/271 276/351/453 279/352/455 280/193/273 +s 5 +f 276/351/454 275/154/232 278/156/234 279/352/456 +s 6 +f 280/193/273 279/352/455 282/353/457 283/195/275 +s 5 +f 279/352/456 278/156/234 281/158/236 282/353/458 +s 6 +f 283/195/275 282/353/457 285/354/459 286/197/277 +s 5 +f 282/353/458 281/158/236 284/160/238 285/354/460 +s 6 +f 286/197/277 285/354/459 288/355/461 289/199/279 +s 5 +f 285/354/460 284/160/238 287/162/240 288/355/462 +s 6 +f 289/199/279 288/355/461 291/356/463 292/201/281 +s 5 +f 288/355/462 287/162/240 290/164/242 291/356/464 +s 6 +f 292/201/281 291/356/463 294/357/465 295/203/283 +s 5 +f 291/356/464 290/164/242 293/166/244 294/357/466 +s 6 +f 295/203/283 294/357/465 297/358/467 298/205/285 +s 5 +f 294/357/466 293/166/244 296/168/246 297/358/468 +s 6 +f 298/205/285 297/358/467 300/359/469 301/207/287 +s 5 +f 297/358/468 296/168/246 299/170/248 300/359/470 +s 6 +f 301/207/287 300/359/469 303/360/471 304/209/289 +s 5 +f 300/359/470 299/170/248 302/172/250 303/360/472 +s 6 +f 304/209/289 303/360/471 306/361/473 307/211/291 +s 5 +f 303/360/472 302/172/250 305/174/252 306/361/474 +s 6 +f 307/211/291 306/361/473 309/362/475 310/213/293 +s 5 +f 306/361/474 305/174/252 308/176/254 309/362/476 +s 6 +f 310/213/293 309/362/475 312/363/477 313/215/295 +s 5 +f 309/362/476 308/176/254 311/178/256 312/363/478 +s 6 +f 313/215/295 312/363/477 315/364/479 316/217/297 +s 5 +f 312/363/478 311/178/256 314/180/258 315/364/480 +s 6 +f 316/217/297 315/364/479 318/365/481 319/219/299 +s 5 +f 315/364/480 314/180/258 317/182/260 318/365/482 +s 6 +f 319/219/299 318/365/481 321/366/446 322/221/301 +s 5 +f 318/365/482 317/182/260 320/184/262 321/366/444 diff --git a/src/lsystem.js b/src/lsystem.js index e643b6d..b976d4a 100644 --- a/src/lsystem.js +++ b/src/lsystem.js @@ -1,76 +1,327 @@ -// A class that represents a symbol replacement rule to -// be used when expanding an L-system grammar. -function Rule(prob, str) { - this.probability = prob; // The probability that this Rule will be used when replacing a character in the grammar string - this.successorString = str; // The string that will replace the char that maps to this Rule +var Random = require("random-js"); + +class LContext +{ + constructor() + { + this.branched = false; + } + + copy() + { + return new LContext(); + } } -// TODO: Implement a linked list class and its requisite functions -// as described in the homework writeup -// TODO: Turn the string into linked list -export function stringToLinkedList(input_string) { - // ex. assuming input_string = "F+X" - // you should return a linked list where the head is - // at Node('F') and the tail is at Node('X') - var ll = new LinkedList(); - return ll; +// An instruction is essentially a symbol with logic, context, stack and (TODO) parameters +class LInstruction +{ + symbol() { return "A"; } + evaluate(context, stack) { return context; } +} + +// Dummy instructions can be anything, they are used for replacement +// Generic instruction +class DummyInstruction extends LInstruction +{ + constructor(symbol) { super(); this.dummySymbol = symbol; } + + symbol() { return this.dummySymbol; } + + evaluate(context, stack) { + return null; + } } -// TODO: Return a string form of the LinkedList -export function linkedListToString(linkedList) { - // ex. Node1("F")->Node2("X") should be "FX" - var result = ""; - return result; +// Generic instruction +class PushInstruction extends LInstruction +{ + symbol() { return "["; } + + evaluate(context, stack) { + stack.push(context); + return null; + } } -// TODO: Given the node to be replaced, -// insert a sub-linked-list that represents replacementString -function replaceNode(linkedList, node, replacementString) { +// Generic instruction +class PullInstruction extends LInstruction +{ + symbol() { return "]"; } + + evaluate(context, stack) { + var c = stack.pop(context); + c.branched = true; + return c; + } } -export default function Lsystem(axiom, grammar, iterations) { - // default LSystem - this.axiom = "FX"; - this.grammar = {}; - this.grammar['X'] = [ - new Rule(1.0, '[-FX][+FX]') - ]; - this.iterations = 0; - - // Set up the axiom string - if (typeof axiom !== "undefined") { - this.axiom = axiom; +// A grammar chain is a doubly linked list of instructions +// that can be modified by given rules +class LInstructionChain +{ + constructor() + { + this.root = null; + this.last = null; + } + + push(value) + { + if(this.root == null) + { + this.root = { prev: null, next: null, value: value, new : false}; + this.last = this.root; + } + else if(this.last != null) + { + var node = { prev: this.last, next: null, value: value, new : true}; + this.last.next = node; + this.last = node; + } + + return this.last; + } + + // Evaluates a chain of instructions, both with a context and a stack + evaluate(initialState) + { + var contextStack = []; + var context = initialState; + var stateArray = [context.copy()]; + + this.evaluateInternal(function(node) { + var c = node.value.evaluate(context.copy(), contextStack); + + // Some instructions may not want to modify the context + if(c != null) + { + // Debug data :D + c.relatedInstruction = node.value; + stateArray.push(c); + + context = c; + } + }); + + return stateArray; + } + + evaluateInternal(evaluateFunc) + { + this.iterate(null, null, evaluateFunc); + } + + // General purpose iteration function + iterate(condition, returnFunc, evaluateFunc = null) + { + var node = this.root; + + while(node != null) { + + if(evaluateFunc != null) + evaluateFunc(node); + + if(returnFunc != null && condition != null && condition(node)) + return returnFunc(node); + + node = node.next; + } + + return null; + } + + toString() + { + var result = ""; + this.evaluateInternal(function(node) { result += node.value.symbol(); } ); + return result; + } + + findAll(value) + { + var nodes = []; + this.iterate(null, null, function(node) { if(node.value == value) nodes.push(node); }); + return nodes; + } + + find(value) + { + return this.iterate(function(node){return node.value == value;}, function(node) { return node } ); + } + + // Because we're expanding in-place, we must be careful not to + // expand recently added nodes that come from a previous replacement + // in the same expansion cycle. + expand(rules, random) + { + var node = this.root; + + while(node != null) + { + // Get next before replacement + var next = node.next; + + for(var pred in rules) + { + if (rules.hasOwnProperty(pred)) + { + var ruleArray = rules[pred]; + var replaced = false; + + var randomValue = random.real(0, 1, true); + + for(var r = 0; r < ruleArray.length && !replaced; r++) + { + if(node.value == ruleArray[r].predecessor) + { + if(ruleArray[r].probability >= 1.0 || ruleArray[r].probability > randomValue) + { + this.replace(node, ruleArray[r].successor); + replaced = true; + break; + } + else + { + randomValue -= ruleArray[r].probability; + } + } + } + } + } + + node = next; + } + } + + // Now it only replaces one symbol. TODO context aware rules + replaceSymbol(v, values) + { + this.replace(this.find(v), values); + } + + replace(node, values) + { + if(node == null) + return; + + var prevNode = node.prev; + this.last = prevNode; + + if(this.root == node) + this.root = this.last; + + for(var i = 0; i < values.length; i++) + this.push(values[i]); + + // Reconnect the chain, while ignoring the replaced node + if(this.last != null) + { + this.last.next = node.next; + + if(node.next != null) + node.next.prev = this.last; + + // Make sure we update the last node + while(this.last.next != null) + this.last = this.last.next; + } + } +} + +// Just an auxiliary container of strings +function LRule(predecessor, successor, probability) +{ + this.predecessor = predecessor; + this.successor = successor; + this.probability = probability; +} + +function LSystem(axiom, instructions, rules, iterations, random) +{ + this.registerInstruction = function(instruction) + { + this.instructionMap[instruction.symbol()] = instruction; + } + + this.getInstruction = function(symbol) + { + if(!(symbol in this.instructionMap)) + console.error("Symbol " + symbol + " not present in instruction map!"); + + return this.instructionMap[symbol]; + } + + this.parseAxiom = function(axiomSymbols) + { + this.chain = new LInstructionChain(); + + for(var i = 0; i < axiomSymbols.length; i++) + this.chain.push(this.getInstruction(axiomSymbols[i])); } - // Set up the grammar as a dictionary that - // maps a single character (symbol) to a Rule. - if (typeof grammar !== "undefined") { - this.grammar = Object.assign({}, grammar); + this.updateAxiom = function(axiom) + { + this.axiom = axiom; + this.parseAxiom(axiom); } - - // Set up iterations (the number of times you - // should expand the axiom in DoIterations) - if (typeof iterations !== "undefined") { - this.iterations = iterations; + + this.parseRule = function(predecessor, successorList, probability) + { + var predInstruction = this.getInstruction(predecessor); + var successorInstructions = []; + + for(var i = 0; i < successorList.length; i++) + successorInstructions.push(this.getInstruction(successorList[i])); + + if(!(predecessor in this.ruleMap)) + this.ruleMap[predecessor] = []; + + this.ruleMap[predecessor].push( { predecessor: predInstruction, successor: successorInstructions, probability: probability }); } - // A function to alter the axiom string stored - // in the L-system - this.updateAxiom = function(axiom) { - // Setup axiom - if (typeof axiom !== "undefined") { - this.axiom = axiom; + this.expand = function() + { + var t = performance.now(); + + // Reset the chain + this.updateAxiom(this.axiom); + + for(var i = 0; i < this.iterations; i++) + { + this.chain.expand(this.ruleMap, this.random); } + + t = performance.now() - t; + + // console.log("Expansion took " + t.toFixed(1) + "ms"); + + return this.chain; } - // TODO - // This function returns a linked list that is the result - // of expanding the L-system's axiom n times. - // The implementation we have provided you just returns a linked - // list of the axiom. - this.doIterations = function(n) { - var lSystemLL = StringToLinkedList(this.axiom); - return lSystemLL; + this.evaluate = function(initialState) + { + return this.chain.evaluate(initialState); } -} \ No newline at end of file + + this.iterations = iterations; + this.instructionMap = {}; + this.ruleMap = {}; + this.chain = new LInstructionChain(); + this.random = random; + + // Register common instructions + this.registerInstruction(new PushInstruction()); + this.registerInstruction(new PullInstruction()); + + for(var i = 0; i < instructions.length; i++) + this.registerInstruction(instructions[i]); + + for(var r = 0; r < rules.length; r++) + this.parseRule(rules[r].predecessor, rules[r].successor, rules[r].probability); + + this.updateAxiom(axiom); +} + +export {LSystem, LContext, LRule, LInstruction, DummyInstruction} \ No newline at end of file diff --git a/src/main.js b/src/main.js index f0c6600..0b3aa9b 100644 --- a/src/main.js +++ b/src/main.js @@ -1,12 +1,12 @@ const THREE = require('three'); // older modules are imported like this. You shouldn't have to worry about this much import Framework from './framework' -import Lsystem, {LinkedListToString} from './lsystem.js' +import LSystem from './lsystem.js' import Turtle from './turtle.js' +import {PlantLSystem, MainCharacter, CactusCharacter, WillowCharacter} from './plants.js' var turtle; -// called after the scene loads function onLoad(framework) { var scene = framework.scene; var camera = framework.camera; @@ -22,26 +22,95 @@ function onLoad(framework) { scene.add(directionalLight); // set camera position - camera.position.set(1, 1, 2); - camera.lookAt(new THREE.Vector3(0,0,0)); + camera.position.set(2, 3, 4); + camera.lookAt(new THREE.Vector3(0,2,0)); - // initialize LSystem and a Turtle to draw - var lsys = new Lsystem(); - turtle = new Turtle(scene); - gui.add(camera, 'fov', 0, 180).onChange(function(newVal) { - camera.updateProjectionMatrix(); - }); + var UserSettings = + { + iterations : 5, + willow : null, + main : null, + cactus : null, + rebuild : function() { RebuildTrees(scene, UserSettings) } + } - gui.add(lsys, 'axiom').onChange(function(newVal) { - lsys.UpdateAxiom(newVal); - doLsystem(lsys, lsys.iterations, turtle); - }); + // // initialize LSystem and a Turtle to draw + // var lsys = new Lsystem(); + // turtle = new Turtle(scene); - gui.add(lsys, 'iterations', 0, 12).step(1).onChange(function(newVal) { - clearScene(turtle); - doLsystem(lsys, newVal, turtle); + gui.add(UserSettings, 'rebuild', 0, 180); + // gui.add(lsys, 'axiom').onChange(function(newVal) { + // lsys.UpdateAxiom(newVal); + // doLsystem(lsys, lsys.iterations, turtle); + // }); + + gui.add(UserSettings, 'iterations', 0, 8).step(1).onChange(function(newVal) { + // clearScene(turtle); + // doLsystem(lsys, newVal, turtle); + RebuildTrees(scene, UserSettings); }); + + // var lSystem = new LSystem("FX", "", 10); + // lSystem.expand(); + + var lSystem = new MainCharacter(2234, 5); + var expandedChain = lSystem.expand(); + + var mesh = lSystem.generateMesh(); + mesh.scale.set(.3, .3, .3); + scene.add(mesh); + + var cactus = new CactusCharacter(6565, 6); + cactus.expand(); + var cactusMesh = cactus.generateMesh(); + cactusMesh.position.set(2, 0, 0); + cactusMesh.scale.set(.2, .2, .2); + scene.add(cactusMesh); + + var willow = new WillowCharacter(2135, 5); + willow.expand(); + var willowMesh = willow.generateMesh(); + willowMesh.position.set(-2, 0, 0); + willowMesh.scale.set(.2, .2, .2); + scene.add(willowMesh); + + UserSettings.willow = willowMesh; + UserSettings.main = mesh; + UserSettings.cactus = cactusMesh; +} + +function RebuildTrees(scene, UserSettings) +{ + scene.remove(UserSettings.willow); + scene.remove(UserSettings.main); + scene.remove(UserSettings.cactus); + + var lSystem = new MainCharacter(performance.now(), UserSettings.iterations); + lSystem.expand(); + var mesh = lSystem.generateMesh(); + mesh.scale.set(.3, .3, .3); + scene.add(mesh); + + var cactus = new CactusCharacter(performance.now(), UserSettings.iterations); + cactus.expand(); + var cactusMesh = cactus.generateMesh(); + cactusMesh.position.set(2, 0, 0); + cactusMesh.scale.set(.2, .2, .2); + scene.add(cactusMesh); + + var willow = new WillowCharacter(performance.now(), UserSettings.iterations); + willow.expand(); + var willowMesh = willow.generateMesh(); + willowMesh.position.set(-2, 0, 0); + willowMesh.scale.set(.2, .2, .2); + scene.add(willowMesh); + + + UserSettings.willow = willowMesh; + UserSettings.main = mesh; + UserSettings.cactus = cactusMesh; + } // clears the scene by removing all geometries added by turtle.js diff --git a/src/plants.js b/src/plants.js new file mode 100644 index 0000000..2eb66c2 --- /dev/null +++ b/src/plants.js @@ -0,0 +1,607 @@ +const THREE = require('three'); +var Random = require("random-js"); + +import { LSystem, LContext, LRule, LInstruction, DummyInstruction } from './lsystem.js' + +function toRadians(degrees) +{ + return degrees * Math.PI / 180.0; +} + +function randomTwistRotation(random, twist) +{ + var a = twist; + var euler = new THREE.Euler(0, a * random.real(.75, 1), 0); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + return quat; +} + +function randomQuaternion(random, amplitude) +{ + var a = amplitude * .5; + var euler = new THREE.Euler(a * random.real(-1,1, true), a * random.real(-1,1, true), a * random.real(-1,1, true)); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + return quat; +} + +class CrossSectionParameters +{ + constructor(a, b, m1, m2, n1, n2, n3) + { + this.a = a; + this.b = b; + this.m1 = m1; + this.m2 = m2; + this.n1 = n1; + this.n2 = n2; + this.n3 = n3; + } + + evaluate(t) + { + var term1 = Math.pow(Math.abs(Math.cos(this.m1 * t * .25) / this.a), this.n2); + var term2 = Math.pow(Math.abs(Math.sin(this.m2 * t * .25) / this.b), this.n3); + return Math.pow(term1 + term2, -1.0 / this.n1); + } + + copy() + { + return new CrossSectionParameters(this.a, this.b, this.m1, this.m2, this.n1, this.n2, this.n3); + } +} + +class PlantContext extends LContext +{ + constructor(position, rotation, branchLength, branchRadius, crossSection, random) + { + super(); + + this.position = position.clone(); + this.rotation = rotation.clone(); + this.branchLength = branchLength; + this.branchRadius = branchRadius; + this.random = random; + this.crossSection = crossSection; + this.renderable = false; + this.flower = false; + this.depth = 0; + } + + copy() + { + var c = new PlantContext(this.position, this.rotation, this.branchLength, this.branchRadius, this.crossSection.copy(), this.random); + c.depth = this.depth; + return c; + } +} + +class LInstructionOverride extends LInstruction +{ + constructor(symbolCharacter, instruction) + { + super(); + this.symbolCharacter = symbolCharacter; + this.instruction = instruction; + } + + symbol() + { + return this.symbolCharacter; + } + + evaluate(context, stack) + { + return this.instruction.evaluate(context, stack); + } +} + +// A more specific instruction that can modify branches +class BranchInstruction extends LInstruction +{ + constructor(sizeFactor, radiusFactor) + { + super(); + this.sizeFactor = sizeFactor; + this.radiusFactor = radiusFactor; + } + + symbol() { return "B"; } + + evaluate(context, stack) + { + var c = context; + c.branchLength *= this.sizeFactor; + c.branchRadius *= this.radiusFactor; + c.branched = true; + + // For now, when branching we lose all fine details + c.crossSection = new CrossSectionParameters(1,1,1,1,1,1,1); + return c; + } +} + +class RootInstruction extends LInstruction +{ + constructor(sizeFactor) + { + super(); + this.sizeFactor = sizeFactor; + } + + symbol() { return "R"; } + + evaluate(context, stack) + { + var c = context; + c.position.add(new THREE.Vector3(0, context.branchLength * .2, 0).applyQuaternion(c.rotation)); + c.renderable = true; + c.branchRadius *= this.sizeFactor; + return c; + } +} + +// Main branch +class ForwardInstruction extends LInstruction +{ + constructor(twistFactor) + { + super(); + this.twistFactor = twistFactor; + } + + symbol() { return "F"; } + + evaluate(context, stack) + { + var c = context; + c.position.add(new THREE.Vector3(0, context.branchLength, 0).applyQuaternion(c.rotation)); + c.branchRadius += c.random.real(-.2, .2, true) * c.branchRadius; + c.rotation.multiply(randomTwistRotation(c.random, this.twistFactor)); + c.renderable = true; + c.depth++; + return c; + } +} + +class DetailInstruction extends LInstruction +{ + constructor(rotationFactor, minLength, maxLength, twistFactor) + { + super(); + this.rotationFactor = rotationFactor; + this.minLength = minLength; + this.maxLength = maxLength; + this.twistFactor = twistFactor; + } + + symbol() { return "Q"; } + + evaluate(context, stack) + { + var c = context; + c.position.add(new THREE.Vector3(0, c.random.real(this.minLength, this.maxLength) * c.branchLength, 0).applyQuaternion(c.rotation)); + c.renderable = true; + c.rotation.multiply(randomTwistRotation(c.random, this.twistFactor)); + c.rotation.multiply(randomQuaternion(c.random, this.rotationFactor)); + c.branchRadius += c.random.real(-.1, .1, true) * c.branchRadius; + c.depth++; + return c; + } +} + +class RotatePositiveInstruction extends LInstruction +{ + constructor(angle) + { + super(); + this.angle = angle; + } + + symbol() { return "+"; } + + evaluate(context, stack) { + var c = context; + + var euler = new THREE.Euler(0, c.random.real(-Math.PI, Math.PI), this.angle * c.random.real(.5, 1)); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + + c.rotation.multiply(quat); + + // Jump to the boundary of the tree + c.position.add(new THREE.Vector3(0, context.branchRadius, 0).applyQuaternion(c.rotation)); + + return c; + } +} + +class RotateNegativeInstruction extends LInstruction +{ + symbol() { return "-"; } + + evaluate(context, stack) { + var c = context; + + var euler = new THREE.Euler(0, c.random.real(-Math.PI, Math.PI), -1.25 * c.random.real(.5, 1)); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + + c.rotation.multiply(quat); + + // Jump to the boundary of the tree + c.position.add(new THREE.Vector3(0, context.branchRadius, 0).applyQuaternion(c.rotation)); + return c; + } +} + +class FlowerInstruction extends LInstruction +{ + symbol() { return "W"; } + + evaluate(context, stack) + { + context.flower = true; + return context; + } +} + +export default class PlantLSystem +{ + constructor() {} + + expand() + { + return this.system.expand(); + } + + evaluate() + { + // (a, b, m1, m2, n1, n2, n3) + var crossSection = new CrossSectionParameters(1,1,2,10,-1.5,1,1); + var state = new PlantContext(new THREE.Vector3(0,0,0), new THREE.Quaternion().setFromEuler(new THREE.Euler(0,0,0)), 1.0, .95, crossSection, this.system.random); + return this.system.evaluate(state); + } + + generateCrossSectionVertices(geometry, state, subdivs, lastSectionOfBranch, nextState) + { + var centerPoint = state.position; + + for(var s = 0; s < subdivs; s++) + { + var theta = s * 2 * 3.1415 / subdivs; + var x = Math.cos(theta); + var y = Math.sin(theta); + + var r = state.crossSection.evaluate(theta) * state.branchRadius; + + if(lastSectionOfBranch) + r *= .5; + + var quat = state.rotation; + + if(state.branched && nextState != null) + quat = nextState.rotation; + + var point = centerPoint.clone().add(new THREE.Vector3(x * r, 0, y * r).applyQuaternion(quat)); + + geometry.vertices.push(point); + } + } + + generateMesh() + { + var plantContainer = new THREE.Group(); + + var material = new THREE.MeshLambertMaterial({ color: 0xffffff, emissive: 0x333333 }); + material.side = THREE.DoubleSide; + + var stateArray = this.evaluate(); + + var t = performance.now(); + + var flowerGeometry = new THREE.SphereBufferGeometry(.1, 16, 16); + var geometry = new THREE.Geometry(); + var prevPosition = stateArray[0].position; + var subdivs = this.subdivisions; + var segments = 0; + var maxDepth = 0; + + // We need to find the max depth, so that we can normalize other stuff + for(var i = 0; i < stateArray.length; i++) + if(stateArray[i].depth > maxDepth) + maxDepth = stateArray[i].depth; + + // We always draw backwards, with consideration of branching and the first case + for(var i = 0; i < stateArray.length; i++) + { + var p = stateArray[i].position; + var offset = geometry.vertices.length - subdivs; + + var lastSectionOfBranch = (i == stateArray.length - 1) || stateArray[i+1].branched; + + // Note: if the grammar branched, we need to redraw the initial set of vertices + if(i == 0 || stateArray[i].renderable || stateArray[i].branched) + { + var nextState = i < stateArray.length - 1 ? stateArray[i+1] : null; + this.generateCrossSectionVertices(geometry, stateArray[i], subdivs, lastSectionOfBranch, nextState); + } + + if(stateArray[i].flower) + { + var sphere = new THREE.Mesh(flowerGeometry, material); + var scale = this.system.random.real(.15, 4); + sphere.position.copy(stateArray[i].position.add(new THREE.Vector3(0, -scale * .1, 0))); + + sphere.scale.set(scale, scale, scale); + plantContainer.add(sphere); + } + + if((prevPosition.distanceTo(p) > .01 && stateArray[i].renderable)) + { + // console.log(stateArray[i].position); + // console.log(stateArray[i-1].position); + // console.log('') + + if(offset >= 0) + { + for(var v = 0; v < subdivs; v++) + { + var v1 = offset + v; + var v2 = offset + ((v + 1) % subdivs); + var v3 = offset + subdivs + ((v + 1) % subdivs); + + var v4 = offset + v; + var v5 = offset + subdivs + ((v + 1) % subdivs); + var v6 = offset + subdivs + v; + + geometry.faces.push(new THREE.Face3(v3, v2, v1)); + geometry.faces.push(new THREE.Face3(v6, v5, v4)); + } + + segments++; + } + } + + prevPosition = p; + } + + // console.log(stateArray); + + geometry.mergeVertices(); + geometry.computeVertexNormals(); + + // console.log("Mesh generation took " + t.toFixed(1) + "ms (" + segments + " segments, " + subdivs + " subdivs, " + geometry.vertices.length + " vertices)"); + + var mesh = new THREE.Mesh(geometry, material); + + plantContainer.add(mesh); + return plantContainer; + } + + getLineDebugger() + { + var material = new THREE.LineBasicMaterial({ color: 0xffffff }); + material.transparent = true; + material.depthTest = false; + + var geometry = new THREE.Geometry(); + + var stateArray = this.evaluate(); + + var prevPosition = stateArray[0].position; + var subdivs = 8; + + for(var i = 0; i < stateArray.length; i++) + { + var p = stateArray[i].position; + + if(i == 0 || (prevPosition.distanceTo(p) > .01 && stateArray[i].renderable)) + { + this.generateCrossSectionVertices(geometry, stateArray[i], subdivs, null); + geometry.vertices.push(p); + } + + prevPosition = p; + } + + return new THREE.Line(geometry, material); + } +} + +export class MainCharacter extends PlantLSystem +{ + constructor(seed, iterations) + { + super(); + + var instructions = [new ForwardInstruction(toRadians(35)), + new DummyInstruction("X"), + new DummyInstruction("Y"), + new FlowerInstruction(), + new RotateNegativeInstruction(), + new RotatePositiveInstruction(toRadians(90)), + new BranchInstruction(.8, .6), + new DetailInstruction(toRadians(40), .3, .6, toRadians(5)), + new RootInstruction(.7), + new LInstructionOverride("E", new DetailInstruction(toRadians(10), .3, .2, toRadians(5)))]; + + var rules = []; + + // Two arms rule + rules.push(new LRule("X", "[B-QQQQQY][B+QQQQQY]", 1.0)); + + // Arms details (fingers?) + rules.push(new LRule("Y", "[B-QX][B+QX]QQ", .75)); + rules.push(new LRule("Y", "QW", .25)); + + // Detailing the main branch + rules.push(new LRule("F", "EEFXE", .85)); + rules.push(new LRule("F", "FXF", .15)); + + var random = new Random(Random.engines.mt19937().seed(seed)); + this.system = new LSystem("RRRRFXEEEEX", instructions, rules, iterations, random); + this.subdivisions = 32; + } +} + + +class CactusBranchInstruction extends LInstruction +{ + symbol() { return "C" }; + + evaluate(context, stack) + { + var c = context; + + var euler = new THREE.Euler(0, c.random.real(-Math.PI, Math.PI), Math.PI * .5); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + + // Jump to the boundary of the tree + c.position.add(new THREE.Vector3(0, context.branchRadius , 0).applyQuaternion(quat)); + + c.branchRadius *= .5; + c.rotation.multiply(quat); + return c; + } +} + +class CactusForward extends LInstruction +{ + symbol() { return "F" }; + + evaluate(context, stack) + { + var c = context; + + c.position.add(new THREE.Vector3(0, context.branchLength, 0).applyQuaternion(c.rotation)); + c.branchRadius += c.random.real(-.1, .1, true) * c.branchRadius; + // c.rotation.multiply(randomTwistRotation(c.random, this.twistFactor)); + + var euler = new THREE.Euler(0, 0, -.35); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + + var dir = new THREE.Vector3(0,1,0).applyQuaternion(c.rotation) + + if(Math.abs(dir.y - 1.0) > .1) + c.rotation.multiply(quat); + + + c.renderable = true; + c.depth++; + return c; + } +} + +export class CactusCharacter extends PlantLSystem +{ + evaluate() + { + // (a, b, m1, m2, n1, n2, n3) + var crossSection = new CrossSectionParameters(1,1,18,18,2.225,1,10); + var state = new PlantContext(new THREE.Vector3(0,0,0), new THREE.Quaternion().setFromEuler(new THREE.Euler(0,0,0)), .4, 1.25, crossSection, this.system.random); + return this.system.evaluate(state); + } + + constructor(seed, iterations) + { + super(); + + var instructions = [new CactusForward(), + new DummyInstruction("X"), + new DummyInstruction("Y"), + new CactusBranchInstruction(), + new FlowerInstruction(), + new RotateNegativeInstruction(), + new RotatePositiveInstruction(toRadians(90)), + new BranchInstruction(.8, .6), + new DetailInstruction(toRadians(0), .5, .5, toRadians(0)), + new RootInstruction(.8), + new LInstructionOverride("E", new CactusForward())]; + + var rules = []; + + rules.push(new LRule("F", "FF", .3)); // Grow Rule + // rules.push(new LRule("F", "E", .5)); + rules.push(new LRule("E", "EE", 1.0)); // Grow Rule + rules.push(new LRule("X", "[CE]", 1.0)); + + var random = new Random(Random.engines.mt19937().seed(seed)); + // this.system = new LSystem("RRFFRRR", instructions, rules, 5, random); + + this.system = new LSystem("RFXFXFXFFF", instructions, rules, iterations, random); + this.subdivisions = 128; + } +} + +class WillowInstruction extends LInstruction +{ + symbol() { return "T" }; + + + evaluate(context, stack) + { + var c = context; + + c.position.add(new THREE.Vector3(0, context.branchLength, 0).applyQuaternion(c.rotation)); + c.branchRadius += c.random.real(-.1, .1, true) * c.branchRadius; + // c.rotation.multiply(randomTwistRotation(c.random, this.twistFactor)); + + var euler = new THREE.Euler(0, 0, .35); + var quat = new THREE.Quaternion(); + quat.setFromEuler(euler); + + var dir = new THREE.Vector3(0,1,0).applyQuaternion(c.rotation) + + if(Math.abs(dir.y + 1.0) > .1) + c.rotation.multiply(quat); + + c.renderable = true; + c.depth++; + return c; + } +} + + + +export class WillowCharacter extends PlantLSystem +{ + evaluate() + { + // (a, b, m1, m2, n1, n2, n3) + var crossSection = new CrossSectionParameters(1,1,18,18,2.225,1,10); + var state = new PlantContext(new THREE.Vector3(0,0,0), new THREE.Quaternion().setFromEuler(new THREE.Euler(0,0,0)), 1.0, 1.25, crossSection, this.system.random); + return this.system.evaluate(state); + } + + constructor(seed, iterations) + { + super(); + + var instructions = [new ForwardInstruction(toRadians(45)), + new DummyInstruction("X"), + new DummyInstruction("Y"), + new FlowerInstruction(), + new WillowInstruction(), + new RotateNegativeInstruction(), + new RotatePositiveInstruction(toRadians(90)), + new BranchInstruction(.8, .6), + new DetailInstruction(toRadians(15), .5, .5, toRadians(20)), + new RootInstruction(.8)]; + + var rules = []; + + rules.push(new LRule("Q", "QQ", 1.0)); // Grow Rule + rules.push(new LRule("T", "TT", 1.0)); // Grow Rule + + rules.push(new LRule("X", "[B+QT][B-QT]X", 1.0)); // Grow Rule + + var random = new Random(Random.engines.mt19937().seed(seed)); + + this.system = new LSystem("RRQX", instructions, rules, iterations, random); + this.subdivisions = 64; + } +}