OpenGL: Difference between revisions

Content added Content deleted
No edit summary
(Added Wren)
Line 2,786: Line 2,786:
-displayproc paintShape -reshapeproc resizedWin
-displayproc paintShape -reshapeproc resizedWin
pack .surface -fill both -expand 1</lang>Most of this code should be very familiar to anyone looking at the C version above, or with normal [[Tk]] applications.
pack .surface -fill both -expand 1</lang>Most of this code should be very familiar to anyone looking at the C version above, or with normal [[Tk]] applications.

=={{header|Wren}}==
{{trans|C}}
{{libheader|FreeGLUT}}
It is not currently possible for Wren-cli to access OpenGL directly, so we need to use an embedded application to complete this task. The following embeds a Wren script in a C application, the language which Wren itself is written in.

We wrap as many OpenGL/FreeGLUT calls as possible from the Wren side though glutInit (requires command line parameters) and glutMainLoop (requires a re-entrant VM) must be called by the host.

Notice that we can't pass Wren methods directly to the glutDisplayFunc and glutReshapeFunc functions for callback registration purposes because of re-entrancy problems so we simply instigate them from Wren and fix up the callbacks from the C side.
<lang ecmascript>/* opengl.wren */

var GL_COLOR_BUFFER_BIT = 0x4000
var GL_DEPTH_BUFFER_BIT = 0x0100

var GL_SMOOTH = 0x1d01
var GL_MODELVIEW = 0x1700
var GL_PROJECTION = 0x1701

var GL_TRIANGLES = 0x0004

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 loadIdentity()

foreign static translatef(x, y, z)

foreign static begin(mode)

foreign static color3f(red, green, blue)

foreign static vertex2f(x, y)

foreign static end()

foreign static flush()

foreign static viewport(x, y, width, height)

foreign static matrixMode(mode)

foreign static ortho(left, right, bottom, top, nearVal, farVal)
}

class Glut {
foreign static initWindowSize(width, height)

foreign static createWindow(name)

foreign static displayFunc()

foreign static reshapeFunc()

foreign static setOption(eWhat, value)
}

class GLCallbacks {
static paint() {
GL.clearColor(0.3, 0.3, 0.3, 0)
GL.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
GL.shadeModel(GL_SMOOTH)
GL.loadIdentity()
GL.translatef(-15, -15, 0)
GL.begin(GL_TRIANGLES)
GL.color3f(1, 0, 0)
GL.vertex2f(0, 0)
GL.color3f(0, 1, 0)
GL.vertex2f(30, 0)
GL.color3f(0, 0, 1)
GL.vertex2f(0, 30)
GL.end()
GL.flush()
}

static reshape(width, height) {
GL.viewport(0, 0, width, height)
GL.matrixMode(GL_PROJECTION)
GL.loadIdentity()
GL.ortho(-30, 30, -30, 30, -30, 30)
GL.matrixMode(GL_MODELVIEW)
}
}

Glut.initWindowSize(640, 480)
Glut.createWindow("Triangle")
Glut.displayFunc()
Glut.reshapeFunc()
Glut.setOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS)</lang>
<br>
We now embed this Wren script in the following C program, compile and run it.
<lang c>#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/gl.h>
#include <GL/freeglut.h>
#include "wren.h"

/* C <=> Wren interface functions */

WrenVM *vm;

void display() {
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "GLCallbacks", 0);
WrenHandle *method = wrenMakeCallHandle(vm, "paint()");
wrenCall(vm, method);
wrenReleaseHandle(vm, method);
}

void reshape(int width, int height) {
wrenEnsureSlots(vm, 3);
wrenGetVariable(vm, "main", "GLCallbacks", 0);
WrenHandle *method = wrenMakeCallHandle(vm, "reshape(_,_)");
wrenSetSlotDouble(vm, 1, (double)width);
wrenSetSlotDouble(vm, 2, (double)height);
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_loadIdentity(WrenVM* vm) {
glLoadIdentity();
}

void C_translatef(WrenVM* vm) {
GLfloat x = (GLfloat)wrenGetSlotDouble(vm, 1);
GLfloat y = (GLfloat)wrenGetSlotDouble(vm, 2);
GLfloat z = (GLfloat)wrenGetSlotDouble(vm, 3);
glTranslatef(x, y, z);
}

void C_begin(WrenVM* vm) {
GLenum mode = (GLenum)wrenGetSlotDouble(vm, 1);
glBegin(mode);
}

void C_color3f(WrenVM* vm) {
GLfloat red = (GLfloat)wrenGetSlotDouble(vm, 1);
GLfloat green = (GLfloat)wrenGetSlotDouble(vm, 2);
GLfloat blue = (GLfloat)wrenGetSlotDouble(vm, 3);
glColor3f(red, green, blue);
}

void C_vertex2f(WrenVM* vm) {
GLfloat x = (GLfloat)wrenGetSlotDouble(vm, 1);
GLfloat y = (GLfloat)wrenGetSlotDouble(vm, 2);
glVertex2f(x, y);
}

void C_end(WrenVM* vm) {
glEnd();
}

void C_flush(WrenVM* vm) {
glFlush();
}

void C_viewport(WrenVM* vm) {
GLint x = (GLint) wrenGetSlotDouble(vm, 1);
GLint y = (GLint) wrenGetSlotDouble(vm, 2);
GLsizei width = (GLsizei)wrenGetSlotDouble(vm, 3);
GLsizei height = (GLsizei)wrenGetSlotDouble(vm, 4);
glViewport(x, y, width, height);
}

void C_matrixMode(WrenVM* vm) {
GLenum mode = (GLenum)wrenGetSlotDouble(vm, 1);
glMatrixMode(mode);
}

void C_ortho(WrenVM* vm) {
GLdouble left = (GLdouble)wrenGetSlotDouble(vm, 1);
GLdouble right = (GLdouble)wrenGetSlotDouble(vm, 2);
GLdouble bottom = (GLdouble)wrenGetSlotDouble(vm, 3);
GLdouble top = (GLdouble)wrenGetSlotDouble(vm, 4);
GLdouble nearVal = (GLdouble)wrenGetSlotDouble(vm, 5);
GLdouble farVal = (GLdouble)wrenGetSlotDouble(vm, 6);
glOrtho(left, right, bottom, top, nearVal, farVal);
}

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) {
glutDisplayFunc(&display);
}

void C_reshapeFunc(WrenVM* vm) {
glutReshapeFunc(&reshape);
}

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, "loadIdentity()") == 0) return C_loadIdentity;
if (isStatic && strcmp(signature, "translatef(_,_,_)") == 0) return C_translatef;
if (isStatic && strcmp(signature, "begin(_)") == 0) return C_begin;
if (isStatic && strcmp(signature, "color3f(_,_,_)") == 0) return C_color3f;
if (isStatic && strcmp(signature, "vertex2f(_,_)") == 0) return C_vertex2f;
if (isStatic && strcmp(signature, "end()") == 0) return C_end;
if (isStatic && strcmp(signature, "flush()") == 0) return C_flush;
if (isStatic && strcmp(signature, "viewport(_,_,_,_)") == 0) return C_viewport;
if (isStatic && strcmp(signature, "matrixMode(_)") == 0) return C_matrixMode;
if (isStatic && strcmp(signature, "ortho(_,_,_,_,_,_)") == 0) return C_ortho;
} else if (strcmp(className, "Glut") == 0) {
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, "reshapeFunc()") == 0) return C_reshapeFunc;
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 = "opengl.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>

{{out}}
<pre>
Same as C example.
</pre>


{{omit from|ACL2}}
{{omit from|ACL2}}