<- back
hw1 (100 + 5 pts) upload hw.cpp* to glow
codebase & Github Issues (get homework help, report bugs, ask questions about lecture, etc.) video of a perfect solution to the main part of the assignment (no extra credit) for full credit, your submission should produce the same or very similar output
ilo's - get reacquainted with malloc(...) - get acquainted with basic_draw(...), imgui_slider(...), and input - get acquainted with data-oriented design - challenge yourself
code reading a stretchy buffer, aka a dynamic array, is a useful data struture. it holds a pointer to a heap-allocated array (the internal array), and has a function to push back (append) new elements. as new elements are pushed back, the internal array automatically grows (stretches). a reasonable implementation might allocate an internal array of length 16 on the first push back, and then double the length of the internal array as needed. std::vector is one implementation of a stretchy buffer. here is another: http://nothings.org/stb_ds/ - the capacity is the length of the internal array (the total number of slots elements *could* fill) - the length (aka size) of the stretchy buffer is the number of elements that are currently stored in the internal array (the number of slots that are actually filled) - ✅ the capacity of a stretchy buffer is always greater than or equal its length

code hw note: a single build and run of your submission should demonstrate the functionality for all parts of the code hw (including any extra credit). please write your hw.cpp such that i can verify everything works without making edits to hw.cpp or having to build and run multiple times 🙂👍 note: i will sometimes give you the length of my solution to the problem as a hint. fewer lines is not necessarily better! /* alright let's get crack-a-lackin'. to start, please clone a fresh copy of the current codebase. each week there will be updates and bugfixes to cow.cpp and snail.cpp, as well as an updated hw.cpp with this week's documentation and starter code */ a. (20 pts) revisit hw0 spec - draw the same red square outline from hw0a, only this time make it so you can also drag the vertices around
hint - see the documentation for widget_drag(...) - the vertex positions will need to persist across frames. assuming you will store them in a fixed-size array (a fine choice, since there are only four vec2's to be stored), you can accomplish this either by declaring the array before the while loop, or by declaring the array to be static (locally-persistent) inside the while loop. as long as you understand what you're doing, either way is fine by me :) - it may be easier to draw the red squre outline with basic_draw(...) than with gl_begin(...), gl_end()
- draw the same green circle outline from hw0b, only this time provide a slider to change N, where N is the number of vertices used to approximate the circular outline as a line loop - N should start at 16 - N should range from 0 to 32
hint - see the documentation for imgui_slider(...) - it may be easier to draw the green circle outline with gl_begin(...), gl_end() than with basic_draw(...)
b. (60 pts) bouncing balls++: video explanation: https://www.youtube.com/embed/nutJzrWlno0?rel=0 note: to go to the next app, press the Q key spec (summary of the video explanation): - app draws the 3D double unit box (x, y, z all go from [-1, 1]) in 3D wireframe - app should simulate at least 100,000 vertices - vertices were initialized at random positions in the double unit box - vertices were initialized with random initial velocities (not too fast please 😬) - vertices were initialized with random colors - vertices move following the update rule "position <- position + velocity" - vertices bounce off all six walls of the cube in a way that makes sense - (assume zero gravity and perfectly elastic collisions) - a single call to basic_draw(primitive, ...) draws first N vertices with color specified per-vertex in a given size (size is the same for all primitives) - provide a slider to scrub through which primitive we're using to draw the data - POINTS, LINES, LINE_STRIP, LINE_LOOP, TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, TRIANGLE_MESH, QUAD_MESH - hotkeys J and K to decrement and increment the primitive respectively - slider should loop when using hotkeys (see documentation) - provide a slider to scrub the number of vertices we're drawing - (all the vertices will still "exist", but we will only draw the first N) - the slider for N should range from 4 to 100,000 - when the app first starts, N is 12. (so i can see collision-handling is correct) - provide a slider to scrub the size of the primitives from 0.0 to 50.0 - (no effect on TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, or QUADS) - pause (optional; ungraded) - pressing the P key should pause and unpause the simulation (you must still draw the simulation when paused) - pressing the . key (period) while paused should step forward one frame - the app runs at ~60fps in the Ward Lab while drawing all 100,000 vertices (this is just a sanity check on your implementation; makes sure you're not e.g. calling malloc every frame)
hints - my solution is ~50 lines long and doesn't actually use anything from snail (you are more than welcome to use snail in your solution) - to handle collisions, first think about the problem in 1D - you definitely don't have to, but it is possible to draw the wireframe double unit box with a single somewhat bizarre call to basic_draw(LINE_STRIP, ...)
c. (10 pts) bootleg std::vector: implement a very basic stretchy buffer API that makes the usage code currently commented out in hw1b() work spec (enforced by ASSERT's) - the stretchy buffer capacity (length of the internal array) should... - start at 0 - be 16 after the first push_back - double as needed - freeing the stretchy buffer should... - free the internal array - set the pointer to the internal array to NULL - set the length of the stretchy buffer to 0 - set the capacity to 0 note: workarounds that don't actually implement a working stretchy buffer will not score points
hints - my solution is ~20 lines long - i implement - struct StretchyBuffer { ... }; - void sbuff_push_back(StretchyBuffer *buffer, vec2 point) { ... } - void sbuff_free(StretchyBuffer *buffer) { ... } - i use malloc, realloc, and free
d. (10 pts) bootleg annotation tool: use the stretchy buffer of your choice* to implement a basic annotation / pen tool *probably not a bad idea to just use std::vector unless you've already done the stretchy buffer refactor extra credit; if you're feeling bold, use stb_ds 🚀 spec: - left mouse click to start drawing stroke - left mouse hold to continue drawing stroke - left mouse release to finish drawing stroke - press the X key on the keyboard to clear all strokes - don't leak memory don't worry about this one
hints - my solution is ~20 lines long - a std::vector<std::vector<vec2>> may be convenient - calling basic_draw(...) once per stroke per frame is A OK

❗❗❗ please grab an updated copy of cow.cpp from the Github before attempting the extra credit (it has bugfixes that you'll need) 🤙. (1 pt) stretchy buffer refactor: templatize your stretchy buffer API so that you can create, e.g., a StretchyBuffer<vec2> or a StretchyBuffer<vec3>. additionally, implement the method T &operator [](int index) { ... } so you can access a stretchy buffer like you would a regular array; e.g., buffer[3] += buffer[4] * 2;. if you like, you may also add a push_back(...) method. congratulations, you have created a not-particularly-featureful replacement for std::vector that you can actually inspect in a debugger 🎉 note: to score points for this question you must have usage code. i recommend writing the usage code first. ✏. (1 pt) annotation tool refactor: refactor your solution to hw1d() into a function void widget_annotate(mat4 PV, vec3 color = monokai.blue) { ... } that you can call in the while loop of any app to annotate that app. call it in hw1a() to prove it works video of correct behavior: https://www.youtube.com/embed/XV30COToGDM?rel=0 for full credit - widget_annotate(...) must always draw over everything (besides maybe the gui) - it must play nicely with widget_drag(...) - "you must not annotate if dragging, and not drag if you are annotating" - this involves the global variable widget_active_widget_ID - you may start drawing a new stroke if and only if it is 0 - when you start drawing a stroke, you must set it to WIDGET_ID_ANNOTATE - you may continue drawing a stroke if and only if it is WIDGET_ID_ANNOTATE - you may finish drawing a stroke if and only if it is WIDGET_ID_ANNOTATE - when you finish drawing a stroke, you must set it back to 0 example usage code: if (input.key_toggle['z']) { widget_annotate(); } 🧁. (up to 3 pts) vaporwave terrain flyover: using what we learned this week, make something like this https://youtube.com/embed/8kIMjwWdYz4?rel=0 hint: the line imgui_readout("camera", &camera); may help you line up your camera optional soundtrack
🐄