summaryrefslogtreecommitdiff
path: root/cad/src/exprs/draw_utils.py
blob: 075138308fabf21da025cd916643490f8323f1be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# Copyright 2006-2007 Nanorex, Inc.  See LICENSE file for details.
"""
draw_utils.py

$Id$

Note: this module does not really belong in the exprs package --
that's its main client, but it contains only pure OpenGL utilities.
"""

from OpenGL.GL import GL_TEXTURE_2D
from OpenGL.GL import glTexCoord2fv
from OpenGL.GL import glColor4fv
from OpenGL.GL import GL_QUADS
from OpenGL.GL import glColor3fv
from OpenGL.GL import GL_LIGHTING
from OpenGL.GL import glDisable
from OpenGL.GL import GL_TRIANGLES
from OpenGL.GL import glBegin
from OpenGL.GL import glVertex3fv
from OpenGL.GL import glEnd
from OpenGL.GL import glEnable
from OpenGL.GL import GL_QUAD_STRIP

from OpenGL.GLU import gluUnProject

from geometry.VQT import norm, A
from Numeric import dot

from array import array
# ==

def mymousepoints(glpane, x, y): #bruce 071017 moved this here from testdraw.py
    ### TODO: rename, docstring

    # modified from GLPane.mousepoints; x and y are window coords (except y is 0 at bottom, positive as you go up [guess 070124])
    self = glpane
    just_beyond = 0.0
    p1 = A(gluUnProject(x, y, just_beyond))
    p2 = A(gluUnProject(x, y, 1.0))

    los = self.lineOfSight # isn't this just norm(p2 - p1)?? Probably not, if we're in perspective mode! [bruce Q 061206]
        # note: this might be in abs coords (not sure!) even though p1 and p2 would be in local coords.
        # I need to review that in GLPane.__getattr__. ###k

    k = dot(los, -self.pov - p1) / dot(los, p2 - p1)

    p2 = p1 + k*(p2-p1)
    return (p1, p2)

# == new LL drawing helpers

def draw_textured_rect(origin, dx, dy, tex_origin, tex_dx, tex_dy):
    """
    Fill a spatial rect defined by the 3d points (origin, dx, dy)
    with the 2d-texture subrect defined by the 2d points (tex_origin, tex_dx, tex_dy)
    in the currently bound texture object.
    """
    glEnable(GL_TEXTURE_2D)
    glBegin(GL_QUADS)
    glTexCoord2fv(tex_origin) # tex coords have to come before vertices, I think! ###k
    glVertex3fv(origin)
    glTexCoord2fv(tex_origin + tex_dx)
    glVertex3fv(origin + dx)
    glTexCoord2fv(tex_origin + tex_dx + tex_dy)
    glVertex3fv(origin + dx + dy)
    glTexCoord2fv(tex_origin + tex_dy)
    glVertex3fv(origin + dy)
    glEnd()
    glDisable(GL_TEXTURE_2D)

def draw_textured_rect_subtriangle(origin, dx, dy, tex_origin, tex_dx, tex_dy, points): #070404 modified from draw_textured_rect
    """
    Like draw_textured_rect, but draw only the sub-triangle of the same rect (textured in the same way),
    where the subtriangle has relative 2d vertices as specified inside that rect (treating its own coords as each in [0.0, 1.0]).

    WARNING: depending on the glEnables set up by the caller, the sub-triangle coords might need to be
    in CCW winding order for the triangle to be visible from the front.
    """
    #e could easily generalize API to polygon, and this implem to convex polygon, if desired
    ##e WARNING: this function's name and api are likely to be revised;
    # or we might just replace the whole scheme, using things like Textured(Triangle(...),...) instead,
    # perhaps implemented by telling OpenGL how to compute the texture coords in a wrapper, then just drawing the triangle.
    assert len(points) == 3
    # and each point should be a V of length 2, or a 2-tuple, with elements convertible to floats -- this is assumed below
    glEnable(GL_TEXTURE_2D)
    glBegin(GL_TRIANGLES)
    for px, py in points:
        px = float(px)
        py = float(py)
        glTexCoord2fv((tex_origin + px * tex_dx + py * tex_dy).tolist())
        # glVertex3fv(origin + px * dx + py * dy)
    glEnd()
    glDisable(GL_TEXTURE_2D)

# Ideally we'd modularize the following to separate the fill/color info from the shape-info. (And optimize them.)
# For now they're just demos that might be useful.

def draw_filled_rect(origin, dx, dy, color):
##    print 'draw_filled_rect',(origin, dx, dy, color) #####@@@@@
    glDisable(GL_LIGHTING) # this allows the specified color to work. Otherwise it doesn't work (I always get dark blue). Why???
     # guess: if i want lighting, i have to specify a materialcolor, not just a regular color. (and vertex normals)
    try:
        len(color)
    except:
        print "following exception in len(color) for color = %r" % (color,) # 061212 -- why didn't caller's fix_color catch it? ##k
        raise
    if len(color) == 4:
        glColor4fv(color)
        if 0 and color[3] != 1.0:
            print "color has alpha",color ####@@@@
    else:
        glColor3fv(color)
##    glRectfv(origin, origin + dx + dy) # won't work for most coords! also, ignores Z. color still not working.
    glBegin(GL_QUADS)
    glVertex3fv(origin)
    #glColor3fv(white)#
    glVertex3fv(origin + dx)
    # glColor3fv(white) # hack, see if works - yes!
    #glColor3fv(color)#
    glVertex3fv(origin + dx + dy)
    #glColor3fv(white)#
    glVertex3fv(origin + dy)
    glEnd()
    glEnable(GL_LIGHTING) # should be outside of glEnd! when inside, i got infloop! (not sure that was why; quit/reran after that)

def draw_filled_triangle(origin, dx, dy, color):
    glColor3fv(color)
    glDisable(GL_LIGHTING)
    glBegin(GL_TRIANGLES)
    glVertex3fv(origin)
    glVertex3fv(origin + dx)
    glVertex3fv(origin + dy)
    glEnd()
    glEnable(GL_LIGHTING)

def draw_filled_rect_frame(origin, dx, dy, thickness, color):
    """
    draw something that looks like a picture frame of a single filled color.
    """
    tx = thickness * norm(dx)
    ty = thickness * norm(dy)
    ## glColor3fv(color) ### this has an exception (wants 3 elts, gets 4) in Mac A9.1-rc1
    # (i.e. in the Mac "Gold" PyOpenGL for A9.1), so instead, do the following: [bruce 070703]
    glColor3fv(color[:3])
    glDisable(GL_LIGHTING)
    glBegin(GL_QUAD_STRIP)
    glVertex3fv(origin)
    glVertex3fv(origin + tx + ty)
    glVertex3fv(origin + dx)
    glVertex3fv(origin + dx - tx + ty)
    glVertex3fv(origin + dx + dy)
    glVertex3fv(origin + dx + dy - tx - ty)
    glVertex3fv(origin + dy)
    glVertex3fv(origin + dy + tx - ty)
    glVertex3fv(origin)
    glVertex3fv(origin + tx + ty)
    glEnd()
    glEnable(GL_LIGHTING)

# end