349 lines
10 KiB
JavaScript
349 lines
10 KiB
JavaScript
|
/*
|
||
|
node-x11 JavaScript version of glxgears
|
||
|
https://github.com/sidorares/node-x11
|
||
|
adopted version is intentionally as much close to glxgears.c as possible
|
||
|
Andrey Sidorov sidorares@yandex.ru
|
||
|
|
||
|
original code (C) Brian Paul
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included
|
||
|
* in all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*/
|
||
|
/* $XFree86: xc/programs/glxgears/glxgears.c,v 1.2 2001/04/03 15:56:26 dawes Exp $ */
|
||
|
|
||
|
/*
|
||
|
* This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT)
|
||
|
* Port by Brian Paul 23 March 2001
|
||
|
*
|
||
|
* Command line options:
|
||
|
* -info print GL implementation information
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
var view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
|
||
|
var gear1, gear2, gear3;
|
||
|
var angle = 0.0;
|
||
|
var M_PI = Math.PI;
|
||
|
var sin = Math.sin;
|
||
|
var cos = Math.cos;
|
||
|
var sqrt = Math.sqrt;
|
||
|
var model = require('./teapot');
|
||
|
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
* Draw a gear wheel. You'll probably want to call this function when
|
||
|
* building a display list since we do a lot of trig here.
|
||
|
*
|
||
|
* Input: inner_radius - radius of hole at center
|
||
|
* outer_radius - radius at center of teeth
|
||
|
* width - width of gear
|
||
|
* teeth - number of teeth
|
||
|
* tooth_depth - depth of tooth
|
||
|
*/
|
||
|
|
||
|
function gear(gl, inner_radius, outer_radius, width, teeth, tooth_depth)
|
||
|
{
|
||
|
var i;
|
||
|
var r0, r1, r2;
|
||
|
var angle, da;
|
||
|
var u, v, len;
|
||
|
|
||
|
r0 = inner_radius;
|
||
|
r1 = outer_radius - tooth_depth / 2.0;
|
||
|
r2 = outer_radius + tooth_depth / 2.0;
|
||
|
|
||
|
da = 2.0 * M_PI / teeth / 4.0;
|
||
|
|
||
|
gl.ShadeModel(gl.FLAT);
|
||
|
gl.Normal3f(0.0, 0.0, 1.0);
|
||
|
|
||
|
/* draw front face */
|
||
|
gl.Begin(gl.QUAD_STRIP);
|
||
|
for (i = 0; i <= teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||
|
if (i < teeth) {
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
width * 0.5);
|
||
|
}
|
||
|
}
|
||
|
gl.End();
|
||
|
|
||
|
/* draw front sides of teeth */
|
||
|
gl.Begin(gl.QUADS);
|
||
|
da = 2.0 * M_PI / teeth / 4.0;
|
||
|
for (i = 0; i < teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
|
||
|
width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
width * 0.5);
|
||
|
}
|
||
|
gl.End();
|
||
|
|
||
|
gl.Normal3f(0.0, 0.0, -1.0);
|
||
|
|
||
|
/* draw back face */
|
||
|
gl.Begin(gl.QUAD_STRIP);
|
||
|
for (i = 0; i <= teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||
|
if (i < teeth) {
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
-width * 0.5);
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||
|
}
|
||
|
}
|
||
|
gl.End();
|
||
|
|
||
|
/* draw back sides of teeth */
|
||
|
gl.Begin(gl.QUADS);
|
||
|
da = 2.0 * M_PI / teeth / 4.0;
|
||
|
for (i = 0; i < teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
-width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
|
||
|
-width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||
|
}
|
||
|
gl.End();
|
||
|
|
||
|
/* draw outward faces of teeth */
|
||
|
gl.Begin(gl.QUAD_STRIP);
|
||
|
for (i = 0; i < teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
|
||
|
u = r2 * cos(angle + da) - r1 * cos(angle);
|
||
|
v = r2 * sin(angle + da) - r1 * sin(angle);
|
||
|
len = sqrt(u * u + v * v);
|
||
|
u /= len;
|
||
|
v /= len;
|
||
|
gl.Normal3f(v, -u, 0.0);
|
||
|
gl.Vertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
|
||
|
gl.Normal3f(cos(angle), sin(angle), 0.0);
|
||
|
gl.Vertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
|
||
|
width * 0.5);
|
||
|
gl.Vertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
|
||
|
-width * 0.5);
|
||
|
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
|
||
|
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
|
||
|
gl.Normal3f(v, -u, 0.0);
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
|
||
|
-width * 0.5);
|
||
|
gl.Normal3f(cos(angle), sin(angle), 0.0);
|
||
|
}
|
||
|
|
||
|
gl.Vertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
|
||
|
gl.Vertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
|
||
|
|
||
|
gl.End();
|
||
|
|
||
|
gl.ShadeModel(gl.SMOOTH);
|
||
|
|
||
|
/* draw inside radius cylinder */
|
||
|
gl.Begin(gl.QUAD_STRIP);
|
||
|
for (i = 0; i <= teeth; i++) {
|
||
|
angle = i * 2.0 * M_PI / teeth;
|
||
|
gl.Normal3f(-cos(angle), -sin(angle), 0.0);
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
|
||
|
gl.Vertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
|
||
|
}
|
||
|
gl.End();
|
||
|
gl.render();
|
||
|
|
||
|
gl.Begin(gl.TRIANGLES);
|
||
|
var t = 0;
|
||
|
var v = 0;
|
||
|
|
||
|
|
||
|
for (t=0; t < model.indices.length; t+= 3) {
|
||
|
for (v = 0; v < 3; ++v) {
|
||
|
var ind = model.indices[t + v]*3;
|
||
|
var x = 0.1*model.vertexPositions[ind + 0];
|
||
|
var y = 0.1*model.vertexPositions[ind + 1];
|
||
|
var z = 0.1*model.vertexPositions[ind + 2];
|
||
|
gl.Vertex3f(x, y, z);
|
||
|
x = model.vertexNormals[ind + 0];
|
||
|
y = model.vertexNormals[ind + 1];
|
||
|
z = model.vertexNormals[ind + 2];
|
||
|
gl.Normal3f(y, x, z);
|
||
|
//console.log(x, y, z);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gl.End();
|
||
|
gl.render();
|
||
|
}
|
||
|
|
||
|
|
||
|
function draw(gl)
|
||
|
{
|
||
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
||
|
|
||
|
gl.PushMatrix();
|
||
|
gl.Rotatef(view_rotx, 1.0, 0.0, 0.0);
|
||
|
gl.Rotatef(view_roty, 0.0, 1.0, 0.0);
|
||
|
gl.Rotatef(view_rotz, 0.0, 0.0, 1.0);
|
||
|
|
||
|
gl.PushMatrix();
|
||
|
gl.Translatef(-3.0, -2.0, 0.0);
|
||
|
gl.Rotatef(angle, 0.0, 0.0, 1.0);
|
||
|
gl.CallList(gear1);
|
||
|
gl.PopMatrix();
|
||
|
|
||
|
/*
|
||
|
gl.PushMatrix();
|
||
|
gl.Translatef(3.1, -2.0, 0.0);
|
||
|
gl.Rotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
|
||
|
gl.CallList(gear2);
|
||
|
gl.PopMatrix();
|
||
|
|
||
|
gl.PushMatrix();
|
||
|
gl.Translatef(-3.1, 4.2, 0.0);
|
||
|
gl.Rotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
|
||
|
gl.CallList(gear3);
|
||
|
gl.PopMatrix();
|
||
|
*/
|
||
|
gl.PopMatrix();
|
||
|
}
|
||
|
|
||
|
|
||
|
/* new window size or exposure */
|
||
|
function reshape(gl, width, height)
|
||
|
{
|
||
|
var h = height / width;
|
||
|
gl.Viewport(0, 0, width, height);
|
||
|
gl.MatrixMode(gl.PROJECTION);
|
||
|
gl.LoadIdentity();
|
||
|
gl.Frustum(-1.0, 1.0, -h, h, 5.0, 60.0);
|
||
|
gl.MatrixMode(gl.MODELVIEW);
|
||
|
gl.LoadIdentity();
|
||
|
gl.Translatef(0.0, 0.0, -40.0);
|
||
|
gl.Scalef(0.1, 0.1, 0.1);
|
||
|
gl.render();
|
||
|
}
|
||
|
|
||
|
|
||
|
function init(gl, done)
|
||
|
{
|
||
|
var pos = [5.0, 5.0, 10.0, 0.0]
|
||
|
var red = [ 0.8, 0.1, 0.0, 1.0 ];
|
||
|
var green = [ 0.0, 0.8, 0.2, 1.0 ];
|
||
|
var blue = [ 0.2, 0.2, 1.0, 1.0 ];
|
||
|
|
||
|
gl.Lightfv(gl.LIGHT0, gl.POSITION, pos);
|
||
|
gl.Enable(gl.CULL_FACE);
|
||
|
gl.Enable(gl.LIGHTING);
|
||
|
gl.Enable(gl.LIGHT0);
|
||
|
gl.Enable(gl.DEPTH_TEST);
|
||
|
|
||
|
/* make the gears */
|
||
|
gl.GenLists(3, function(err, startIndex) {
|
||
|
gear1 = startIndex;
|
||
|
gl.NewList(gear1, gl.COMPILE);
|
||
|
gl.Materialfv(gl.FRONT, gl.AMBIENT_AND_DIFFUSE, red);
|
||
|
gear(gl, 1.0, 4.0, 1.0, 20, 0.7);
|
||
|
gl.EndList();
|
||
|
|
||
|
gear2 = startIndex + 1;
|
||
|
gl.NewList(gear2, gl.COMPILE);
|
||
|
gl.Materialfv(gl.FRONT, gl.AMBIENT_AND_DIFFUSE, green);
|
||
|
gear(gl, 0.5, 2.0, 2.0, 10, 0.7);
|
||
|
gl.EndList();
|
||
|
|
||
|
gear3 = startIndex + 2;
|
||
|
gl.NewList(gear3, gl.COMPILE);
|
||
|
gl.Materialfv(gl.FRONT, gl.AMBIENT_AND_DIFFUSE, blue);
|
||
|
gear(gl, 1.3, 2.0, 0.5, 10, 0.7);
|
||
|
gl.EndList();
|
||
|
gl.Enable(gl.NORMALIZE);
|
||
|
done();
|
||
|
});
|
||
|
}
|
||
|
|
||
|
var x11 = require('../../lib');
|
||
|
var eventmask = x11.eventMask.PointerMotion|x11.eventMask.ButtonPress|x11.eventMask.ButtonRelease|x11.eventMask.StructureNotify|x11.eventMask.Exposure;
|
||
|
|
||
|
x11.createClient(function(err, display) {
|
||
|
var X = display.client;
|
||
|
var root = display.screen[0].root;
|
||
|
var width = 1000;
|
||
|
var height = 1000;
|
||
|
X.require('glx', function(err, GLX) {
|
||
|
var visual = 0xa1;
|
||
|
var win = X.AllocID();
|
||
|
X.CreateWindow(win, root, 0, 0, width, height, 0, 0, 0, 0, { eventMask: eventmask });
|
||
|
X.MapWindow(win);
|
||
|
|
||
|
var ctx = X.AllocID();
|
||
|
GLX.CreateContext(ctx, 0xa1, 0, 0, 0);
|
||
|
GLX.MakeCurrent(win, ctx, 0, function() {});
|
||
|
var gl = GLX.renderPipeline(ctx);
|
||
|
|
||
|
var initialized = false;
|
||
|
init(gl, function() {
|
||
|
gl.render();
|
||
|
initialized = true;
|
||
|
setInterval(function() {
|
||
|
angle += 0.4;
|
||
|
reshape(gl, width, height);
|
||
|
draw(gl);
|
||
|
gl.SwapBuffers(win);
|
||
|
}, 20);
|
||
|
});
|
||
|
|
||
|
X.on('event', function(ev) {
|
||
|
switch(ev.type) {
|
||
|
case 22:
|
||
|
//reshape(gl, ev.width, ev.height);
|
||
|
width = ev.width;
|
||
|
height = ev.height;
|
||
|
break;
|
||
|
}
|
||
|
angle += 0.2;
|
||
|
reshape(gl, width, height);
|
||
|
if (initialized)
|
||
|
draw(gl);
|
||
|
gl.SwapBuffers(win);
|
||
|
});
|
||
|
|
||
|
});
|
||
|
X.on('error', function(err) { console.log(err); });
|
||
|
});
|
||
|
;
|