This is way to render classic Utah Teapot using OpenGL library.
See also: [https://en.wikipedia.org/wiki/Utah_teapot Utah Teapot wikipage].
C
As well explained on the Wikipedia page ( link above ), the teapot played such an important role in the development of Computer Graphics, that Mark Kilgard honoured it by giving it it's own [https://www.opengl.org/resources/libraries/glut/spec3/node89.html#SECTION000129000000000000000 primitive drawing functions]. [http://freeglut.sourceforge.net/ freeglut] did even better and implemented the rest of the tea set, yes, the API also provides a cup and a spoon.
This implementation sticks to the task requirements and only shows the teapot, it's rotating, so you can enjoy it's magnificence from all possible viewpoints and perspectives.
#include<gl/freeglut.h>
double rot = 0;
float matCol[] = {1,0,0,0};
void display(){
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(30,1,1,0);
glRotatef(rot,0,1,1);
glMaterialfv(GL_FRONT,GL_DIFFUSE,matCol);
glutWireTeapot(0.5);
glPopMatrix();
glFlush();
}
void onIdle(){
rot += 0.01;
glutPostRedisplay();
}
void init(){
float pos[] = {1,1,1,0};
float white[] = {1,1,1,0};
float shini[] = {70};
glClearColor(.5,.5,.5,0);
glShadeModel(GL_SMOOTH);
glLightfv(GL_LIGHT0,GL_AMBIENT,white);
glLightfv(GL_LIGHT0,GL_DIFFUSE,white);
glMaterialfv(GL_FRONT,GL_SHININESS,shini);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
}
int main(int argC, char* argV[])
{
glutInit(&argC,argV);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(900,700);
glutCreateWindow("The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut.");
init();
glutDisplayFunc(display);
glutIdleFunc(onIdle);
glutMainLoop();
return 0;
}
Go
Although there are a number of third party Go bindings for OpenGL, the following uses 'cgo' to interface directly with the C libraries.
package main
/*
#cgo LDFLAGS: -lGL -lGLU -lglut
#include <stdlib.h>
#include <GL/freeglut.h>
extern void display();
extern void onIdle();
typedef void (*callback) ();
static inline callback displayFunc() {
return display;
}
static inline callback idleFunc() {
return onIdle;
}
*/
import "C"
import "unsafe"
var rot = 0.0
var matCol = [4]C.float{1, 0, 0, 0}
//export display
func display() {
C.glClear(C.GL_COLOR_BUFFER_BIT | C.GL_DEPTH_BUFFER_BIT)
C.glPushMatrix()
C.glRotatef(30, 1, 1, 0)
C.glRotatef(C.float(rot), 0, 1, 1)
C.glMaterialfv(C.GL_FRONT, C.GL_DIFFUSE, &matCol[0])
C.glutWireTeapot(0.5)
C.glPopMatrix()
C.glFlush()
}
//export onIdle
func onIdle() {
rot += 0.01
C.glutPostRedisplay()
}
func initialize() {
white := [4]C.float{1, 1, 1, 0}
shini := [1]C.float{70}
C.glClearColor(0.5, 0.5, 0.5, 0)
C.glShadeModel(C.GL_SMOOTH)
C.glLightfv(C.GL_LIGHT0, C.GL_AMBIENT, &white[0])
C.glLightfv(C.GL_LIGHT0, C.GL_DIFFUSE, &white[0])
C.glMaterialfv(C.GL_FRONT, C.GL_SHININESS, &shini[0])
C.glEnable(C.GL_LIGHTING)
C.glEnable(C.GL_LIGHT0)
C.glEnable(C.GL_DEPTH_TEST)
}
func main() {
argc := C.int(0)
C.glutInit(&argc, nil)
C.glutInitDisplayMode(C.GLUT_SINGLE | C.GLUT_RGB | C.GLUT_DEPTH)
C.glutInitWindowSize(900, 700)
tl := "The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut."
tlc := C.CString(tl)
C.glutCreateWindow(tlc)
initialize()
C.glutDisplayFunc(C.displayFunc())
C.glutIdleFunc(C.idleFunc())
C.glutMainLoop()
C.free(unsafe.Pointer(tlc))
}
J
Direct translation from C.
NB. Teapot using freeglut
require '~Projects/freeglut/gldefs.ijs'
f=: 1.1-1.1
void=: 0$''
rot=: f+0
matCol=: f+1 0 0 0
cb1=: cdcb '+ x x'
cb2=: cdcb '+ x x x'
cdcallback=: 3 : 0
y=. 15!:17''
select. #y
case. 1 do. display 0
case. 2 do. onIdle 0
end.
)
display=: 3 : 0
glClear(GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT)
glPushMatrix void
glRotatef((30+f);(1+f);(1+f);f)
glRotatef(rot;f;(1+f);(1+f))
glMaterialfv(GL_FRONT;GL_DIFFUSE;<matCol)
glutWireTeapot(0.5)
glPopMatrix void
glFlush void
)
onIdle=: 3 : 0
rot=: rot+0.01
glutPostRedisplay void
)
init=: 3 : 0
pos=. f+1,1,1,0
white=. f+1,1,1,0
shini=. ,f+70
glClearColor(0.5;0.5;0.5;f)
glShadeModel(GL_SMOOTH)
glLightfv(GL_LIGHT0;GL_AMBIENT;white)
glLightfv(GL_LIGHT0;GL_DIFFUSE;white)
glMaterialfv(GL_FRONT;GL_SHININESS;shini)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
)
main=: 3 : 0
argC=. ,2-2
argV=.<,0{a.
glutInit(argC;argV)
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE;GLUT_ACTION_GLUTMAINLOOP_RETURNS)
glutInitDisplayMode(GLUT_SINGLE+GLUT_RGB+GLUT_DEPTH)
glutInitWindowSize(900;700)
glutCreateWindow(<'The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut.')
init void
glutDisplayFunc(cb1)
glutIdleFunc(cb2)
glutMainLoop void
void
)
Kotlin
Assuming that freeglut is already installed on your system in the default location(s), you first need to build opengl.klib using the following .def file and the cinterop tool:
// opengl.def
headers = /usr/include/GL/glut.h
compilerOpts = -I/usr/include
linkerOpts = -L/usr/lib/x86_64-linux-gnu -lglut -lGL -lGLU
You then need to compile the following Kotlin program, linking against opengl.klib, and run the resulting .kexe file to view the rotating teapot.
// Kotlin Native v0.6
import kotlinx.cinterop.*
import opengl.*
var rot = 0f
val matCol = floatArrayOf(1f, 0f, 0f, 0f)
fun display() {
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glRotatef(30f, 1f, 1f, 0f)
glRotatef(rot, 0f, 1f, 1f)
glMaterialfv(GL_FRONT, GL_DIFFUSE, matCol.toCValues())
glutWireTeapot(0.5)
glPopMatrix()
glFlush()
}
fun onIdle() {
rot += 0.1f
glutPostRedisplay()
}
fun init() {
val white = floatArrayOf(1f, 1f, 1f, 0f)
val shini = floatArrayOf(70f)
glClearColor(0.5f, 0.5f, 0.5f, 0f);
glShadeModel(GL_SMOOTH)
glLightfv(GL_LIGHT0, GL_AMBIENT, white.toCValues())
glLightfv(GL_LIGHT0, GL_DIFFUSE, white.toCValues())
glMaterialfv(GL_FRONT, GL_SHININESS, shini.toCValues())
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
}
fun main(args: Array<String>) {
memScoped {
val argc = alloc<IntVar>().apply { value = 0 }
glutInit(argc.ptr, null)
}
glutInitDisplayMode(GLUT_SINGLE or GLUT_RGB or GLUT_DEPTH)
glutInitWindowSize(900, 700)
val title = "The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut."
glutCreateWindow(title)
init()
glutDisplayFunc(staticCFunction(::display))
glutIdleFunc(staticCFunction(::onIdle))
glutMainLoop()
}
Ol
; initial data:
(define vertices '(
( 0.2000 0.0000 2.70000 ) ( 0.2000 -0.1120 2.70000 )
( 0.1120 -0.2000 2.70000 ) ( 0.0000 -0.2000 2.70000 )
( 1.3375 0.0000 2.53125 ) ( 1.3375 -0.7490 2.53125 )
( 0.7490 -1.3375 2.53125 ) ( 0.0000 -1.3375 2.53125 )
( 1.4375 0.0000 2.53125 ) ( 1.4375 -0.8050 2.53125 )
( 0.8050 -1.4375 2.53125 ) ( 0.0000 -1.4375 2.53125 )
( 1.5000 0.0000 2.40000 ) ( 1.5000 -0.8400 2.40000 )
( 0.8400 -1.5000 2.40000 ) ( 0.0000 -1.5000 2.40000 )
( 1.7500 0.0000 1.87500 ) ( 1.7500 -0.9800 1.87500 )
( 0.9800 -1.7500 1.87500 ) ( 0.0000 -1.7500 1.87500 )
( 2.0000 0.0000 1.35000 ) ( 2.0000 -1.1200 1.35000 )
( 1.1200 -2.0000 1.35000 ) ( 0.0000 -2.0000 1.35000 )
( 2.0000 0.0000 0.90000 ) ( 2.0000 -1.1200 0.90000 )
( 1.1200 -2.0000 0.90000 ) ( 0.0000 -2.0000 0.90000 )
( -2.0000 0.0000 0.90000 ) ( 2.0000 0.0000 0.45000 )
( 2.0000 -1.1200 0.45000 ) ( 1.1200 -2.0000 0.45000 )
( 0.0000 -2.0000 0.45000 ) ( 1.5000 0.0000 0.22500 )
( 1.5000 -0.8400 0.22500 ) ( 0.8400 -1.5000 0.22500 )
( 0.0000 -1.5000 0.22500 ) ( 1.5000 0.0000 0.15000 )
( 1.5000 -0.8400 0.15000 ) ( 0.8400 -1.5000 0.15000 )
( 0.0000 -1.5000 0.15000 ) ( -1.6000 0.0000 2.02500 )
( -1.6000 -0.3000 2.02500 ) ( -1.5000 -0.3000 2.25000 )
( -1.5000 0.0000 2.25000 ) ( -2.3000 0.0000 2.02500 )
( -2.3000 -0.3000 2.02500 ) ( -2.5000 -0.3000 2.25000 )
( -2.5000 0.0000 2.25000 ) ( -2.7000 0.0000 2.02500 )
( -2.7000 -0.3000 2.02500 ) ( -3.0000 -0.3000 2.25000 )
( -3.0000 0.0000 2.25000 ) ( -2.7000 0.0000 1.80000 )
( -2.7000 -0.3000 1.80000 ) ( -3.0000 -0.3000 1.80000 )
( -3.0000 0.0000 1.80000 ) ( -2.7000 0.0000 1.57500 )
( -2.7000 -0.3000 1.57500 ) ( -3.0000 -0.3000 1.35000 )
( -3.0000 0.0000 1.35000 ) ( -2.5000 0.0000 1.12500 )
( -2.5000 -0.3000 1.12500 ) ( -2.6500 -0.3000 0.93750 )
( -2.6500 0.0000 0.93750 ) ( -2.0000 -0.3000 0.90000 )
( -1.9000 -0.3000 0.60000 ) ( -1.9000 0.0000 0.60000 )
( 1.7000 0.0000 1.42500 ) ( 1.7000 -0.6600 1.42500 )
( 1.7000 -0.6600 0.60000 ) ( 1.7000 0.0000 0.60000 )
( 2.6000 0.0000 1.42500 ) ( 2.6000 -0.6600 1.42500 )
( 3.1000 -0.6600 0.82500 ) ( 3.1000 0.0000 0.82500 )
( 2.3000 0.0000 2.10000 ) ( 2.3000 -0.2500 2.10000 )
( 2.4000 -0.2500 2.02500 ) ( 2.4000 0.0000 2.02500 )
( 2.7000 0.0000 2.40000 ) ( 2.7000 -0.2500 2.40000 )
( 3.3000 -0.2500 2.40000 ) ( 3.3000 0.0000 2.40000 )
( 2.8000 0.0000 2.47500 ) ( 2.8000 -0.2500 2.47500 )
( 3.5250 -0.2500 2.49375 ) ( 3.5250 0.0000 2.49375 )
( 2.9000 0.0000 2.47500 ) ( 2.9000 -0.1500 2.47500 )
( 3.4500 -0.1500 2.51250 ) ( 3.4500 0.0000 2.51250 )
( 2.8000 0.0000 2.40000 ) ( 2.8000 -0.1500 2.40000 )
( 3.2000 -0.1500 2.40000 ) ( 3.2000 0.0000 2.40000 )
( 0.0000 0.0000 3.15000 ) ( 0.8000 0.0000 3.15000 )
( 0.8000 -0.4500 3.15000 ) ( 0.4500 -0.8000 3.15000 )
( 0.0000 -0.8000 3.15000 ) ( 0.0000 0.0000 2.85000 )
( 1.4000 0.0000 2.40000 ) ( 1.4000 -0.7840 2.40000 )
( 0.7840 -1.4000 2.40000 ) ( 0.0000 -1.4000 2.40000 )
( 0.4000 0.0000 2.55000 ) ( 0.4000 -0.2240 2.55000 )
( 0.2240 -0.4000 2.55000 ) ( 0.0000 -0.4000 2.55000 )
( 1.3000 0.0000 2.55000 ) ( 1.3000 -0.7280 2.55000 )
( 0.7280 -1.3000 2.55000 ) ( 0.0000 -1.3000 2.55000 )
( 1.3000 0.0000 2.40000 ) ( 1.3000 -0.7280 2.40000 )
( 0.7280 -1.3000 2.40000 ) ( 0.0000 -1.3000 2.40000 )))
(define Rim: '(
( 102 103 104 105 4 5 6 7
8 9 10 11 12 13 14 15 )))
(define Body: '(
( 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 )
( 24 25 26 27 29 30 31 32
33 34 35 36 37 38 39 40 )))
(define Lid: '(
( 96 96 96 96 97 98 99 100
101 101 101 101 0 1 2 3 )
( 0 1 2 3 106 107 108 109
110 111 112 113 114 115 116 117 )))
(define Handle: '(
( 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 )
( 53 54 55 56 57 58 59 60
61 62 63 64 28 65 66 67 )))
(define Spout: '(
( 68 69 70 71 72 73 74 75
76 77 78 79 80 81 82 83 )
( 80 81 82 83 84 85 86 87
88 89 90 91 92 93 94 95 )))
; render pass:
(define knots '(0 0 0 0 1 1 1 1))
(let ((render (lambda (surface)
(gluBeginSurface teapot)
(gluNurbsSurface teapot 8 knots 8 knots (* 4 3) 3 (fold append '() (map (lambda (n) (nth vertices n)) surface)) 4 4 GL_MAP2_VERTEX_3)
(gluEndSurface teapot))))
(for-each render Rim:)
(for-each render Body:)
(for-each render Lid:)
(glScalef -1 1 1)
(for-each render Rim:)
(for-each render Body:)
(for-each render Lid:)
(glScalef -1 -1 1)
(for-each render Rim:)
(for-each render Body:)
(for-each render Lid:)
(glScalef -1 1 1)
(for-each render Rim:)
(for-each render Body:)
(for-each render Lid:)
(for-each render Handle:)
(for-each render Spout:)
(glScalef 1 -1 1)
(for-each render Handle:)
(for-each render Spout:))
Phix
include GL/gl.e
include GL/freeglut.e
atom rot = 0;
atom matCol = allocate(16)
poke(matCol,
atom_to_float32(1) &
atom_to_float32(0) &
atom_to_float32(0) &
atom_to_float32(0)
)
function display()
glClear(or_bits(GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT))
glPushMatrix()
glRotatef(30,1,1,0)
glRotatef(rot,0,1,1)
glMaterialfv(GL_FRONT,GL_DIFFUSE,matCol)
glutWireTeapot(0.5)
glPopMatrix()
glFlush()
return 0
end function
function onIdle()
rot += 0.01
glutPostRedisplay()
return 0
end function
procedure init()
atom white = allocate(16)
poke(white,
atom_to_float32(1) &
atom_to_float32(1) &
atom_to_float32(1) &
atom_to_float32(0)
)
atom shini = allocate(4)
poke(shini,
atom_to_float32(70)
)
glClearColor(.5,.5,.5,0)
glShadeModel(GL_SMOOTH)
glLightfv(GL_LIGHT0,GL_AMBIENT,white)
glLightfv(GL_LIGHT0,GL_DIFFUSE,white)
glMaterialfv(GL_FRONT,GL_SHININESS,shini)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
end procedure
procedure main()
glutInit()
glutInitDisplayMode(or_all({GLUT_SINGLE,GLUT_RGB,GLUT_DEPTH}))
glutInitWindowSize(900,700)
{} = glutCreateWindow("The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut.")
init()
glutDisplayFunc(call_back(routine_id("display")))
glutIdleFunc(call_back(routine_id("onIdle")))
glutMainLoop()
end procedure
main()
To run this, you will need the freeglut package from [http://phix.x10.mx/pmwiki/pmwiki.php?n=Main.Freeglut-TheFreeOpenglUtilityToolkit PCAN]