nortikin / sverchok

Sverchok
http://nortikin.github.io/sverchok/
GNU General Public License v3.0
2.24k stars 233 forks source link

Viewer Draw little glitch #157

Closed enzyme69 closed 10 years ago

enzyme69 commented 10 years ago

prtscr capture_21

Sometimes, the Viewer Draw is giving result that is not quite correct. Such as above.

ly29 commented 10 years ago

There seems to be an issue with n-gon drawing code, it is open GL related, the GL_POLYGON option on only works for concave convex polygons (it might work otherwise but no guarantee).

More about the issue: http://stackoverflow.com/questions/15556929/open-gl-polygon

How to resolve... Hmm don't remember enough about Open GL for that right now.

zeffii commented 10 years ago

Drag the degrees slider, and it seems that this is down to drawing polygons from a fan. howwzat

enzyme69 commented 10 years ago

Yes I confirm that, something to do with concave and convex. If I go the opposite direction (minus), it is okey. Zeffii explained it well.

enzyme69 commented 10 years ago

By the way, Linus, with "Vectorized Input" and List Input, do we have 30 = maximum Limit on Circles?

Look something weird happens: https://www.dropbox.com/s/vvyjeghk3apyoll/procedural_star_006.blend

ly29 commented 10 years ago

Yes GL_POYGON does a triangle fan starting from vert nr 0.

ly29 commented 10 years ago

@enzyme69 Well List Input is limited to 32 values for int or float, for pratcial reasons, for more than that I think text input (which is not working properly right now) is the better answer. But you can also use List Join for unlimited (or atleast something like 64*32 values). For vector the limit is 10. But the input into Circle is limited by your computers memory more than anything else. To test make 100 circles like below. circle100

enzyme69 commented 10 years ago

I see, thanks again for this explanation. Maybe I do it like this next time. Safer and more predictable.

ly29 commented 10 years ago

But there is something strange in your example, you only have 6*5 matrix from the plane input and if ones sets to 6x6 to get 36 as the number of circles you make something goes wrong with last one. Hmm

enzyme69 commented 10 years ago

Aha...

enzyme69 commented 10 years ago

prtscr capture_27

This is pretty interesting already. Can make my procedural Mandala now.

zeffii commented 10 years ago

one circle, one kdtree edges. bam. mandala

enzyme69 commented 10 years ago

:+1: It was List Match then KDTree... let's make Turtle and Tree and LSystem.

ly29 commented 10 years ago

Also discovered that sometimes we get callbacks that aren't disabled when using undo a lot. I guess hash(node) #116 is not stable on undo or there is something else going on. Anyway lets focus on the GL_POLYGON issue in this tread.

zeffii commented 10 years ago

it's a tricky one, fix it one way and up will pop a scenario where the fix is also not desirable. The best way to go is to stick with convex polygons Jimmy, and clever lists constructing.

ly29 commented 10 years ago

The proper way I guess is to tesselate the ngon when drawing it.

zeffii commented 10 years ago

yeah, tesselation..I think blender has a function call for that

ly29 commented 10 years ago

Some cases might be too complex since one easily can construct faces that simply can't be drawn in rational way with ngons. But a case like this we should be able to handle I think.

ly29 commented 10 years ago

There should be some opengl solutions also.

http://www.blender.org/documentation/blender_python_api_2_70a_release/mathutils.geometry.html

mathutils.geometry.tessellate_polygon(veclist_list)
Takes a list of polylines (each point a vector) and returns the point indices for a polyline filled with triangles.
ly29 commented 10 years ago

Seems to work well, should be restructured I guess so we call per obj and not per face.

Ugly test code:

                v=[data_vector[k][i] for i in pol]
                tess_poly=mathutils.geometry.tessellate_polygon([v])
                for a,b,c in tess_poly:
                    glVertex3f(*(data_matrix[i]*data_vector[k][a]))
                    glVertex3f(*(data_matrix[i]*data_vector[k][b]))
                    glVertex3f(*(data_matrix[i]*data_vector[k][c]))

Also change to

 glBegin(GL_TRIANGLES)

And imported GL_TRIANGLES convex-test

ly29 commented 10 years ago

Doesn't always work well, though, can't draw cylinder with the new code...

ly29 commented 10 years ago

This almost works... But it looks ugly and I don't know enough about open gl.

            for j, pol in enumerate(data_polygons[k]):
                if shade:
                    normal_no_ = mathutils.geometry.normal(
                            data_vector[k][pol[0]],
                            data_vector[k][pol[1]],
                            data_vector[k][pol[2]]
                            )
                    normal_no = (normal_no_.angle(vectorlight,0))/math.pi
                    randa = (normal_no * coloa) - 0.1
                    randb = (normal_no * colob) - 0.1
                    randc = (normal_no * coloc) - 0.1
                else:
                    randa = ((j/oblen) + coloa) / 2.5
                    randb = ((j/oblen) + colob) / 2.5
                    randc = ((j/oblen) + coloc) / 2.5
                glColor3f(randa+0.2, randb+0.2, randc+0.2)
                if len(pol)>4:
                    glBegin(GL_TRIANGLES)
                    v=[data_vector[k][i] for i in pol]
                    tess_poly=mathutils.geometry.tessellate_polygon([v])
                    for a,b,c in tess_poly:
                        glVertex3f(*(data_matrix[i]*data_vector[k][a]))
                        glVertex3f(*(data_matrix[i]*data_vector[k][b]))
                        glVertex3f(*(data_matrix[i]*data_vector[k][c]))
                elif len(pol)==4:
                    glBegin(GL_POLYGON)
                    for point in pol:
                        vec_corrected = data_matrix[i]*data_vector[k][int(point)]
                        glVertex3f(*vec_corrected)
                else:
                    glBegin(GL_TRIANGLES)
                    for point in pol:
                        vec_corrected = data_matrix[i]*data_vector[k][int(point)]
                        glVertex3f(*vec_corrected)
                glEnd()
                glPointSize(1.75)
                glLineWidth(1.0)
zeffii commented 10 years ago

I would be more inclined to take a hard-line and say for the time being:

don't expect ngons with concave elements to render properly

The fact that it can draw some OK is a convenience, not a final desirable solution. I would must rather have an extra 'tesselate' node.

ly29 commented 10 years ago

Agreed, but it is fun to test. Leave it for now until we make an overview of the viewer draw function properly.

zeffii commented 10 years ago

see my updated comment, you agree?

ly29 commented 10 years ago

Yes.

ly29 commented 10 years ago

Convex draws fine, concave doesn't. Somehow I get them mixed up.

zeffii commented 10 years ago

cool, back to ListRange, almost testable :)

ly29 commented 10 years ago

Also the place to analyse the data isn't in callbacks inner loop but in the node

zeffii commented 10 years ago

so either a separate node, or a switch on draw_buttons_ext to beautify complex ngons. or both, i'm sure it could be handy elsewhere..ie bmesh node could use it.

ly29 commented 10 years ago

I was thinking we could preprocess the data a bit so the callback might run quicker and avoid some errors. Apply matrix or use gl matrix etc to avoid a lot extra work.

ly29 commented 10 years ago

I realized I made a mistake and this code works for drawing concave n-gons. But it is an ugly solution solving the problem in the wrong place. I think the correct solution is to tesslate the n-gones for the viewdrawer but let bmesh and blender handle that for baking.

    #######
    # polygons
    vectorlight = Vector((-0.66,-0.66,-0.66))
    if data_polygons and data_vector:
        glLineWidth(1.0)
        glEnable(polyholy)

        for i, matrix in enumerate(data_matrix):    # object
            k = i
            if i > verlen:
                k = verlen
            oblen = len(data_polygons[k])
            for j, pol in enumerate(data_polygons[k]):
                if shade:
                    normal_no_ = mathutils.geometry.normal(
                            data_vector[k][pol[0]],
                            data_vector[k][pol[1]],
                            data_vector[k][pol[2]]
                            )
                    normal_no = (normal_no_.angle(vectorlight,0))/math.pi
                    randa = (normal_no * coloa) - 0.1
                    randb = (normal_no * colob) - 0.1
                    randc = (normal_no * coloc) - 0.1
                else:
                    randa = ((j/oblen) + coloa) / 2.5
                    randb = ((j/oblen) + colob) / 2.5
                    randc = ((j/oblen) + coloc) / 2.5
                glColor3f(randa+0.2, randb+0.2, randc+0.2)
                if len(pol)>4:
                    glBegin(GL_TRIANGLES)
                    v=[data_vector[k][i] for i in pol]
                    tess_poly=mathutils.geometry.tessellate_polygon([v])
                    for a,b,c in tess_poly:
                        glVertex3f(*(data_matrix[i]*v[a]))
                        glVertex3f(*(data_matrix[i]*v[b]))
                        glVertex3f(*(data_matrix[i]*v[c]))
                elif len(pol)==4:
                    glBegin(GL_POLYGON)
                    for point in pol:
                        vec_corrected = data_matrix[i]*data_vector[k][int(point)]
                        glVertex3f(*vec_corrected)
                else:
                    glBegin(GL_TRIANGLES)
                    for point in pol:
                        vec_corrected = data_matrix[i]*data_vector[k][int(point)]
                        glVertex3f(*vec_corrected)
                glEnd()
                glPointSize(1.75)
                glLineWidth(1.0)
        glDisable(polyholy)
zeffii commented 10 years ago

Ah, i forgot you were already doing this.

ly29 commented 10 years ago

This does work but should we do it as a temporary solution? I don't have to time restructure the code for the viewer draw for some time and since you wanted to make a v2 anyway.

zeffii commented 10 years ago

it's up to you, it won't be for a few days until I get around to this.

ly29 commented 10 years ago

It is up on github now, ugly hack and all. If causes problems let us just revert and wait for mk2

zeffii commented 10 years ago

it'll be useful to test that for a while anyway. perhaps a mode to select we want ngon 5+ drawing routine to have

zeffii commented 10 years ago

@nortikin has been quiet probably making something crazy! :D

enzyme69 commented 10 years ago

Yes, Nikita show something crazy, surprise us :)

ly29 commented 10 years ago

concave