| Module #3, Assignment #2
Exercise #1
The Change3DShape application has code that can show either a Cube, a Tetrahedron or an Octahedron, and it lets you rotate any of them along the X, Y or Z axes:

Right now, the code creates a dark background (as desired) with the command gl.clearColor( 0.1, 0.1, 0.1, 1.0 ). However, the code only allows you to see the cube object:

Modify the code so that it allows you to choose which object to view using a dropdown with the names of each object in it. Whichever object the user chooses in the dropdown should be the one that the user sees rotating.

The HTML code is partially done in the following file Change3DShape.html.
The JavaScript code is partially done in the following file Change3DShape.js.
To accomplish this task you will need to "Dropdown" list input which you can find the code for in the "Summary WegGL Reference Sheet." And after you have that in your HTML code, you will need a handler for it in your JavaScript code. The handler must reset the buffers for the vertices and the colors, then call the appropriate shape creating method, and then update the appropriate WebGL attributes by calling "bindBuffer(...)" and "bufferData(...)" with the appropriate buffer variables. But note the buffer variables MUST be global variables to work inside of the handler. Here is a example of what your handler code might look like to accomplish this.
var whShape = event.target.value;
points = [];
colors = [];
if (whShape == 0) {
colorCube();
}
else if (whShape == 1) {
colorTetra();
}
else if (whShape == 2) {
colorOcta();
}
gl.bindBuffer(gl.ARRAY_BUFFER, cBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW);
Exercise #2
The CubeTetraOcta application has code that shows either a Cube, a Tetrahedron or an Octahedron, and it lets you rotate any of them along the X, Y or Z axes:

Right now, the code creates a dark background (as desired) with the command gl.clearColor( 0.1, 0.1, 0.1, 1.0 ). However, the code does not allow you to see all three objects at the same time. Modify the code so that you can see all the objects at the same time, and they each can rotate around its own center point, and each can be scaled around its own center point.

Move the center of the cube to the clip coordinate position (-0.5, 0.4, 0.0), move the center of the tetrahedron to the clip coordinate position (0.5, 0.4, 0.0), and move the center of the octahedron to clip coordinate position (0.0, -0.5, 0.0).
The HTML code is partially done in the following file CubeTetraOcta.html.
The Javascript code is partially done in the following file CubeTetraOcta.js.
To make the required modifications, you will have to add a translation matrix and a scaling matrix that are uniform variables to your vertex shader in your HTML code with the following declarations:
uniform mat4 transMat;
uniform mat4 scaleMat;
Then you will need to multiply these matrices along with the rotation matrices in the following order when you are deriving the gl_Position:
gl_Position = transMat * rz * ry * rx * scaleMat * vPosition;
Next, you must add a row of "Stop/Start" buttons so that if "Stop Cube" is pressed, the Cube will stop rotating, and the button's text will change to "Start Cube". And when "Start Cube" is pressed the Cube will start rotating again, and the button will toggle to "Stop Cube" again. Add similar buttons for the Tetrahedron and the Octahedron.
Then, add a "Cube Scale" slider that will go from 1 to 5, and it will start at position 4. At position 1 it will make the Cube 25% of its normal size. At position 2 it will make the Cube 50% of its normal size. At position 3 it will make the Cube 75% of its normal size. At position 4 it will make the Cube 100% of its normal size. At position 5 it will make the Cube 125% of its normal size. Add similar sliders for the Tetrahedron and the Octahedron.
In addition to this, you will need to make the following changes to your Javascript code:
Javascript code changes:
- In the declarations at the top, find the line "var whShape = 0;". This is a field that determines which of the three shapes will show up, and since we want them all to show up, remove this line and the comment line right above it.
- While still in the declarations at the top, find the line "var thetaLoc;" and keep that line in the code, but below it, add the following lines which declare various variables you will be using to manage your transformatioins for the cube, the tetrahedron and the octahedron:
var transMat;
var transMatLoc;
var scaleMat;
var scaleMatLoc;
var transMatCube;
var transMatTetra;
var transMatOcta;
var cubeScale = 1.0;
var tetraScale = 1.0;
var octaScale = 1.0;
var cubeOff = [-0.5, 0.4, 0.0];
var tetraOff = [0.5, 0.4, 0.0];
var octaOff = [0.0, -0.5, 0.0];
var cTheta = [0, 0, 0];
var tTheta = [0, 0, 0];
var oTheta = [0, 0, 0];
var cSpinning = true;
var tSpinning = true;
var oSpinning = true;
var totCubePts = 0;
var totTetraPts = 0;
var totOctaPts = 0;
- In the init() function, you will find code that has a comment above it that says "Load shaders and initialize attribute buffers". Right below that comment line is where there is an if-else block that looks like the following:
if (whShape == 0) {
// --------------- Cube --------------------------
colorCube();
}
else if (whShape == 1) {
// --------------- Tetrahedron -------------------
colorTetra();
}
else if (whShape == 2) {
// --------------- Octahedron --------------------
colorOcta();
}
This block implements only one of the three shapes in the attribute buffers, and now we need to implement all three of them. So replace this if-block with the following code:
// ---------- Initialize Cube Vertices --------------
colorCube();
// ------ Initialize Tetrahedron Vertices -----------
colorTetra();
// ------- Initialize Octahedron Vertices -----------
colorOcta();
// ------- Create Translation Matrices -----------
transMatCube = translate(cubeOff[0],cubeOff[1],cubeOff[2]);
transMatTetra = translate(tetraOff[0],tetraOff[1],tetraOff[2]);
transMatOcta = translate(octaOff[0],octaOff[1],octaOff[2]);
- Next, while still in your init() method, above the "render();" line at the bottom of the method, add the following two lines to add two uniform variables that will be used as the translation matrix and the scaling matrix:
transMatLoc = gl.getUniformLocation(program, "transMat");
scaleMatLoc = gl.getUniformLocation(program, "scaleMat");
- Next, while still in your init() method, you will need to set the scale values to their proper initial values. Do this right above the "render();" again. If you named your slider IDs "cSlider", "tSlider" and "oSlider", then your code for this would look like the following:
cubeScale = Number(document.getElementById("cSlider").value);
tetraScale = Number(document.getElementById("tSlider").value);
octaScale = Number(document.getElementById("oSlider").value);
- Next, while still in your init() method and above the "render();" line, you need to add your button handlers and your slider handlers. If you named your buttons "cStartStop", "tStartStop" and "oStartStop", then the button and slider handler for the cube would look something like this:
document.getElementById("cStartStop").onclick = function () {
cSpinning = !cSpinning;
document.getElementById("cStartStop").innerText =
(cSpinning) ? "Stop Cube" : "Start Cube";
};
document.getElementById("cSlider").onchange =
function (event) {
cubeScale = Number(event.target.value);
};
You should be able to come up with the button and slider handlers for the tetrahedron and the octahedron.
- Next, in the render() method find the following line:
gl.drawArrays(gl.TRIANGLES, 0, points.length);
And replace this line with the following lines:
transMat = transMatCube;
gl.uniformMatrix4fv(transMatLoc, false, flatten(transMat));
// Render cube
gl.drawArrays(gl.TRIANGLES, 0, totCubePts);
transMat = transMatTetra;
gl.uniformMatrix4fv(transMatLoc, false, flatten(transMat));
// Render tetrahedron
gl.drawArrays(gl.TRIANGLES, totCubePts, totTetraPts);
transMat = transMatOcta;
gl.uniformMatrix4fv(transMatLoc, false, flatten(transMat));
// Render octahedron
gl.drawArrays(gl.TRIANGLES, totCubePts + totTetraPts, totOctaPts);
- In your squares() function, below the line "colors.push(vertexColors[c]);" add the following line that keeps track of the total number of cube vertices:
++totCubePts;
- In your makeTetra() function, below the line "points.push(c);" add the following line that keeps track of the total number of tetrahedron vertices:
totTetraPts += 3;
- In your makeOcta() function, below the line "points.push(c);" add the following line that keeps track of the total number of octahedron vertices:
totOctaPts += 3;
- All of your final changes need to be made in the render() method, where you will have to assign the scaleMat value and the 3 theta values for each object, just like you assign a transMat value for each object before gl.drawArrays() for that object is called. To do this, accomplish the following tasks for each object in its proper place in the render() method.
- For each object shape, set the scaleMat to a Scale Matrix with whatever the current scale slider value is divided by 4. For instance, for the cube this would be the value:
scaleMat = scalem(cubeScale / 4, cubeScale / 4, cubeScale / 4);
- After setting the scaleMat value, update the scaleMatLoc value with a call to the gl.uniformMatrix4fv() method.
- Next, if the flag keeping track of whether the object is spinning is true, then update its theta value along the current axis. For instance, for the cube this would be the following code:
if (cSpinning)
cTheta[axis] += 2.0;
(Note: this means you will no longer just modify the theta value each time render() runs with the line that is currently in the code: "theta[axis] += 2.0;")
- Then update the thetaLoc value with a call to the gl.uniform3fv() method and pass it the current object's theta values (for the cube this means the cTheta values).
- Now you should be all done.
Add a Comment block section to the top of your Javascript program in this assignment with the following information filled in using the following format:
/*
* Course: CS 4722
* Section: .....
* Name: ......
* Professor: ......
* Assignment #: ......
*/
Be sure your program
runs without error.
DeliverablesTurn in the files: Change3DShape.zip (with your HTML and JS files) CubeTetraOcta.zip (with your HTML and JS files)
Do this by uploading the file as an attachment to this Module's assignment drop box in D2L Brightspace.
|