taichi-dev / taichi_three

A soft renderer based on Taichi (work in progress)
https://t3.142857.red/
MIT License
223 stars 24 forks source link

What does the model.face mean? #23

Open JerryYan97 opened 4 years ago

JerryYan97 commented 4 years ago

Hello,

Taichi_three looks like a really cool project to make taichi do greater demos!

Besides, what does model.face mean? I am looking at the 'hello triangle' demo, but it is still a little bit confusing for me, because it doesn't look like OpenGL triangle convention. How should I interpret it?

Moreover, I believe a more thorough document than the one now can make this project popular soon :)

Thank you!

JerryYan97 commented 4 years ago

Besides, does it have a way to draw 3D lines like OpenGL? It looks like for some animation or simulation frame-wire is enough.

archibate commented 4 years ago

Here I'll demostrate why I choose the non-intuitive faces API instead of the intuitive legacy OpenGL API, by some pseudo-code.

Suppose you have a triangle ABC, whose vertices are (ax, ay), (bx, by), (cx, cy).

Step 1:

glBegin(GL_TRIANGLE);
glVertex(ax, ay);
glVertex(bx, by);
glVertex(cx, cy);
glEnd();

This is called the Intermediate Mode (IM) of OpenGL, which is well known among us. It's intuitive but will become low-efficient when there are a lot of vertices and faces. So it's soon deprecated in later versions of OpenGL, and replaced with a better API.

Step 2: So instead of invoking glVertex 3-times for each triangle, we store the 3 vertices into an array:

triangle_vertices = [[ax, ay], [bx, by], [cx, cy]]
glDrawTriangle(triangle_vertices);

But what if you want to draw two triangles, ABC and BCD?

triangle1_vertices = [[ax, ay], [bx, by], [cx, cy]]
glDrawTriangle(triangle1_vertices);
triangle2_vertices = [[bx, by], [cx, cy], [dx, dy]]
glDrawTriangle(triangle2_vertices);

See? If we want to draw n triangles, we have to invoke glDrawTriangle for n-times. Still low-efficient.

Step 3: So let's again store the multiple triangles in an array:

triangles = []
triangles[0] = [[ax, ay], [bx, by], [cx, cy]]
triangles[1] = [[bx, by], [cx, cy], [dx, dy]]
glDrawTriangles(triangles);

With this, we can draw multiple triangles within a single glDrawTriangles! But wait, the two triangles have a common edge BC, their data are simply replicated in triangles[0] and triangles[1]. If we want to move the vertex (cx, cy) now, we need to update the both in triangles[0] and triangles[1].

Step 4: So can we reuse the vertex (bx, by) and (cx, cy), so that we don't have to duplicate them? Yes! To do so, instead of directly storing the vertex positions in triangles, we store some integers in triangles:

vertices = [[ax, ay], [bx, by], [cx, cy], [dx, dy]]
triangles = []
triangles[0] = [0, 1, 2]  # tell GL to find the vertex position from vertices[0], vertices[1], vertices[2]
triangles[1] = [1, 2, 3]  # tell GL to find the vertex position from vertices[1], vertices[2], vertices[3]
glDrawTrianglesByIndex(vertices, triangles);

And this become the final API design of latest OpenGL.

Congrats! Now we learn that: The triangles here are model.faces in taichi-three. The vertices here are model.pos in taichi-three.

JerryYan97 commented 4 years ago

Got it. Thanks. But I am still not sure about the meaning here. model.pos[0] = [+0.0, +0.5, 0.0] model.pos[1] = [-0.5, -0.5, 0.0] model.pos[2] = [+0.5, -0.5, 0.0] model.nrm[0] = [0.0, 0.0, -1.0] model.nrm[1] = [0.0, 0.0, +1.0] model.faces[0] = [[0, 0, 0], [1, 0, 0], [2, 0, 0]] model.faces[1] = [[0, 0, 1], [2, 0, 1], [1, 0, 1]] Does it mean each element in a model.faces[0] represents a vertices? Meanwhile, for a element, the first integer is the index for the positions, the second integer is the index for colors and the third index is for the index of normals?

archibate commented 4 years ago

Does it mean each element in a model.faces[0] represents a vertices?

No, each element in a model.faces[0] represents a face, as its name suggests.

Meanwhile, for a element, the first integer is the index for the positions, the second integer is the index for colors and the third index is for the index of normals?

Sorry about my poor explaination skills.. Here's the implementation in case you need it: https://github.com/taichi-dev/taichi_three/blob/e45f1b33767c09a5c7c824c9f7400eae854ea4ac/taichi_three/model.py#L42-L46 https://github.com/taichi-dev/taichi_three/blob/e45f1b33767c09a5c7c824c9f7400eae854ea4ac/taichi_three/geometry.py#L84-L90 Hope this helps :)

JerryYan97 commented 4 years ago

Ah. Got it. Thanks. It looks like I understand it correctly :) But this rule is still quite strange for me.