diff --git a/README.md b/README.md index 5ca56be..ae2a32d 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,12 @@ +# [Project3: LSystems] -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) +## Color +Change the color of the trunk, leaves, or flowers/fruit (without changing structure -# L-System Parser +## Grow +Animate the angle of the branches -lsystem.js contains classes for L-system, Rule, and LinkedList. Here’s our suggested structure: +## Iterations +Create a different tree + -**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 diff --git a/images/skymap/nx.jpg b/images/skymap/nx.jpg new file mode 100644 index 0000000..1cae307 Binary files /dev/null and b/images/skymap/nx.jpg differ diff --git a/images/skymap/ny.jpg b/images/skymap/ny.jpg new file mode 100644 index 0000000..fa7a975 Binary files /dev/null and b/images/skymap/ny.jpg differ diff --git a/images/skymap/nz.jpg b/images/skymap/nz.jpg new file mode 100644 index 0000000..1e9c54e Binary files /dev/null and b/images/skymap/nz.jpg differ diff --git a/images/skymap/px.jpg b/images/skymap/px.jpg new file mode 100644 index 0000000..0ad2eea Binary files /dev/null and b/images/skymap/px.jpg differ diff --git a/images/skymap/py.jpg b/images/skymap/py.jpg new file mode 100644 index 0000000..de7e5cc Binary files /dev/null and b/images/skymap/py.jpg differ diff --git a/images/skymap/pz.jpg b/images/skymap/pz.jpg new file mode 100644 index 0000000..836cdb4 Binary files /dev/null and b/images/skymap/pz.jpg differ diff --git a/leaf.obj b/leaf.obj new file mode 100644 index 0000000..3a81cc7 --- /dev/null +++ b/leaf.obj @@ -0,0 +1,404 @@ +# This file uses centimeters as units for non-parametric coordinates. + +mtllib leaf.mtl +g default +v -0.669570 1.003154 0.444401 +v 0.698759 0.997311 0.452740 +v -0.563024 1.003154 0.573665 +v 0.005893 1.003154 -1.015663 +v 0.001723 0.703990 0.490269 +v 0.670806 0.999077 0.582004 +v 0.278295 1.003154 -0.586174 +v 0.374201 0.908823 0.627872 +v -0.360784 1.003154 -0.561156 +v -0.327426 0.894578 0.540306 +v -0.890569 1.003154 0.364092 +v 0.857211 1.003154 0.293206 +v 0.549882 0.902117 0.305715 +v 0.374201 0.787318 0.309885 +v 0.035081 0.700154 0.312808 +v -0.327426 0.811341 0.309885 +v -0.596383 0.988398 0.309885 +v -0.878060 1.003154 -0.414313 +v 0.882230 1.003154 -0.372615 +v 0.466486 0.997754 -0.205823 +v 0.411729 1.003154 -0.510219 +v 0.035081 1.003154 -0.426823 +v -0.327426 1.003154 -0.426823 +v -0.433760 0.968400 -0.201654 +v -0.760125 1.003154 0.152111 +v 0.784515 1.003154 0.054318 +v 0.514216 0.950118 0.086942 +v 0.311024 0.867950 0.051208 +v 0.035081 0.813800 0.136321 +v -0.327426 0.879710 -0.005187 +v -0.526833 0.967413 0.091112 +v -0.161302 1.003154 -0.618956 +v -0.170818 0.772339 0.516499 +v -0.154946 0.724241 0.309885 +v -0.154946 0.857506 0.054993 +v -0.154946 1.003154 -0.426823 +v -0.669570 1.082068 0.444401 +v -0.563024 1.082068 0.573665 +v -0.596383 1.067312 0.309885 +v -0.890569 1.082068 0.364092 +v -0.327426 0.974082 0.540306 +v -0.327426 0.890255 0.309885 +v 0.001723 0.784505 0.490269 +v 0.035081 0.852969 0.309885 +v 0.374201 0.987737 0.627872 +v 0.374201 0.958623 0.309885 +v 0.670806 1.077990 0.582004 +v 0.549882 1.021613 0.305715 +v 0.698759 1.082068 0.452740 +v 0.857211 1.082068 0.293206 +v -0.170818 0.851192 0.516499 +v -0.154946 0.803315 0.309885 +v 0.514216 1.039822 0.086942 +v 0.784515 1.082068 0.054318 +v 0.311024 0.958623 0.038372 +v 0.035081 0.958623 -0.005187 +v -0.327426 0.958623 -0.005187 +v -0.154946 0.955824 -0.005187 +v -0.526833 1.046327 0.091112 +v -0.760125 1.082068 0.152111 +v 0.035081 1.082068 -0.426823 +v 0.005893 1.082068 -1.015663 +v 0.411729 1.082068 -0.510219 +v 0.278295 1.082068 -0.586174 +v -0.327426 1.082068 -0.426823 +v -0.360784 1.082068 -0.561156 +v -0.154946 1.082068 -0.426823 +v -0.161302 1.082068 -0.618956 +v 0.466486 1.073904 -0.205823 +v 0.882230 1.082068 -0.372615 +v -0.433760 1.047313 -0.201654 +v -0.878060 1.082068 -0.414313 +vt 0.375000 0.250000 +vt 0.625000 0.250000 +vt 0.425687 0.250000 +vt 0.504371 0.500000 +vt 0.504371 0.250000 +vt 0.590342 0.250000 +vt 0.546628 0.500000 +vt 0.546628 0.250000 +vt 0.459201 0.500000 +vt 0.459201 0.250000 +vt 0.375000 0.336386 +vt 0.625000 0.336386 +vt 0.590342 0.336386 +vt 0.546628 0.336386 +vt 0.504371 0.336386 +vt 0.459201 0.336386 +vt 0.425687 0.336386 +vt 0.375000 0.428185 +vt 0.625000 0.428185 +vt 0.590342 0.428185 +vt 0.546628 0.428185 +vt 0.504371 0.428185 +vt 0.459201 0.428185 +vt 0.425687 0.428185 +vt 0.375000 0.375646 +vt 0.625000 0.375646 +vt 0.590342 0.375646 +vt 0.546628 0.375646 +vt 0.504371 0.375646 +vt 0.459201 0.375646 +vt 0.425687 0.375646 +vt 0.480693 0.500000 +vt 0.480693 0.250000 +vt 0.480693 0.336386 +vt 0.480693 0.375646 +vt 0.480693 0.428185 +vt 0.375000 0.250000 +vt 0.425687 0.250000 +vt 0.425687 0.336386 +vt 0.375000 0.336386 +vt 0.459201 0.250000 +vt 0.459201 0.336386 +vt 0.504371 0.336386 +vt 0.504371 0.250000 +vt 0.546628 0.250000 +vt 0.546628 0.336386 +vt 0.590342 0.336386 +vt 0.590342 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.336386 +vt 0.480693 0.250000 +vt 0.480693 0.336386 +vt 0.590342 0.375646 +vt 0.625000 0.375646 +vt 0.546628 0.375646 +vt 0.504371 0.375646 +vt 0.459201 0.375646 +vt 0.480693 0.375646 +vt 0.425687 0.375646 +vt 0.375000 0.375646 +vt 0.504371 0.500000 +vt 0.504371 0.428185 +vt 0.546628 0.428185 +vt 0.546628 0.500000 +vt 0.459201 0.500000 +vt 0.459201 0.428185 +vt 0.480693 0.428185 +vt 0.480693 0.500000 +vt 0.590342 0.428185 +vt 0.625000 0.428185 +vt 0.425687 0.428185 +vt 0.375000 0.428185 +vt 0.375000 0.250000 +vt 0.425687 0.250000 +vt 0.375000 0.336386 +vt 0.459201 0.250000 +vt 0.504371 0.250000 +vt 0.546628 0.250000 +vt 0.590342 0.250000 +vt 0.625000 0.250000 +vt 0.625000 0.336386 +vt 0.480693 0.250000 +vt 0.625000 0.375646 +vt 0.375000 0.375646 +vt 0.546628 0.428185 +vt 0.546628 0.500000 +vt 0.504371 0.500000 +vt 0.459201 0.500000 +vt 0.459201 0.428185 +vt 0.480693 0.500000 +vt 0.625000 0.428185 +vt 0.590342 0.428185 +vt 0.425687 0.428185 +vt 0.375000 0.428185 +vn 0.051821 0.995367 -0.080993 +vn 0.421486 0.886857 -0.189299 +vn 0.323797 0.945291 -0.039751 +vn 0.082869 0.996238 -0.025346 +vn 0.482986 0.849801 -0.211097 +vn 0.444061 0.895675 0.024015 +vn -0.236425 0.956931 0.168484 +vn -0.282008 0.958097 0.050222 +vn -0.362831 0.931788 -0.011154 +vn -0.320667 0.944860 0.066428 +vn -0.274383 0.961620 -0.000900 +vn -0.301151 0.949614 -0.086837 +vn -0.245834 0.958384 -0.145143 +vn -0.187861 0.981855 0.025858 +vn 0.362349 0.922453 -0.133357 +vn 0.149646 0.971074 0.186069 +vn -0.213575 0.973523 0.081482 +vn -0.097559 0.993691 0.055324 +vn -0.159927 0.966023 0.203034 +vn -0.051897 0.962650 0.265728 +vn 0.268558 0.931029 0.247108 +vn 0.020966 0.948632 0.315687 +vn 0.247301 0.967241 0.057329 +vn 0.100484 0.994934 -0.002880 +vn 0.000000 1.000000 0.000000 +vn 0.005242 0.986178 0.165608 +vn -0.031505 0.982981 0.180986 +vn 0.000000 1.000000 0.000000 +vn 0.000000 1.000000 0.000000 +vn 0.049910 0.979010 0.197605 +vn 0.000000 0.984954 0.172815 +vn 0.000000 1.000000 0.000000 +vn -0.249271 0.964156 0.090927 +vn -0.060775 0.997225 0.043002 +vn 0.210031 0.974511 0.078834 +vn 0.103892 0.994587 -0.001864 +vn -0.051821 -0.995367 0.080993 +vn -0.082869 -0.996238 0.025346 +vn -0.324108 -0.945197 0.039440 +vn -0.422321 -0.886648 0.188416 +vn -0.447825 -0.893955 -0.017245 +vn -0.483409 -0.849775 0.210235 +vn 0.153635 -0.984214 -0.087861 +vn 0.347072 -0.937777 -0.010766 +vn 0.370322 -0.895625 0.246410 +vn 0.170814 -0.961177 0.216705 +vn 0.380042 -0.924873 0.013306 +vn 0.276381 -0.958822 -0.065382 +vn 0.361480 -0.905925 0.220528 +vn 0.398352 -0.886185 0.236625 +vn -0.258649 -0.951516 -0.166484 +vn -0.418537 -0.888966 0.185921 +vn 0.263372 -0.952194 -0.154795 +vn 0.128468 -0.987140 -0.095133 +vn 0.151300 -0.943885 -0.293579 +vn 0.023556 -0.934079 -0.356288 +vn -0.247908 -0.936739 -0.247105 +vn -0.079903 -0.941020 -0.328780 +vn -0.247301 -0.967241 -0.057328 +vn -0.100484 -0.994934 0.002880 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.047896 -0.976656 -0.209401 +vn -0.006125 -0.981038 -0.193719 +vn 0.000000 -1.000000 0.000000 +vn 0.000000 -1.000000 0.000000 +vn -0.019374 -0.981336 -0.191322 +vn -0.050717 -0.978027 -0.202215 +vn 0.267320 -0.957248 -0.110524 +vn 0.067020 -0.995869 -0.061261 +vn -0.210030 -0.974511 -0.078833 +vn -0.103892 -0.994587 0.001864 +vn -0.771656 0.000000 0.636040 +vn -0.771656 0.000000 0.636040 +vn -0.771656 0.000000 0.636040 +vn -0.771656 0.000000 0.636040 +vn -0.341537 0.000000 0.939868 +vn -0.341537 0.000000 0.939868 +vn -0.341537 0.000000 0.939868 +vn -0.341537 0.000000 0.939868 +vn 0.140191 -0.000000 0.990124 +vn 0.145898 -0.000000 0.989300 +vn 0.142545 -0.000000 0.989788 +vn 0.140191 -0.000000 0.990125 +vn -0.190530 -0.000000 0.981681 +vn -0.192825 -0.000000 0.981233 +vn -0.069364 -0.000000 0.997591 +vn -0.205946 -0.000000 0.978563 +vn 0.977409 0.000000 0.211356 +vn 0.977409 0.000000 0.211356 +vn 0.977409 0.000000 0.211356 +vn 0.977409 0.000000 0.211356 +vn 0.709509 0.000000 0.704696 +vn 0.709509 0.000000 0.704696 +vn 0.709509 0.000000 0.704696 +vn 0.709509 0.000000 0.704696 +vn 0.152827 -0.000000 0.988253 +vn 0.152827 -0.000000 0.988253 +vn 0.150294 -0.000000 0.988641 +vn 0.150294 -0.000000 0.988641 +vn 0.956684 0.000000 -0.291129 +vn 0.999295 0.000000 0.037549 +vn 0.999295 0.000000 0.037549 +vn 0.956684 0.000000 -0.291129 +vn -0.851669 0.000000 -0.524079 +vn -0.851669 0.000000 -0.524079 +vn -0.851669 0.000000 -0.524079 +vn -0.851669 0.000000 -0.524079 +vn 0.494702 0.000000 -0.869063 +vn 0.779754 0.000000 -0.626087 +vn 0.779754 0.000000 -0.626087 +vn 0.494702 0.000000 -0.869063 +vn 0.844470 0.000000 -0.535603 +vn 0.844470 0.000000 -0.535603 +vn -0.970524 0.000000 0.241007 +vn -0.970524 0.000000 0.241007 +vn -0.970524 0.000000 0.241007 +vn -0.970524 0.000000 0.241007 +vn -0.278305 0.000000 -0.960493 +vn -0.278305 0.000000 -0.960493 +vn -0.278305 0.000000 -0.960493 +vn -0.278305 0.000000 -0.960493 +vn 0.974794 0.000000 0.223107 +vn 0.974794 0.000000 0.223107 +vn -0.372342 0.000000 -0.928095 +vn -0.372342 0.000000 -0.928095 +vn -0.372342 0.000000 -0.928096 +vn -0.372342 0.000000 -0.928096 +vn 0.984202 0.000000 -0.177047 +vn 0.984202 0.000000 -0.177047 +vn 0.984202 0.000000 -0.177047 +vn 0.984202 0.000000 -0.177047 +vn -0.904241 0.000000 -0.427022 +vn -0.904241 0.000000 -0.427022 +vn -0.904241 0.000000 -0.427022 +vn -0.904241 0.000000 -0.427022 +vn 0.431734 0.000000 -0.902001 +vn 0.431734 0.000000 -0.902001 +vn 0.431734 0.000000 -0.902001 +vn 0.431734 0.000000 -0.902001 +vn -0.979005 0.000000 0.203837 +vn -0.979005 0.000000 0.203837 +vn -0.979005 0.000000 0.203837 +vn -0.979005 0.000000 0.203837 +vn -0.921502 0.000000 -0.388373 +vn -0.921502 0.000000 -0.388373 +vn -0.921502 0.000000 -0.388373 +vn -0.921502 0.000000 -0.388373 +s 1 +g pCube1 +usemtl initialShadingGroup +f 37/73/1 38/74/2 39/17/3 40/75/4 +f 39/17/3 38/74/2 41/76/5 42/16/6 +f 44/15/7 43/77/8 45/78/9 46/14/10 +f 48/13/11 47/79/12 49/80/13 50/81/14 +f 46/14/10 45/78/9 47/79/12 48/13/11 +f 42/16/6 41/76/5 51/82/15 52/34/16 +f 53/27/17 48/13/11 50/81/14 54/83/18 +f 55/28/19 46/14/10 48/13/11 53/27/17 +f 56/29/20 44/15/7 46/14/10 55/28/19 +f 57/30/21 42/16/6 52/34/16 58/35/22 +f 59/31/23 39/17/3 42/16/6 57/30/21 +f 40/75/4 39/17/3 59/31/23 60/84/24 +f 62/87/25 61/22/26 63/85/27 64/86/28 +f 66/88/29 65/89/30 67/36/31 68/90/32 +f 69/92/33 53/27/17 54/83/18 70/91/34 +f 63/85/27 55/28/19 53/27/17 69/92/33 +f 61/22/26 56/29/20 55/28/19 63/85/27 +f 65/89/30 57/30/21 58/35/22 67/36/31 +f 71/93/35 59/31/23 57/30/21 65/89/30 +f 60/84/24 59/31/23 71/93/35 72/94/36 +f 52/34/16 51/82/15 43/77/8 44/15/7 +f 58/35/22 52/34/16 44/15/7 56/29/20 +f 67/36/31 58/35/22 56/29/20 61/22/26 +f 68/90/32 67/36/31 61/22/26 62/87/25 +s 4 +f 1/37/37 11/40/38 17/39/39 3/38/40 +f 17/39/39 16/42/41 10/41/42 3/38/40 +f 15/43/43 14/46/44 8/45/45 5/44/46 +f 13/47/47 12/50/48 2/49/49 6/48/50 +f 14/46/44 13/47/47 6/48/50 8/45/45 +f 16/42/41 34/52/51 33/51/52 10/41/42 +f 27/53/53 26/54/54 12/50/48 13/47/47 +f 28/55/55 27/53/53 13/47/47 14/46/44 +f 29/56/56 28/55/55 14/46/44 15/43/43 +f 30/57/57 35/58/58 34/52/51 16/42/41 +f 31/59/59 30/57/57 16/42/41 17/39/39 +f 11/40/38 25/60/60 31/59/59 17/39/39 +f 4/61/61 7/64/62 21/63/63 22/62/64 +f 9/65/65 32/68/66 36/67/67 23/66/68 +f 20/69/69 19/70/70 26/54/54 27/53/53 +f 21/63/63 20/69/69 27/53/53 28/55/55 +f 22/62/64 21/63/63 28/55/55 29/56/56 +f 23/66/68 36/67/67 35/58/58 30/57/57 +f 24/71/71 23/66/68 30/57/57 31/59/59 +f 25/60/60 18/72/72 24/71/71 31/59/59 +f 34/52/51 15/43/43 5/44/46 33/51/52 +f 35/58/58 29/56/56 15/43/43 34/52/51 +f 36/67/67 22/62/64 29/56/56 35/58/58 +f 32/68/66 4/61/61 22/62/64 36/67/67 +s off +f 1/1/73 3/3/74 38/74/75 37/73/76 +f 11/11/77 1/1/78 37/73/79 40/75/80 +s 7 +f 3/3/81 10/10/82 41/76/83 38/74/84 +f 5/5/85 8/8/86 45/78/87 43/77/88 +s off +f 6/6/89 2/2/90 49/80/91 47/79/92 +f 2/2/93 12/12/94 50/81/95 49/80/96 +s 7 +f 8/8/86 6/6/97 47/79/98 45/78/87 +f 10/10/82 33/33/99 51/82/100 41/76/83 +s 9 +f 12/12/101 26/26/102 54/83/103 50/81/104 +s off +f 25/25/105 11/11/106 40/75/107 60/84/108 +s 10 +f 21/21/109 7/7/110 64/86/111 63/85/112 +f 7/7/110 4/4/113 62/87/114 64/86/111 +s off +f 9/9/115 23/23/116 65/89/117 66/88/118 +f 32/32/119 9/9/120 66/88/121 68/90/122 +s 9 +f 26/26/102 19/19/123 70/91/124 54/83/103 +s off +f 19/19/125 20/20/126 69/92/127 70/91/128 +f 20/20/129 21/21/130 63/85/131 69/92/132 +f 23/23/133 24/24/134 71/93/135 65/89/136 +f 24/24/137 18/18/138 72/94/139 71/93/140 +f 18/18/141 25/25/142 60/84/143 72/94/144 +s 7 +f 33/33/99 5/5/85 43/77/88 51/82/100 +s off +f 4/4/145 32/32/146 68/90/147 62/87/148 diff --git a/package.json b/package.json index be683fc..f6ef21b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "scripts": { "start": "webpack-dev-server --hot --inline", "build": "webpack", - "deploy": "node deploy.js" + "deploy": "gh-pages-deploy" }, "gh-pages-deploy": { "prep": [ diff --git a/src/framework.js b/src/framework.js index 76f901a..443fd7f 100644 --- a/src/framework.js +++ b/src/framework.js @@ -34,7 +34,7 @@ function init(callback, update) { var controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping = true; controls.enableZoom = true; - controls.target.set(0, 0, 0); + controls.target.set(0, 1, 0); controls.rotateSpeed = 0.3; controls.zoomSpeed = 1.0; controls.panSpeed = 2.0; diff --git a/src/leaf.mtl b/src/leaf.mtl new file mode 100644 index 0000000..c89145d --- /dev/null +++ b/src/leaf.mtl @@ -0,0 +1,6 @@ +newmtl initialShadingGroup +illum 4 +Kd 0.50 0.50 0.50 +Ka 0.00 0.00 0.00 +Tf 1.00 1.00 1.00 +Ni 1.00 diff --git a/src/lsystem.js b/src/lsystem.js index e643b6d..d19df92 100644 --- a/src/lsystem.js +++ b/src/lsystem.js @@ -7,36 +7,109 @@ function Rule(prob, str) { // TODO: Implement a linked list class and its requisite functions // as described in the homework writeup +var Node = function(str, i) { + this.next = null; + this.prev = null; + this.sym = str; + this.iter = i; //what iteration node was added +} + +var LinkedList = function() { + this.size = 0; + this.head = null; + this.tail = null; +} + +LinkedList.prototype.append = function(str, iter) { + var n = new Node(str, iter); + this.size++; + if (this.tail == null) { + this.head = n; this.tail = n; + return; + } + n.prev = this.tail; this.tail.next = n; + this.tail = n; +} + +LinkedList.prototype.prepend = function(str, iter) { + var n = new Node(str, iter); + this.size++; + if (this.head == null) { + this.head = n; this.tail = n; + return; + } + n.next = this.head; this.head.next = n; + this.head = n; +} + +LinkedList.prototype.combine = function(l1, l2) { + var list = new LinkedList(); + list.head = l1.head; + list.tail = l2.tail; + l1.tail.next = l2.head; + l2.head.prev = l1.tail; + list.size = l1.size + l2.size; + return list; +} // TODO: Turn the string into linked list -export function stringToLinkedList(input_string) { +export function stringToLinkedList(input_string, iter) { // 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; + var list = new LinkedList(); + for (var i = 0; i < input_string.length; i ++) { + var c = input_string.charAt(i); list.append(c, iter); + } + return list; } // TODO: Return a string form of the LinkedList export function linkedListToString(linkedList) { // ex. Node1("F")->Node2("X") should be "FX" var result = ""; + var n = linkedList.head; + while (n != null) { + result += n.sym; n = n.next; + } return result; } // TODO: Given the node to be replaced, // insert a sub-linked-list that represents replacementString -function replaceNode(linkedList, node, replacementString) { +// ASSUMING REPLACEMENT IS NOT EMPTY +function replaceNode(linkedList, node, replacementString, iter) { + + var sub = stringToLinkedList(replacementString, iter); + + if (node.prev == null && node.next == null) { + linkedList.head = sub.head; + linkedList.tail = sub.tail; + linkedList.size = sub.size; + return; + } + if (node.prev == null) {linkedList.head = sub.head;} + else {node.prev.next = sub.head; sub.head.prev = node.prev;} + if (node.next == null) {linkedList.tail = sub.tail;} + else {node.next.prev = sub.tail; sub.tail.next = node.next;} + linkedList.size += sub.size - 1; } export default function Lsystem(axiom, grammar, iterations) { // default LSystem - this.axiom = "FX"; + this.axiom = 'AX'; this.grammar = {}; - this.grammar['X'] = [ - new Rule(1.0, '[-FX][+FX]') - ]; - this.iterations = 0; + this.grammar['X'] = [new Rule(1.0, 'BY')]; + this.grammar['Y'] = [new Rule(1.0, 'CZ')]; + this.grammar['Z'] = [new Rule(1.0, 'DU')]; + this.grammar['U'] = [new Rule(0.25, '[FQ*]>FU'), + new Rule(0.25, '[FQ] sum) { + i = i +1; + var rule = this.grammar[str][i]; + sum += this.grammar[str][i].probability; + } + return this.grammar[str][i].successorString; + } + // 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); + this.doIterations = function(num) { + var lSystemLL = stringToLinkedList(this.axiom, -1); + for (var i = 0; i < num; i++) { + var nod = lSystemLL.head; + // debugger; + while (nod != null) { + if (this.grammar[nod.sym] != null) { + + var new_str = this.selectRule(nod.sym); + replaceNode(lSystemLL, nod, new_str, i + 1); + + } + nod = nod.next; + } + } + this.result = lSystemLL; return lSystemLL; } } \ No newline at end of file diff --git a/src/main.js b/src/main.js index f0c6600..048b0e9 100644 --- a/src/main.js +++ b/src/main.js @@ -1,10 +1,20 @@ 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, {linkedListToString} from './lsystem.js' import Turtle from './turtle.js' var turtle; +var lsys; + +var guiMake = { + make : function() { + var result = lsys.doIterations(lsys.iterations); + turtle.clear(); + //turtle = new Turtle(turtle.scene); + turtle.renderSymbols(result); + } +}; // called after the scene loads function onLoad(framework) { @@ -22,26 +32,69 @@ function onLoad(framework) { scene.add(directionalLight); // set camera position - camera.position.set(1, 1, 2); + camera.position.set(40, 0, 0); camera.lookAt(new THREE.Vector3(0,0,0)); + // set skybox + var loader = new THREE.CubeTextureLoader(); + var urlPrefix = 'images/skymap/'; + + var skymap = new THREE.CubeTextureLoader().load([ + urlPrefix + 'px.jpg', urlPrefix + 'nx.jpg', + urlPrefix + 'py.jpg', urlPrefix + 'ny.jpg', + urlPrefix + 'pz.jpg', urlPrefix + 'nz.jpg' + ] ); + + scene.background = skymap; + + var plane = new THREE.PlaneGeometry(100,1000, 32); + plane.rotateX(3.14159/2); + plane.rotateZ(3.14159); + plane.translate(0,-10,0) + var material = new THREE.MeshLambertMaterial( {color: 0x005c09, emissive: 0x000000} ); + var ground = new THREE.Mesh(plane, material ); + // leaf.scale.set(100,100,100); + scene.add(ground); + // initialize LSystem and a Turtle to draw - var lsys = new Lsystem(); + lsys = new Lsystem(); turtle = new Turtle(scene); + doLsystem(lsys, lsys.iterations, turtle); - gui.add(camera, 'fov', 0, 180).onChange(function(newVal) { - camera.updateProjectionMatrix(); - }); + // gui.add(camera, 'fov', 0, 180).onChange(function(newVal) { + // camera.updateProjectionMatrix(); + // }); gui.add(lsys, 'axiom').onChange(function(newVal) { - lsys.UpdateAxiom(newVal); + lsys.updateAxiom(newVal); doLsystem(lsys, lsys.iterations, turtle); }); - gui.add(lsys, 'iterations', 0, 12).step(1).onChange(function(newVal) { + gui.add(lsys, 'iterations', 0, 20).step(1).onChange(function(newVal) { clearScene(turtle); doLsystem(lsys, newVal, turtle); }); + gui.add(turtle, 'angle', 0, 180).onChange(function(newVal) { + clearScene(turtle); + turtle.clear(); + turtle.renderSymbols(lsys.result); + }); + gui.addColor(turtle, 'stem_color').onChange(function(newVal) { + clearScene(turtle); + turtle.clear(); + turtle.renderSymbols(lsys.result); + }); + gui.addColor(turtle, 'leaf_color').onChange(function(newVal) { + clearScene(turtle); + turtle.clear(); + turtle.renderSymbols(lsys.result); + }); + gui.addColor(turtle, 'flower_color').onChange(function(newVal) { + clearScene(turtle); + turtle.clear(); + turtle.renderSymbols(lsys.result); + }); + gui.add(turtle, 'grow'); } // clears the scene by removing all geometries added by turtle.js @@ -54,14 +107,25 @@ function clearScene(turtle) { } function doLsystem(lsystem, iterations, turtle) { - var result = lsystem.DoIterations(iterations); + var result = lsystem.doIterations(iterations); turtle.clear(); - turtle = new Turtle(turtle.scene); + //turtle = new Turtle(turtle.scene); turtle.renderSymbols(result); } // called on frame updates function onUpdate(framework) { + if (turtle !== undefined) { + if (turtle.grow) { + var date = new Date(); + turtle.angle = date.getSeconds(); + clearScene(turtle); + turtle.clear(); + turtle.renderSymbols(lsys.result); + } + + } + } // when the scene is done initializing, it will call onLoad, then on frame updates, call onUpdate diff --git a/src/shaders/obj-frag.glsl b/src/shaders/obj-frag.glsl new file mode 100644 index 0000000..76adf44 --- /dev/null +++ b/src/shaders/obj-frag.glsl @@ -0,0 +1,16 @@ +uniform vec3 color; +uniform vec3 light; + +varying vec3 vPosition; +varying vec3 vNormal; + +vec3 lerp(vec3 a, vec3 b, float t) { + return a * (1.0-t*t) + b * t*t; +} + +void main() { + vec3 incoming_ray = normalize(light - vPosition); + float c = dot(vNormal, incoming_ray); + gl_FragColor = vec4(c * color, 1.0 ); + +} \ No newline at end of file diff --git a/src/shaders/obj-vert.glsl b/src/shaders/obj-vert.glsl new file mode 100644 index 0000000..9be614c --- /dev/null +++ b/src/shaders/obj-vert.glsl @@ -0,0 +1,10 @@ +varying vec3 vPosition; +varying vec3 vNormal; + +void main() { + + vNormal = normal; + vPosition = position; + + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); +} \ No newline at end of file diff --git a/src/turtle.js b/src/turtle.js index 1db2723..f267c8c 100644 --- a/src/turtle.js +++ b/src/turtle.js @@ -1,29 +1,58 @@ const THREE = require('three') +import LinkedList from './lsystem.js' // A class used to encapsulate the state of a turtle at a given moment. // The Turtle class contains one TurtleState member variable. // You are free to add features to this state class, // such as color or whimiscality -var TurtleState = function(pos, dir) { +var TurtleState = function(pos, dir, c) { return { pos: new THREE.Vector3(pos.x, pos.y, pos.z), - dir: new THREE.Vector3(dir.x, dir.y, dir.z) + dir: new THREE.Vector3(dir.x, dir.y, dir.z), + iter: 0 } } + +var points = []; +for (var i = 0; i < 10; i ++) { + points.push(new THREE.Vector2(Math.sin(i * 0.2) * 10 + 5, (i - 5) * 2)); +} export default class Turtle { constructor(scene, grammar) { - this.state = new TurtleState(new THREE.Vector3(0,0,0), new THREE.Vector3(0,1,0)); + this.state = new TurtleState(new THREE.Vector3(0,-10,0), new THREE.Vector3(0,1,0)); this.scene = scene; + this.stack = []; + this.flower_color = 0xff1111; + this.leaf_color = 0x167400; + this.stem_color = 0x361900; + this.angle = 30; + this.tree = new LinkedList(); + this.grow = false; // TODO: Start by adding rules for '[' and ']' then more! // Make sure to implement the functions for the new rules inside Turtle if (typeof grammar === "undefined") { this.renderGrammar = { - '+' : this.rotateTurtle.bind(this, 30, 0, 0), - '-' : this.rotateTurtle.bind(this, -30, 0, 0), - 'F' : this.makeCylinder.bind(this, 2, 0.1) + '+' : this.rotateTurtle.bind(this, 1, 1, 1), + '-' : this.rotateTurtle.bind(this, -1, -1, -1), + '^' : this.rotateTurtle.bind(this, 0, 1, 0), + 'v' : this.rotateTurtle.bind(this, 0, -1, 0), + '>' : this.rotateTurtle.bind(this, 1, 0, 0), + '<' : this.rotateTurtle.bind(this, -1, 0, 0), + '(' : this.rotateTurtle.bind(this, 0, 0, 1), + ')' : this.rotateTurtle.bind(this, 0, 0, -1), + // grow trunk + 'F' : this.makeCylinder.bind(this, 2, 0.2, 0.2), + 'A' : this.makeCylinder.bind(this, 2, 0.8, 1.0), + 'B' : this.makeCylinder.bind(this, 2, 0.6, 0.8), + 'C' : this.makeCylinder.bind(this, 2, 0.4, 0.6), + 'D' : this.makeCylinder.bind(this, 2, 0.2, 0.4), + '[' : this.saveState.bind(this), + ']' : this.restoreState.bind(this), + '*' : this.makeFlower.bind(this, 1), + '#' : this.makeLeaf.bind(this, 1) }; } else { this.renderGrammar = grammar; @@ -33,7 +62,8 @@ export default class Turtle { // Resets the turtle's position to the origin // and its orientation to the Y axis clear() { - this.state = new TurtleState(new THREE.Vector3(0,0,0), new THREE.Vector3(0,1,0)); + this.state = new TurtleState(new THREE.Vector3(0,-10,0), new THREE.Vector3(0,1,0)); + this.stack = []; } // A function to help you debug your turtle functions @@ -43,13 +73,23 @@ export default class Turtle { console.log(this.state.dir) } + saveState() { + var s = new TurtleState(this.state.pos, this.state.dir); + this.stack.push(s); + } + + restoreState() { + var s = this.stack.pop(); + this.state = s; + } + // Rotate the turtle's _dir_ vector by each of the // Euler angles indicated by the input. rotateTurtle(x, y, z) { var e = new THREE.Euler( - x * 3.14/180, - y * 3.14/180, - z * 3.14/180); + x * this.angle * 3.14/180, + y * this.angle * 3.14/180, + z * this.angle * 3.14/180); this.state.dir.applyEuler(e); } @@ -65,40 +105,98 @@ export default class Turtle { var newVec = this.state.dir.multiplyScalar(dist); this.state.pos.add(newVec); }; - - // Make a cylinder of given length and width starting at turtle pos - // Moves turtle pos ahead to end of the new cylinder - makeCylinder(len, width) { - var geometry = new THREE.CylinderGeometry(width, width, len); - var material = new THREE.MeshBasicMaterial( {color: 0x00cccc} ); - var cylinder = new THREE.Mesh( geometry, material ); - this.scene.add( cylinder ); - //Orient the cylinder to the turtle's current direction + makeGeometry(geo, scale) { + this.scene.add( geo ); + + //Orient the flower to the turtle's current direction var quat = new THREE.Quaternion(); quat.setFromUnitVectors(new THREE.Vector3(0,1,0), this.state.dir); var mat4 = new THREE.Matrix4(); mat4.makeRotationFromQuaternion(quat); - cylinder.applyMatrix(mat4); + geo.applyMatrix(mat4); - - //Move the cylinder so its base rests at the turtle's current position + //Move the flower so its base rests at the turtle's current position var mat5 = new THREE.Matrix4(); - var trans = this.state.pos.add(this.state.dir.multiplyScalar(0.5 * len)); + var trans = this.state.pos.add(this.state.dir.multiplyScalar(0.5 * scale)); mat5.makeTranslation(trans.x, trans.y, trans.z); - cylinder.applyMatrix(mat5); + geo.applyMatrix(mat5); + } + + bias(b, t) { + return Math.pow(t, Math.log(b)/Math.log(0.5)); + } + + // Make a cylinder of given length and width 0.1 starting at turtle pos + // Moves turtle pos ahead to end of the new cylinder + makeCylinder(len, widthA, widthB) { + var geometry = new THREE.CylinderGeometry(widthA, widthB, len); + var material = new THREE.MeshLambertMaterial( {color: 0x333333, emissive: this.stem_color} ); + //var material = new THREE.ShaderMaterial(this.stem_mat); + var cylinder = new THREE.Mesh( geometry, material ); + + this.makeGeometry(cylinder, len); //Scoot the turtle forward by len units this.moveForward(len/2); }; + + makeFlower(scale) { + var geometry = new THREE.LatheGeometry(points); + geometry.scale(0.05, 0.05, 0.05); + var material = new THREE.MeshLambertMaterial( {color: 0xcccccc, emissive: this.flower_color} ); + var flower = new THREE.Mesh( geometry, material ); + + this.scene.add(flower); + + var quat = new THREE.Quaternion(); + quat.setFromUnitVectors(new THREE.Vector3(0,1,0), this.state.dir); + var mat4 = new THREE.Matrix4(); + mat4.makeRotationFromQuaternion(quat); + flower.applyMatrix(mat4); + + var mat5 = new THREE.Matrix4(); + var trans = this.state.pos; + mat5.makeTranslation(trans.x, trans.y, trans.z); + flower.applyMatrix(mat5); + + // this.moveForward(1); + } + + makeLeaf(scale) { + + + + var geometry = new THREE.ConeGeometry(0.6, 1, 32); + // geometry.scale(0.05, 0.05, 0.05); + var material = new THREE.MeshLambertMaterial( {color: 0xcccccc, emissive: this.leaf_color} ); + var leaf = new THREE.Mesh(geometry, material ); + // leaf.scale.set(100,100,100); + + this.scene.add(leaf); + + var quat = new THREE.Quaternion(); + quat.setFromUnitVectors(new THREE.Vector3(0,1,0), this.state.dir); + var mat4 = new THREE.Matrix4(); + mat4.makeRotationFromQuaternion(quat); + leaf.applyMatrix(mat4); + + var mat5 = new THREE.Matrix4(); + var trans = this.state.pos; + mat5.makeTranslation(trans.x, trans.y, trans.z); + leaf.applyMatrix(mat5); + + // this.moveForward(1); + } // Call the function to which the input symbol is bound. // Look in the Turtle's constructor for examples of how to bind // functions to grammar symbols. renderSymbol(symbolNode) { - var func = this.renderGrammar[symbolNode.character]; + var func = this.renderGrammar[symbolNode.sym]; + this.state.iter = symbolNode.iter; if (func) { - func(); + func(symbolNode); } }; diff --git a/tree1.png b/tree1.png new file mode 100644 index 0000000..d625127 Binary files /dev/null and b/tree1.png differ diff --git a/tree2.png b/tree2.png new file mode 100644 index 0000000..7389c19 Binary files /dev/null and b/tree2.png differ