1#! /usr/bin/env python
2from __future__ import print_function
3import os
4if not os.environ.get( 'PYOPENGL_PLATFORM' ):
5    os.environ['PYOPENGL_PLATFORM'] = 'osmesa'
6from math import pi, sin, cos
7import OpenGL
8OpenGL.USE_ACCELERATE = False
9from OpenGL.GL import *
10from OpenGL.GL.ARB.fragment_program import glGenProgramsARB
11from OpenGL.GLU import *
12from OpenGL.osmesa import *
13
14def sphere(radius, slices, stacks):
15    q = gluNewQuadric()
16    gluQuadricNormals(q, GLU_SMOOTH)
17    gluSphere(q, radius, slices, stacks)
18    gluDeleteQuadric(q)
19
20
21def cone(base, height, slices, stacks):
22    q = gluNewQuadric()
23    gluQuadricDrawStyle(q, GLU_FILL)
24    gluQuadricNormals(q, GLU_SMOOTH)
25    gluCylinder(q, base, 0.0, height, slices, stacks)
26    gluDeleteQuadric(q)
27
28
29def torus(innerRadius, outerRadius, sides, rings):
30    ringDelta = 2.0 * pi / rings
31    sideDelta = 2.0 * pi / sides
32
33    theta = 0.0
34    cosTheta = 1.0
35    sinTheta = 0.0
36    for i in range(rings - 1, -1, -1):
37        theta1 = theta + ringDelta
38        cosTheta1 = cos(theta1)
39        sinTheta1 = sin(theta1)
40        glBegin(GL_QUAD_STRIP)
41        phi = 0.0
42        for j in range(sides, -1, -1):
43            phi += sideDelta
44            cosPhi = cos(phi)
45            sinPhi = sin(phi)
46            dist = outerRadius + innerRadius * cosPhi
47
48            glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi)
49            glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi)
50            glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi)
51            glVertex3f(cosTheta * dist, -sinTheta * dist,  innerRadius * sinPhi)
52        glEnd()
53        theta = theta1
54        cosTheta = cosTheta1
55        sinTheta = sinTheta1
56
57
58def render_image():
59    light_ambient = [0.0, 0.0, 0.0, 1.0]
60    light_diffuse = [1.0, 1.0, 1.0, 1.0]
61    light_specular = [1.0, 1.0, 1.0, 1.0]
62    light_position = [1.0, 1.0, 1.0, 0.0]
63    red_mat = [1.0, 0.2, 0.2, 1.0]
64    green_mat = [0.2, 1.0, 0.2, 1.0]
65    blue_mat = [0.2, 0.2, 1.0, 1.0]
66
67    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient)
68    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse)
69    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular)
70    glLightfv(GL_LIGHT0, GL_POSITION, light_position)
71
72    glEnable(GL_LIGHTING)
73    glEnable(GL_LIGHT0)
74    glEnable(GL_DEPTH_TEST)
75
76    glMatrixMode(GL_PROJECTION)
77    glLoadIdentity()
78    glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0)
79    glMatrixMode(GL_MODELVIEW)
80
81    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
82
83    glPushMatrix()
84    glRotatef(20.0, 1.0, 0.0, 0.0)
85
86    glPushMatrix()
87    glTranslatef(-0.75, 0.5, 0.0)
88    glRotatef(90.0, 1.0, 0.0, 0.0)
89    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat)
90    torus(0.275, 0.85, 20, 20)
91    glPopMatrix()
92
93    glPushMatrix()
94    glTranslatef(-0.75, -0.5, 0.0)
95    glRotatef(270.0, 1.0, 0.0, 0.0)
96    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat)
97    cone(1.0, 2.0, 16, 1)
98    glPopMatrix()
99
100    glPushMatrix()
101    glTranslatef(0.75, 0.0, -1.0)
102    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat)
103    sphere(1.0, 20, 20)
104    glPopMatrix()
105
106    glPopMatrix()
107
108    # This is very important!!!
109    # Make sure buffered commands are finished!!!
110    glFinish()
111
112
113def write_ppm(buf, filename):
114    f = open(filename, "w")
115    if f:
116        h, w, c = buf.shape
117        print( "P3", file=f)
118        print( "# ascii ppm file created by osmesa",file=f)
119        print( "%i %i" % (w, h),file=f)
120        print("255",file=f)
121        for y in range(h - 1, -1, -1):
122            for x in range(w):
123                pixel = buf[y, x]
124                l = " %3d %3d %3d" % (pixel[0], pixel[1], pixel[2])
125                f.write(l)
126            f.write("\n")
127
128if __name__ == '__main__':
129    from OpenGL import arrays
130
131    ctx = OSMesaCreateContext(OSMESA_RGBA, None)
132    #ctx = OSMesaCreateContextExt(OSMESA_RGBA, 32, 0, 0, None)
133
134    width, height = 400, 400
135    buf = arrays.GLubyteArray.zeros((height, width, 4))
136    assert(OSMesaMakeCurrent(ctx, buf, GL_UNSIGNED_BYTE, width, height))
137
138    assert(OSMesaGetCurrentContext())
139
140    program = glGenProgramsARB(1)
141    assert(program)
142
143    z = glGetIntegerv(GL_DEPTH_BITS)
144    s = glGetIntegerv(GL_STENCIL_BITS)
145    a = glGetIntegerv(GL_ACCUM_RED_BITS)
146    print("Depth=%d Stencil=%d Accum=%d" % (z, s, a))
147
148    print("Width=%d Height=%d" % (OSMesaGetIntegerv(OSMESA_WIDTH),
149                                  OSMesaGetIntegerv(OSMESA_HEIGHT)))
150    #OSMesaPixelStore(OSMESA_Y_UP, 0)
151
152    render_image()
153
154    write_ppm(buf, 'output.ppm')
155
156    OSMesaDestroyContext(ctx)
157