


/* Feel free to read and write this struct's members. */
typedef struct bodyBody bodyBody;
struct bodyBody {
    isoIsometry isometry;
    BodyUniforms uniforms;
    veshVesh *vesh;
    bodyBody *firstChild;
    bodyBody *nextSibling;
};

/* Like an initializer, this method sets the body into an acceptable initial 
state. Unlike an initializer, this method has no matching finalizer, because 
there are no resources that must be cleaned up. */
void bodyConfigure(
		bodyBody *body, veshVesh *vesh, bodyBody *firstChild, 
		bodyBody *nextSibling) {
    float rotation[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
    isoSetRotation(&(body->isometry), rotation);
    float translation[3] = {0.0, 0.0, 0.0};
    isoSetTranslation(&(body->isometry), translation);
    BodyUniforms unifs = {0};
    body->uniforms = unifs;
    body->vesh = vesh;
    body->firstChild = firstChild;
    body->nextSibling = nextSibling;
}

/* Called during command buffer construction. If any vesh is present, then 
renders that vesh. The index must count 0, 1, 2, ... as body after body is 
rendered into the scene. But a null vesh need not cause the index to increment. 
*/
void bodyRender(
        const bodyBody *body, VkCommandBuffer *cmdBuf, 
        const VkPipelineLayout *pipelineLayout, 
        const VkDescriptorSet *descriptorSet, const unifAligned *aligned, 
        int index) {
    if (body->vesh != NULL) {
		uint32_t offset = index * aligned->alignedSize;
		vkCmdBindDescriptorSets(
			*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, 
			descriptorSet, 1, &offset);
		veshRender(body->vesh, *cmdBuf);
    }
}

/* Called once per animation frame. If any vesh is present, then loads the 
body's isometry into the body's uniforms and copies the body's uniforms into the 
indexth UBO array element. The index must match the one passed to bodyRender. */
void bodySetUniforms(bodyBody *body, const unifAligned *aligned, int index) {
    if (body->vesh != NULL) {
		float proper[4][4];
		isoGetHomogeneous(&(body->isometry), proper);
		mat4Transpose(proper, body->uniforms.modelingT);
		BodyUniforms *bodyUnif = (BodyUniforms *)unifGetAligned(aligned, index);
		*bodyUnif = body->uniforms;
    }
}

/* Renders the scene graph, that hangs off the given body, including younger 
siblings and their descendants, depth-first, starting from the given index. The 
index is the order of visitation in a depth-first traveral. Returns the next 
index to be used in rendering the graph (on the next call to 
bodyRenderRecursively after this one). */
int bodyRenderRecursively(
        const bodyBody *body, VkCommandBuffer *cmdBuf, 
        const VkPipelineLayout *pipelineLayout, 
        const VkDescriptorSet *descriptorSet, const unifAligned *aligned, 
        int index) {
    
}

/* Sets the uniforms for the scene graph, that hangs off the given body, 
including younger siblings and their descendants, depth-first, starting from the 
given index. The index is the order of visitation in a depth-first traveral. 
Returns the next index to be used (just as bodyRenderRecursively does). In more 
detail, this method computes the product of the ancestry's modeling isometry and 
the body's own modeling isometry. It uses that product as the cumulative 
modeling isometry to be loaded into the body's uniforms (as in bodySetUniforms). 
It then recursively causes the body's descendants (and younger siblings and 
their descendants) to load their uniforms in much the same way. */
int bodySetUniformsRecursively(
        bodyBody *body, const float ancestry[4][4], const unifAligned *aligned, 
        int index) {
    
}


