/**************************************************************\ ** ** ** Translating your old C / OpenGL 1.x demo to js ** ** ** ** Fabrice NEYRET septembre 2015 ** ** ** \**************************************************************/ I wrote wOpenGL1.js lib in the purpose of easing port of OpenGL 1.x to webGL. I explain here is what is left to be done by you: - for embeding your appli into html - for translating basic C to js Note that wOpenGL1 is NOT implementing everything. It's more a width-first basic implementation of every gl/glu/glut features I needed for my old demos. You might have to adapt it if you want more complex features (like multiple lights textures or display-lists, complex fonts, modes, material tuning). === 1: Embeding ================================================ Here is the embeding pattern of your old C program into html:
----------------------------------------------------------------------- === 2: Adapting GL to wbOpenGL1 & webGL ================================ . In js/webGL all functions, variables and flags are in objects: glKeyword, gluKeyword, glutKeyword -> gl.keyword, glu.keyword, glut.keyword (note the change in caps) GL_KEYWORD, GLUT_KEYWORD -> gl.KEYWORD, glut.KEYWORD Note: gl.TRUE and gl.FALSE were not defined (to be replaced by true and false), so that gl.TRUE = false , which is ultra-nasty ! We redefined these, but take care in pure webGL programs. . glut.createWindow("window name") -> ("glut_canvas"); Notes: - We map on the full navigator window. So no programmable resize/move/subwindows. - All initialisations are done at this moment, up to the definition of printf :-) . Our glutMainLoop returns (it should'nt be a problem). . Textures : people often abused when knowing Ids were GLints. In webGL all IDs are now objects ( this is also true compared to OpenGL 2, despite functions and flags are very much identical). -> - For texture binding, do use genTextures() - In texImage, 3 -> gl.RGB Note: - We implemented only 1 texture at a time, no 2-sides distinction, and limited color/texture interaction. - But we reintroduced 1D textures and texGen. - We reset gl.texImage2D to OpenGL behavior, but we renamed webGL native one as gl.texDOMImage2D since it conveniently accept image objects as parameter. Note that webGL images are reversed: use gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); . A key difference between webGL and OpenGL is that all drawings are finaly blended to the html canvas. Since it is often white, all final pixels with non-1 alpha will have altered colors ! Our swapBuffer do reset alpha to 1, but it's good practice to now put alpha to 1 in clearColor() and fogColor(), and take care of Zbuffer/blending interactions. . Also, antialiasing is always on, which corrupts emulation of indexed color. -> for picking (select buffer) avoid very thin primitives, and set pointSize. . Display-lists were based on a totally different hardware and API philosophy than modern buffers-based philosophy. We emulate them the best we can with stacks of VBOs and attribute contexts, but don't expect all states to be dynamically modified, or possibly strange behaviors (e.g. if FLAT or Wire mode was on when building the display-list). . Keyboard events are somewhat different and OS-dependent. In particular keyup/down consider the physical key, not the character meant ! We call your callback with caps + uncaps version, but it does not solve all (and none of the ctrl/alt modifiers). But the base key func works correctly. Verify also how specialKeys are recognised, especially in base key func. === 3: Translating C to JS ============================================ Note that the spirit here is to minimise the translation effort, not to deeply rewrite in the nice spirit of JS or object oriented way. Note also that I'm a beginner in JS, so better solutions might sometime exists ! . Includes : Most often no longer needed. - system includes -> DELETE - custom includes -> require(myinclude.js) (note that require.js is not native) Attention: the URL current path or data files is not the one of includes. . Type declarations: JS has (mostly) no types ! - Variable declarations: int, float, double, char, GLfloat, void*, etc -> var - Variables in function prototypes: int, float, double, char, GLfloat, void*, etc -> DELETE Note: - Multiple declarations with different prototypes will no longer work. Merge them. (defining default values, type-checking, parsing arguments is easy in JS). - Function declaration: void, or anything -> function() Note that there is no longer main(), so our wrapper includes a call to main() - Casting traps: No types, no cast ! But since there are no longer ints, don't expect automatic int behaviors, especially for index in arrays. - (int)(x) -> Math.floor(x) - int/int -> Math.floor(int/int) - Others casts -> DELETE - Pointers ( * ** & -> ) : Scalar are passed by values, structs and arrays are passed by reference. Most of the time you just have to delete * ** & and replace -> by . But for returning or modifying a scalar or pointer via function arguments, you'll have to change the API. NULL is now null No longer expect to browse arrays using pointers ( T + offset; p = &(T[i])+... ) -> use indexes the regular way. - Arrays : - type name[N] -> var name=[] - type name[] = {init values} -> var name=[init values] - type name[][] = {init values} -> var name=[[init values],[...]] - For scalar types it is sufficient since write allocation is dynamics. (you can test existence with if(A[i]) - not very robust though, since 0, null, false also match - or (typeof A[i]myVar != 'undefined'). - For complex types see below (here you'll now need allocation via new). - For dynamic multidimentionnal arrays, you'll now have either - to do an initialisation loop - or allocate at first access: if (!A[i]) A[i]=[] - Attention: webGL buffers are typed (Float32Array, UInt8Array...) and there is no automatic cast. -> cast using new Float32Array([].concat.apply([],myFloatBuff)) - Structs and classes: - Single-use structs can be translated into Objects: struct{ type var1; ...; } structvar -> var structvar = { var1:{}, ...} - But it is not efficient (and possibly complicated) if used in quantities. -> define a class, which in JS is a function (= constructor) : function structvar() { this.var1={}; ... } (or var var1={} for private data). For an array of structs, you'll now have either - to do an initialisation loop - or allocate at first access: if (!A[i]) A[i] = new structvar() Attention: structs, like arrays, are references in JS. var s1 = s2 don't duplicate any data. Convertly, re-setting a struct or array variable, if loosing a last handle on allocated data, will allow garbage collector to free its memory. ( no delete in JS. Or indeed there is one doing something else). - Statics These no longer exist in JS. - make it global, or class-variable of a class, - or emulate: static v -> if ( typeof(func.v) == 'undefined' ) func.v=0; - or rely on closure scopes + anonymous function to isolate it in global ( pretty involved, but very JSish :-) ) : -> ( function() { var v=0; this.func = func() {... } }() ) . Macros: No macro preprocessor in JS :-( - Replace macro constants by const = or var =. - Replace macro functions by functions. - Take care of collisions with functions and variables names. - Do no longer count on side effects, excepted if the "define" function is declared within the function where it is used. - Replace macro conditions by if(cond){}, or /* */ if syntax issues. Indeed functions declarations are still recognised in if(0) sections so you'll probably need to comment these away with /* */. . Maths : As an oriented object langage, all functions and constants are now in the object Math. You might redefine them for ease if you wish: -> var sin = Math.sin, abs = math.abs, M_PI = Math.PI Note that - fmod -> % - drand48 -> Math.random - srand48: doesn't exist ! :-( Re-implementations are available online. . C wrapper : - JS no longer expect a main(), but our wrapper call main(argc, argv) (your's to set args) - There is of course no longer exit() function in a web page: it's your's to choose a new behavior. - Printf / sprintf no longer exist in a web page (besides console.log("...") on the js console). - For your convenience, we implemented (limited) ones, printf displaying in an optional and switchable overlay window. - Multiline strings: either use "...\n"+ or ` ... [br] ...` - Note that simple sprintf can also be rewriten with multitype + , and you don't need to allocate the buffer: var s = "value = "+sin(x) Enjoy ! =============================================================================