OpenGL/Utah teapot

From Rosetta Code
Revision as of 21:43, 5 September 2021 by PureFox (talk | contribs) (Added Wren)
OpenGL/Utah teapot is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

This is a way to render the classic Utah Teapot using OpenGL library.

See also: 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 primitive drawing functions. 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. <lang C>

  1. 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; } </lang>

Go

Translation of: C
Library: FreeGLUT


Although there are a number of third party Go bindings for OpenGL, the following uses 'cgo' to interface directly with the C libraries. <lang go>package main

/*

  1. cgo LDFLAGS: -lGL -lGLU -lglut
  2. include <stdlib.h>
  3. 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))

}</lang>

J

Translation of: C
Library: FreeGLUT


Direct translation from C. <lang J>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 )</lang>

Julia

Makie implements OpenGL shading graphics as part of its plotting functionality. The files are from the University of Utah site. <lang Julia>using Makie, FileIO, InfoZIP

if stat("newell_teaset/teapot.obj").size == 0

   download("https://www.cs.utah.edu/~natevm/newell_teaset/newell_teaset.zip", "newell_teaset.zip")
   InfoZIP.unzip("newell_teaset.zip")

end

utah_teapot = FileIO.load("newell_teaset/teapot.obj") scene = plot(utah_teapot; color = :aquamarine, shading=true, show_axis=false) rotate!(scene, Quaternion(0.6, 0.2, 0.2, 4.0)) display(scene) </lang>

Kotlin

Translation of: C
Library: FreeGLUT
Works with: Ubuntu 14.04

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. <lang scala>// 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()

}</lang>

Nim

Translation of: C
Library: OpenGL

<lang Nim>import opengl, opengl/glut

var

 rot = 0.0
 matCol = [GLfloat 1, 0, 0, 0]

proc onIdle() {.cdecl.} =

 rot += 0.01
 glutPostRedisplay()

proc display() {.cdecl.} =

 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
 glPushMatrix()
 glRotatef(30, 1, 1, 0)
 glRotatef(rot, 0, 1, 1)
 glMaterialfv(GL_FRONT, GL_DIFFUSE, addr(matCol[0]))
 glutWireTeapot(0.5)
 glPopMatrix()
 glFlush()

var argc: cint = 0 glutInit(addr(argc), nil) glutInitDisplayMode(GLUT_SINGLE or GLUT_RGB or GLUT_DEPTH) glutInitWindowSize(900, 700) discard glutCreateWindow("Utah Teapot") glutIdleFunc(onIdle) glutDisplayFunc(display) loadExtensions() glutMainLoop()</lang>

Ol

Library: GL
Library: GLU

<lang lisp>

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:))

</lang>

Phix

Translation of: C

<lang 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()</lang> To run this, you will need the freeglut package from PCAN

Raku

Translation of: C

<lang perl6># 20210524 Raku programming solution

use NativeCall;

my $rot = 0e0;

                           # https://www.khronos.org/opengl/wiki/OpenGL_Type

enum GLenum (

  GL_SMOOTH   => 0x1D01,   GL_LIGHT0     => 0x4000,   GL_AMBIENT   => 0x1200,
  GL_DIFFUSE  => 0x1201,   GL_FRONT      => 0x0404,   GL_SHININESS => 0x1601,
  GL_LIGHTING => 0x0B50,   GL_DEPTH_TEST => 0x0B71,

); enum GLbitfield ( GL_COLOR_BUFFER_BIT => 0x00004000, GL_DEPTH_BUFFER_BIT => 0x00000100, ); enum GLUTdisplay_mode ( GLUT_RGB => 0x0000, GLUT_SINGLE => 0x0000, GLUT_DEPTH => 0x0010, );


constant $lib = 'glut'; sub glutInit(CArray[uint32], CArray[Str]) is native($lib) {*}; sub glutInitDisplayMode(uint32 $mode) is native($lib) {*}; sub glutInitWindowSize(int32 $width, int32 $height) is native($lib) {*}; sub glutCreateWindow(Str $str) is native($lib) {*}; sub glutDisplayFunc(&func ()) is native($lib) {*}; sub glutWireTeapot(num64 $size) is native($lib) {*}; sub glutIdleFunc(&func ()) is native($lib) {*}; sub glutPostRedisplay() is native($lib) {*}; sub glutMainLoop() is native($lib) {*};


constant $gllib = 'GL'; sub glClearColor(num32 $red, num32 $green, num32 $blue, num32 $alpha) is native($gllib) {*}; sub glShadeModel(int32) is native($gllib) {*}; sub glEnable(int32) is native($gllib) {*}; sub glClear(int32) is native($gllib) {*}; sub glRotatef(num32 $angle, num32 $x, num32 $y, num32 $z) is native($gllib) {*}; sub glPushMatrix() is native($gllib) {*}; sub glPopMatrix() is native($gllib) {*}; sub glFlush() is native($gllib) {*}; sub glLightfv (int32, int32, CArray[num32]) is native($gllib) {*}; sub glMaterialfv(int32, int32, CArray[num32]) is native($gllib) {*};


sub init {

  glClearColor(.5e0,.5e0,.5e0,0e0);
  glShadeModel(GL_SMOOTH);
  glLightfv(GL_LIGHT0,GL_AMBIENT,CArray[num32].new: 1e0,1e0,1e0,0e0); # white
  glLightfv(GL_LIGHT0,GL_DIFFUSE,CArray[num32].new: 1e0,1e0,1e0,0e0); # white
  glMaterialfv(GL_FRONT,GL_SHININESS,CArray[num32].new: 70e0); # skinless so no effect ?
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);

}

sub display {

  glClear(GL_COLOR_BUFFER_BIT+|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glRotatef(30e0,1e0,1e0,0e0);
  glRotatef($rot,0e0,1e0,1e0);
  glMaterialfv(GL_FRONT,GL_DIFFUSE, CArray[num32].new: 0e0,1e0,0e0,0e0); # green
  glutWireTeapot(.5e0);
  glPopMatrix();
  glFlush();

}

sub onIdle {

  $rot += 0.1e0;       # changed from 0.01 for faster rotation rate
  glutPostRedisplay();

}


glutInit(CArray[uint32].new,CArray[Str].new); 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(); </lang>

Output: (Offsite Media file)

Wren

Translation of: C
Library: FreeGLUT

As it's not currently possible for Wren-cli to access OpenGL directly, we embed a Wren script in a C application to complete this task. See the OpenGL#wren task for some of the issues involved here. <lang ecmascript>/* utah_teapot.wren */

var Rot = 0 var MatCol = [1, 0, 0, 0]

var GL_COLOR_BUFFER_BIT = 0x4000 var GL_DEPTH_BUFFER_BIT = 0x0100

var GL_SMOOTH = 0x1d01 var GL_FRONT = 0x0404 var GL_DIFFUSE = 0x1201 var GL_LIGHT0 = 0x4000 var GL_AMBIENT = 0x1200 var GL_LIGHTING = 0x0b50 var GL_SHININESS = 0x1601 var GL_DEPTH_TEST = 0x0B71

var GLUT_SINGLE = 0x0000 var GLUT_RGB = 0x0000 var GLUT_DEPTH = 0x0010

var GLUT_ACTION_ON_WINDOW_CLOSE = 0x01f9 var GLUT_ACTION_GLUTMAINLOOP_RETURNS = 0x0001

class GL {

   foreign static clearColor(red, green, blue, alpha)
   foreign static clear(mask)
   foreign static shadeModel(mode)
   foreign static pushMatrix()
   foreign static rotatef(angle, x, y, z)
   foreign static materialfv(face, pname, params)
   foreign static popMatrix()
   foreign static flush()
   foreign static lightfv(light, pname, params)
   foreign static enable(cap)

}

class Glut {

   foreign static initDisplayMode(mode)
   foreign static initWindowSize(width, height)
   foreign static createWindow(name)
   foreign static displayFunc(clazz, method)
   foreign static idleFunc(clazz, method)
   foreign static postRedisplay()
   foreign static wireTeapot(dSize)
   foreign static setOption(eWhat, value)

}

class GLCallbacks {

   static display() {
       GL.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

GL.pushMatrix() GL.rotatef(30, 1, 1, 0) GL.rotatef(Rot, 0, 1, 1) GL.materialfv(GL_FRONT, GL_DIFFUSE, MatCol) Glut.wireTeapot(0.5) GL.popMatrix() GL.flush()

   }
   static onIdle() {
       Rot = Rot + 0.01
       Glut.postRedisplay()
   }

}

var init = Fn.new {

   var white = [1, 1, 1, 0]
   var shini = [70]
   GL.clearColor(0.5, 0.5, 0.5, 0)

GL.shadeModel(GL_SMOOTH) GL.lightfv(GL_LIGHT0, GL_AMBIENT, white) GL.lightfv(GL_LIGHT0, GL_DIFFUSE, white) GL.materialfv(GL_FRONT, GL_SHININESS, shini) GL.enable(GL_LIGHTING) GL.enable(GL_LIGHT0) GL.enable(GL_DEPTH_TEST) }

Glut.initDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH) Glut.initWindowSize(900, 700) Glut.createWindow("The Amazing, Rotating Utah Teapot brought to you in OpenGL via freeglut.") init.call() Glut.displayFunc("GLCallbacks", "display()") Glut.idleFunc("GLCallbacks", "onIdle()") Glut.setOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS)</lang>
We now embed this Wren script in the following C program, compile and run it. <lang c>#include <stdlib.h>

  1. include <stdio.h>
  2. include <string.h>
  3. include <GL/gl.h>
  4. include <GL/freeglut.h>
  5. include "wren.h"

/* C <=> Wren interface functions */

WrenVM *vm;

const char *displayClass, *displayMethod, *idleClass, *idleMethod;

void display() {

   wrenEnsureSlots(vm, 1);
   wrenGetVariable(vm, "main", displayClass, 0);
   WrenHandle *method = wrenMakeCallHandle(vm, displayMethod);
   wrenCall(vm, method);
   wrenReleaseHandle(vm, method);

}

void idle() {

   wrenEnsureSlots(vm, 1);
   wrenGetVariable(vm, "main", idleClass, 0);
   WrenHandle *method = wrenMakeCallHandle(vm, idleMethod);
   wrenCall(vm, method);
   wrenReleaseHandle(vm, method);

}

void C_clearColor(WrenVM* vm) {

   GLclampf red   = (GLclampf)wrenGetSlotDouble(vm, 1);
   GLclampf green = (GLclampf)wrenGetSlotDouble(vm, 2);
   GLclampf blue  = (GLclampf)wrenGetSlotDouble(vm, 3);
   GLclampf alpha = (GLclampf)wrenGetSlotDouble(vm, 4);
   glClearColor(red, green, blue, alpha);

}

void C_clear(WrenVM* vm) {

   GLbitfield mask = (GLbitfield)wrenGetSlotDouble(vm, 1);
   glClear(mask);

}

void C_shadeModel(WrenVM* vm) {

   GLenum mode = (GLenum)wrenGetSlotDouble(vm, 1);
   glShadeModel(mode);

}

void C_pushMatrix(WrenVM* vm) {

   glPushMatrix();

}

void C_rotatef(WrenVM* vm) {

   GLdouble angle = (GLdouble)wrenGetSlotDouble(vm, 1);
   GLdouble x     = (GLdouble)wrenGetSlotDouble(vm, 2);
   GLdouble y     = (GLdouble)wrenGetSlotDouble(vm, 3);
   GLdouble z     = (GLdouble)wrenGetSlotDouble(vm, 4);
   glRotatef(angle, x, y, z);

}

void C_materialfv(WrenVM* vm) {

   GLenum face   = (GLenum)wrenGetSlotDouble(vm, 1);
   GLenum pname  = (GLenum)wrenGetSlotDouble(vm, 2);
   int count = wrenGetListCount(vm, 3);
   GLfloat params[count];
   int i;
   for (i = 0; i < count; ++i) {
       wrenGetListElement(vm, 3, i, 1);
       params[i] = (GLfloat)wrenGetSlotDouble(vm, 1);
   }
   glMaterialfv(face, pname, (const GLfloat*)params);

}

void C_popMatrix(WrenVM* vm) {

   glPopMatrix();

}

void C_flush(WrenVM* vm) {

   glFlush();

}

void C_lightfv(WrenVM* vm) {

   GLenum light  = (GLenum)wrenGetSlotDouble(vm, 1);
   GLenum pname  = (GLenum)wrenGetSlotDouble(vm, 2);
   int count = wrenGetListCount(vm, 3);
   GLfloat params[count];
   int i;
   for (i = 0; i < count; ++i) {
       wrenGetListElement(vm, 3, i, 1);
       params[i] = (GLfloat)wrenGetSlotDouble(vm, 1);
   }
   glLightfv(light, pname, (const GLfloat*)params);

}

void C_enable(WrenVM* vm) {

   GLenum cap = (GLenum)wrenGetSlotDouble(vm, 1);
   glEnable(cap);

}

void C_initDisplayMode(WrenVM* vm) {

   unsigned int mode = (unsigned int)wrenGetSlotDouble(vm, 1);
   glutInitDisplayMode(mode);

}

void C_initWindowSize(WrenVM* vm) {

   int width  = (int)wrenGetSlotDouble(vm, 1);
   int height = (int)wrenGetSlotDouble(vm, 2);
   glutInitWindowSize(width, height);

}

void C_createWindow(WrenVM* vm) {

   const char *name = wrenGetSlotString(vm, 1);
   glutCreateWindow(name);

}

void C_displayFunc(WrenVM* vm) {

   displayClass  = wrenGetSlotString(vm, 1);
   displayMethod = wrenGetSlotString(vm, 2);
   glutDisplayFunc(&display);

}

void C_idleFunc(WrenVM* vm) {

   idleClass  = wrenGetSlotString(vm, 1);
   idleMethod = wrenGetSlotString(vm, 2);
   glutIdleFunc(&idle);

}

void C_postRedisplay(WrenVM* vm) {

   glutPostRedisplay();

}

void C_wireTeapot(WrenVM* vm) {

   GLdouble dSize = (GLdouble)wrenGetSlotDouble(vm, 1);
   glutWireTeapot(dSize);

}

void C_setOption(WrenVM* vm) {

   GLenum eWhat = (GLenum)wrenGetSlotDouble(vm, 1);
   int value    = (int)wrenGetSlotDouble(vm, 2);
   glutSetOption(eWhat, value);

}

WrenForeignMethodFn bindForeignMethod(

   WrenVM* vm,
   const char* module,
   const char* className,
   bool isStatic,
   const char* signature) {
   if (strcmp(module, "main") == 0) {
       if (strcmp(className, "GL") == 0) {
           if (isStatic && strcmp(signature, "clearColor(_,_,_,_)") == 0) return C_clearColor;
           if (isStatic && strcmp(signature, "clear(_)") == 0)            return C_clear;
           if (isStatic && strcmp(signature, "shadeModel(_)") == 0)       return C_shadeModel;
           if (isStatic && strcmp(signature, "pushMatrix()") == 0)        return C_pushMatrix;
           if (isStatic && strcmp(signature, "rotatef(_,_,_,_)") == 0)    return C_rotatef;
           if (isStatic && strcmp(signature, "materialfv(_,_,_)") == 0)   return C_materialfv;
           if (isStatic && strcmp(signature, "popMatrix()") == 0)         return C_popMatrix;
           if (isStatic && strcmp(signature, "flush()") == 0)             return C_flush;
           if (isStatic && strcmp(signature, "lightfv(_,_,_)") == 0)      return C_lightfv;
           if (isStatic && strcmp(signature, "enable(_)") == 0)           return C_enable;
       } else if (strcmp(className, "Glut") == 0) {
           if (isStatic && strcmp(signature, "initDisplayMode(_)") == 0)  return C_initDisplayMode;
           if (isStatic && strcmp(signature, "initWindowSize(_,_)") == 0) return C_initWindowSize;
           if (isStatic && strcmp(signature, "createWindow(_)") == 0)     return C_createWindow;
           if (isStatic && strcmp(signature, "displayFunc(_,_)") == 0)    return C_displayFunc;
           if (isStatic && strcmp(signature, "idleFunc(_,_)") == 0)       return C_idleFunc;
           if (isStatic && strcmp(signature, "postRedisplay()") == 0)     return C_postRedisplay;
           if (isStatic && strcmp(signature, "wireTeapot(_)") == 0)       return C_wireTeapot;
           if (isStatic && strcmp(signature, "setOption(_,_)") == 0)      return C_setOption;
       }
   }
   return NULL;

}

static void writeFn(WrenVM* vm, const char* text) {

   printf("%s", text);

}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {

   switch (errorType) {
       case WREN_ERROR_COMPILE:
           printf("[%s line %d] [Error] %s\n", module, line, msg);
           break;
       case WREN_ERROR_STACK_TRACE:
           printf("[%s line %d] in %s\n", module, line, msg);
           break;
       case WREN_ERROR_RUNTIME:
           printf("[Runtime Error] %s\n", msg);
           break;
   }

}

char *readFile(const char *fileName) {

   FILE *f = fopen(fileName, "r");
   fseek(f, 0, SEEK_END);
   long fsize = ftell(f);
   rewind(f);
   char *script = malloc(fsize + 1);
   fread(script, 1, fsize, f);
   fclose(f);
   script[fsize] = 0;
   return script;

}

int main(int argc, char **argv) {

   glutInit(&argc, argv);
   WrenConfiguration config;
   wrenInitConfiguration(&config);
   config.writeFn = &writeFn;
   config.errorFn = &errorFn;
   config.bindForeignMethodFn = &bindForeignMethod;
   vm = wrenNewVM(&config);
   const char* module = "main";
   const char* fileName = "utah_teapot.wren";
   char *script = readFile(fileName);
   WrenInterpretResult result = wrenInterpret(vm, module, script);
   switch (result) {
       case WREN_RESULT_COMPILE_ERROR:
           printf("Compile Error!\n");
           break;
       case WREN_RESULT_RUNTIME_ERROR:
           printf("Runtime Error!\n");
           break;
       case WREN_RESULT_SUCCESS:
           break;
   }
   glutMainLoop();
   wrenFreeVM(vm);
   free(script);
   return 0;

}</lang>

Output:
Same as C example.