370 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			370 lines
		
	
	
		
			11 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;
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  *  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();
 | |
| }
 | |
| 
 | |
| 
 | |
| 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);
 | |
| }
 | |
| 
 | |
| 
 | |
| 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) {
 | |
|        if (err)
 | |
|        {
 | |
|            console.log(err);
 | |
|            return;
 | |
|        }
 | |
|        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.PointerMotionHint|x11.eventMask.ButtonPress|x11.eventMask.ButtonRelease|x11.eventMask.StructureNotify|x11.eventMask.Exposure;
 | |
| var eventmask = x11.eventMask.PointerMotion;
 | |
| //var eventmask = x11.eventMask.PointerMotion|x11.eventMask.ButtonPress|x11.eventMask.ButtonRelease|x11.eventMask.StructureNotify|x11.eventMask.Exposure;
 | |
| var exec = require('child_process').exec;
 | |
| 
 | |
| function findBestVisual(display, done) {
 | |
|     exec('glxinfo -i -b', function(error, stdout, stderr) {
 | |
|         console.log(stdout);
 | |
|         if (error)
 | |
|             return done(error);
 | |
|         done(null, parseInt(stdout)+1);
 | |
|         //done(null, 0xb1);
 | |
|     })
 | |
| }
 | |
| 
 | |
| 
 | |
| x11.createClient(function(error, display) {
 | |
|     var X = display.client;
 | |
|     var root = display.screen[0].root;
 | |
|     var width = 500;
 | |
|     var height = 500;
 | |
|     X.require('glx', function(err, GLX) {
 | |
|         var depth = 24;
 | |
|         findBestVisual(display, function(err, visual) {
 | |
| 
 | |
|         /*
 | |
|         var visual = 147;
 | |
|         var rgbaVisuals = Object.keys(display.screen[0].depths[depth]);
 | |
|         for (v in rgbaVisuals)
 | |
|         {
 | |
|            var vid = rgbaVisuals[v];
 | |
|            var visualClass = display.screen[0].depths[depth][vid].class;
 | |
|            if (visualClass == 4 || visualClass == 5)
 | |
|            {
 | |
|               visual = vid;
 | |
|               break;
 | |
|            }
 | |
|         }
 | |
|         */
 | |
| 
 | |
|         var cmid = X.AllocID();
 | |
|         X.CreateColormap(cmid, root, visual, 0);
 | |
|         var win = X.AllocID();
 | |
|         console.log(eventmask);
 | |
|         X.CreateWindow(win, root, 0, 0, width, height, 0, depth, 0, visual, { eventMask: eventmask, colormap: cmid, backgroundPixel: 0, borderPixel: 0 });
 | |
|         X.MapWindow(win);
 | |
| 
 | |
|         var ctx = X.AllocID();
 | |
|         GLX.CreateContext(ctx, visual, 0, 0, 0);
 | |
|         GLX.MakeCurrent(win, ctx, 0, function() {});
 | |
|         var gl = GLX.renderPipeline(ctx);
 | |
| 
 | |
|         var initialized = false;
 | |
|         init(gl, function() {
 | |
|           initialized = true;
 | |
|           setInterval(function() {
 | |
|               angle += 2;
 | |
|               reshape(gl, width, height);
 | |
|               draw(gl);
 | |
|               gl.SwapBuffers(win);
 | |
|           }, 50);
 | |
|         });
 | |
| 
 | |
|         X.on('event', function(ev) {
 | |
|            console.log(ev);
 | |
|            switch(ev.type) {
 | |
|            case 22:
 | |
|               reshape(gl, ev.width, ev.height);
 | |
|               width = ev.width;
 | |
|               height = ev.height;
 | |
|               break;
 | |
|            case 6:
 | |
|               X.QueryPointer(win, function(err, pointer) {
 | |
|                 view_rotx = pointer.childX;
 | |
|                 view_roty = pointer.childY;
 | |
|                 reshape(gl, width, height);
 | |
|                 if (initialized)
 | |
|                   draw(gl);
 | |
|                 gl.SwapBuffers(win);
 | |
|               });
 | |
|               return;
 | |
|            }
 | |
|            reshape(gl, width, height);
 | |
|            if (initialized)
 | |
|               draw(gl);
 | |
|            gl.SwapBuffers(win);
 | |
|         });
 | |
| 
 | |
|  }); // findBestVisual
 | |
| 
 | |
|     });
 | |
|     X.on('error', function(err) { console.log(err); });
 | |
| });
 | |
| ;
 |