The model on the right can be constructed, articulated, and rendered using a strategy like that shown below.
(You can run a Java-JOGL program to see how the articulation works by clicking on the image. Press a numeric key between 0 and 9 followed by the left and/or right arrow keys to articulate the various joints.)
void Robot::renderRobot(MInit) M = MInit * MtorsoRotation renderTorso(M) Mlocal = M * Mgenericarm-leftarm * MleftShoulderRotation renderArm(Mlocal, MleftElbowRotation) Mlocal = M * Mgenericarm-rightarm * MrightShoulderRotation renderArm(Mlocal, MrightElbowRotation) Mlocal = M * Mgenericleg-leftleg * MleftHipRotation renderLeg(Mlocal, MleftKneeRotation) Mlocal = M * Mgenericleg-rightleg * MrightHipRotation renderLeg(Mlocal, MrightKneeRotation) Mlocal = M * Mhead-headPos * MheadRotation renderHead(Mlocal)
void Robot::renderArm(M, MelbowRotation) renderUpperArm(M) Mlocal = M * Mlowerarm-arm * MelbowRotation renderLowerArm(Mlocal)
void Robot::renderLowerArm(M) float m[16]; glUniformMatrix4fv(shaderIF->ppuLoc("mc_ec"), 1, false, M.extractColMajor(m)); one or more calls to establishXxx(…) as desired glDrawArrays(…); …
Depending on how elaborate you want the model to be, lower level functions would have the same structure, in particular, continuing to define and use more transformation matrices while calling lower level functions to produce finer and finer gometric detail. At the lowest levels, the implementation would finally use glUniformMatrix to copy the matrix, M, passed to them to the mc_ec matrix, and then issue required calls to functions like glDrawArrays and/or glDrawElements.
Recall that the mc_ec matrix returned from getMatrices will be the product:
Hence, if I want a single robot in its native location, the Robot render method might be structured something like:
void Robot::render() { … cryph::Matrix4x4 mc_ec, ec_lds; getMatrices(mc_ec, ec_lds); float m[16]; glUniformMatrix4fv(shaderIF->ppuLoc("ec_lds"), 1, false, ec_lds.extractColMajor(m)); // Don't set matrix for mc_ec here. Instead: renderRobot(mc_ec); … }
Alternatively, if I want an army of robots (say, in class RobotArmy), I could do something like:
void RobotArmy::render() { … cryph::Matrix4x4 mc_ec, ec_lds; getMatrices(mc_ec, ec_lds); float m[16]; glUniformMatrix4fv(shaderIF->ppuLoc("ec_lds"), 1, false, ec_lds.extractColMajor(m)); // Don't set matrix for mc_ec here. Instead: for (int i=0 ; i<numRobotsInArmy ; i++) robot[i]->renderRobot(mc_ec * robotPlacementMatrix[i]); … }