Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What does the model.face mean? #23

Open
JerryYan97 opened this issue Oct 11, 2020 · 5 comments
Open

What does the model.face mean? #23

JerryYan97 opened this issue Oct 11, 2020 · 5 comments

Comments

@JerryYan97
Copy link

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
Copy link
Author

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
Copy link
Collaborator

archibate commented Oct 11, 2020

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
Copy link
Author

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
Copy link
Collaborator

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:

@ti.func
def render(self, camera):
for i in ti.grouped(self.faces):
# assume all elements to be triangle
render_triangle(self, camera, self.faces[i])

@ti.func
def render_triangle(model, camera, face):
scene = model.scene
L2C = model.L2C[None] # Local to Camera, i.e. ModelView in OpenGL
posa, posb, posc = model.pos[face[0, 0]], model.pos[face[1, 0]], model.pos[face[2, 0]]
texa, texb, texc = model.tex[face[0, 1]], model.tex[face[1, 1]], model.tex[face[2, 1]]
nrma, nrmb, nrmc = model.nrm[face[0, 2]], model.nrm[face[1, 2]], model.nrm[face[2, 2]]

Hope this helps :)

@JerryYan97
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants