| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright (c) 2000-2022 Inria | ||
| 3 | * All rights reserved. | ||
| 4 | * | ||
| 5 | * Redistribution and use in source and binary forms, with or without | ||
| 6 | * modification, are permitted provided that the following conditions are met: | ||
| 7 | * | ||
| 8 | * * Redistributions of source code must retain the above copyright notice, | ||
| 9 | * this list of conditions and the following disclaimer. | ||
| 10 | * * Redistributions in binary form must reproduce the above copyright notice, | ||
| 11 | * this list of conditions and the following disclaimer in the documentation | ||
| 12 | * and/or other materials provided with the distribution. | ||
| 13 | * * Neither the name of the ALICE Project-Team nor the names of its | ||
| 14 | * contributors may be used to endorse or promote products derived from this | ||
| 15 | * software without specific prior written permission. | ||
| 16 | * | ||
| 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
| 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 27 | * POSSIBILITY OF SUCH DAMAGE. | ||
| 28 | * | ||
| 29 | * Contact: Bruno Levy | ||
| 30 | * | ||
| 31 | * https://www.inria.fr/fr/bruno-levy | ||
| 32 | * | ||
| 33 | * Inria, | ||
| 34 | * Domaine de Voluceau, | ||
| 35 | * 78150 Le Chesnay - Rocquencourt | ||
| 36 | * FRANCE | ||
| 37 | * | ||
| 38 | */ | ||
| 39 | |||
| 40 | #include <geogram_gfx/lua/lua_glup.h> | ||
| 41 | #include <geogram_gfx/GLUP/GLUP.h> | ||
| 42 | #include <geogram/basic/geometry.h> | ||
| 43 | #include <geogram/lua/lua_wrap.h> | ||
| 44 | |||
| 45 | #include <map> | ||
| 46 | #include <string> | ||
| 47 | |||
| 48 | |||
| 49 | namespace { | ||
| 50 | using namespace GEO; | ||
| 51 | |||
| 52 | namespace LUAGLUPImpl { | ||
| 53 | |||
| 54 | /** | ||
| 55 | * \brief Gets a string that represents the name of a GLUPmatrix. | ||
| 56 | * \param[in] L a pointer to the LUA state | ||
| 57 | * \param[in] m one of GLUP_MODELVIEW_MATRIX, GLUP_PROJECTION_MATRIX, | ||
| 58 | * GLUP_TEXTURE_MATRIX | ||
| 59 | * \return one of "modelview", "projection", "texture" | ||
| 60 | */ | ||
| 61 | ✗ | static const char* luaglup_matrixname( | |
| 62 | lua_State* L, GLUPmatrix m | ||
| 63 | ) { | ||
| 64 | ✗ | geo_argused(L); | |
| 65 | ✗ | const char* result = nullptr; | |
| 66 | ✗ | switch(m) { | |
| 67 | ✗ | case GLUP_MODELVIEW_MATRIX: | |
| 68 | ✗ | result = "modelview"; | |
| 69 | ✗ | break; | |
| 70 | ✗ | case GLUP_PROJECTION_MATRIX: | |
| 71 | ✗ | result = "projection"; | |
| 72 | ✗ | break; | |
| 73 | ✗ | case GLUP_TEXTURE_MATRIX: | |
| 74 | ✗ | result = "texture"; | |
| 75 | ✗ | break; | |
| 76 | } | ||
| 77 | ✗ | return result; | |
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * \brief Tentatively calls glupPushMatrix(). If a stack overflow | ||
| 82 | * is detected, the function does nothing and returns false. | ||
| 83 | * \details The function keeps track of the current matrix depth | ||
| 84 | * using variables stored in the LUA registry. | ||
| 85 | * \param[in] L a pointer to the LUA state | ||
| 86 | * \retval true if glupPushMatrix() could be successfully called. | ||
| 87 | * \retval false otherwise | ||
| 88 | */ | ||
| 89 | ✗ | static bool luaglup_trypushmatrix(lua_State* L) { | |
| 90 | ✗ | const index_t luaglup_max_matrix_depth = 13; | |
| 91 | ✗ | GLUPmatrix m = glupGetMatrixMode(); | |
| 92 | ✗ | const char* matrix_name = luaglup_matrixname(L,m); | |
| 93 | ✗ | lua_getfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 94 | ✗ | lua_getfield(L, -1, matrix_name); | |
| 95 | ✗ | index_t depth = index_t(lua_tointeger(L, -1)); | |
| 96 | ✗ | if(depth >= luaglup_max_matrix_depth) { | |
| 97 | ✗ | lua_pop(L,2); | |
| 98 | ✗ | return false; | |
| 99 | } | ||
| 100 | ✗ | lua_pop(L,1); | |
| 101 | ✗ | lua_pushinteger(L,lua_Integer(depth+1)); | |
| 102 | ✗ | lua_setfield(L, -2, matrix_name); | |
| 103 | ✗ | lua_pop(L,1); | |
| 104 | ✗ | glupPushMatrix(); | |
| 105 | ✗ | return true; | |
| 106 | } | ||
| 107 | |||
| 108 | /** | ||
| 109 | * \brief Tentatively calls glupPopMatrix(). If a stack underflow | ||
| 110 | * is detected, the function does nothing and returns false. | ||
| 111 | * \details The function keeps track of the current matrix depth | ||
| 112 | * using variables stored in the LUA registry. | ||
| 113 | * \param[in] L a pointer to the LUA state | ||
| 114 | * \retval true if glupPopMatrix() could be successfully called. | ||
| 115 | * \retval false otherwise | ||
| 116 | */ | ||
| 117 | ✗ | static bool luaglup_trypopmatrix(lua_State* L) { | |
| 118 | ✗ | GLUPmatrix m = glupGetMatrixMode(); | |
| 119 | ✗ | const char* matrix_name = luaglup_matrixname(L,m); | |
| 120 | ✗ | lua_getfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 121 | ✗ | lua_getfield(L, -1, matrix_name); | |
| 122 | ✗ | index_t depth = index_t(lua_tointeger(L,-1)); | |
| 123 | ✗ | if(depth == 0) { | |
| 124 | ✗ | lua_pop(L,2); | |
| 125 | ✗ | return false; | |
| 126 | } | ||
| 127 | ✗ | lua_pop(L,1); | |
| 128 | ✗ | lua_pushinteger(L,lua_Integer(depth-1)); | |
| 129 | ✗ | lua_setfield(L, -2, matrix_name); | |
| 130 | ✗ | lua_pop(L,1); | |
| 131 | ✗ | glupPopMatrix(); | |
| 132 | ✗ | return true; | |
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * \brief Pops matrices from the specified GLUP matrix stack | ||
| 137 | * until there is no more matrix on the stack. | ||
| 138 | * \details The function keeps track of the current matrix depth | ||
| 139 | * using variables stored in the LUA registry. | ||
| 140 | * \param[in] L a pointer to the LUA state | ||
| 141 | * \param[in] m one of GLUP_MODELVIEW_MATRIX, GLUP_PROJECTION_MATRIX, | ||
| 142 | * GLUP_TEXTURE_MATRIX | ||
| 143 | */ | ||
| 144 | ✗ | static void luaglup_adjustmatrixstack(lua_State* L, GLUPmatrix m) { | |
| 145 | ✗ | const char* matrix_name = luaglup_matrixname(L,m); | |
| 146 | ✗ | lua_getfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 147 | ✗ | lua_getfield(L, -1, matrix_name); | |
| 148 | ✗ | index_t depth = index_t(lua_tointeger(L,-1)); | |
| 149 | ✗ | lua_pop(L,1); | |
| 150 | ✗ | if(depth != 0) { | |
| 151 | ✗ | GLUPmatrix mode_save = glupGetMatrixMode(); | |
| 152 | ✗ | glupMatrixMode(m); | |
| 153 | ✗ | while(depth != 0) { | |
| 154 | ✗ | glupPopMatrix(); | |
| 155 | ✗ | --depth; | |
| 156 | } | ||
| 157 | ✗ | lua_pushinteger(L,lua_Integer(depth)); | |
| 158 | ✗ | lua_setfield(L,-2,matrix_name); | |
| 159 | ✗ | glupMatrixMode(mode_save); | |
| 160 | } | ||
| 161 | ✗ | lua_pop(L,1); | |
| 162 | ✗ | } | |
| 163 | |||
| 164 | /** | ||
| 165 | * \brief Tests whether the current GLUP state is | ||
| 166 | * between a glupBegin()/glupEnd() pair. | ||
| 167 | * \details The function keeps track of the current | ||
| 168 | * state using a variable stored in the LUA registry. | ||
| 169 | * \param[in] L a pointer to the LUA state. | ||
| 170 | * \retval true if glupBegin() was called (and glupEnd() | ||
| 171 | * was not called yet). | ||
| 172 | * \retval false otherwise. | ||
| 173 | */ | ||
| 174 | ✗ | static bool luaglup_primitiveactive(lua_State* L) { | |
| 175 | ✗ | lua_getfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 176 | ✗ | lua_getfield(L, -1, "primitive_active"); | |
| 177 | ✗ | bool result = (lua_toboolean(L,-1) != 0); | |
| 178 | ✗ | lua_pop(L,2); | |
| 179 | ✗ | return result; | |
| 180 | } | ||
| 181 | |||
| 182 | /** | ||
| 183 | * \brief Specifies to LUA that glupBegin() was called or | ||
| 184 | * that glupEnd() was called. | ||
| 185 | * \details The function keeps track of the current | ||
| 186 | * state using a variable stored in the LUA registry. | ||
| 187 | * \param[in] L a pointer to the LUA state. | ||
| 188 | * \param[in] x true if glupBegin() was called (set the primitive_active | ||
| 189 | * flag), false if glupEnd() was called (reset the primitive_active | ||
| 190 | * flag). | ||
| 191 | */ | ||
| 192 | ✗ | static void luaglup_setprimitiveactive(lua_State* L, bool x) { | |
| 193 | ✗ | lua_getfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 194 | ✗ | lua_pushboolean(L, x ? 1 : 0); | |
| 195 | ✗ | lua_setfield(L, -2, "primitive_active"); | |
| 196 | ✗ | lua_pop(L,1); | |
| 197 | ✗ | } | |
| 198 | |||
| 199 | |||
| 200 | #define DECLARE_GLUP_CONSTANT(C) \ | ||
| 201 | lua_pushliteral(L,#C); \ | ||
| 202 | lua_pushinteger(L,GLUP_##C); \ | ||
| 203 | lua_settable(L,1) | ||
| 204 | |||
| 205 | // Idem: this one could be stored in the registry, using | ||
| 206 | // a LUA table. | ||
| 207 | static std::map<std::string, GEO::vec4> lua_glup_colormap; | ||
| 208 | |||
| 209 | ✗ | static void DECLARE_GLUP_COLOR( | |
| 210 | const char* name, double r, double g, double b, double a=1.0 | ||
| 211 | ) { | ||
| 212 | ✗ | lua_glup_colormap[name] = GEO::vec4(r,g,b,a); | |
| 213 | ✗ | } | |
| 214 | |||
| 215 | ✗ | inline bool get_vec4(lua_State* L, double* xyzw, int pos=1) { | |
| 216 | ✗ | int nargs = lua_gettop(L); | |
| 217 | ✗ | xyzw[0] = 0.0; | |
| 218 | ✗ | xyzw[1] = 0.0; | |
| 219 | ✗ | xyzw[2] = 0.0; | |
| 220 | ✗ | xyzw[3] = 1.0; | |
| 221 | |||
| 222 | ✗ | if(nargs == pos && lua_isstring(L,pos)) { | |
| 223 | ✗ | const char* name = lua_tostring(L,pos); | |
| 224 | ✗ | auto it = lua_glup_colormap.find(name); | |
| 225 | ✗ | if(it == lua_glup_colormap.end()) { | |
| 226 | ✗ | return false; | |
| 227 | } | ||
| 228 | ✗ | xyzw[0] = it->second.x; | |
| 229 | ✗ | xyzw[1] = it->second.y; | |
| 230 | ✗ | xyzw[2] = it->second.z; | |
| 231 | ✗ | xyzw[3] = it->second.w; | |
| 232 | } else { | ||
| 233 | ✗ | if(nargs > pos+3 || nargs < pos) { | |
| 234 | ✗ | return false; | |
| 235 | } | ||
| 236 | ✗ | if(nargs == pos+3) { | |
| 237 | ✗ | if(!lua_isnumber(L,pos+3)) { | |
| 238 | ✗ | return false; | |
| 239 | } | ||
| 240 | ✗ | xyzw[3] = lua_tonumber(L,pos+3); | |
| 241 | } | ||
| 242 | ✗ | if(nargs >= pos+2) { | |
| 243 | ✗ | if(!lua_isnumber(L,pos+2)) { | |
| 244 | ✗ | return false; | |
| 245 | } | ||
| 246 | ✗ | xyzw[2] = lua_tonumber(L,pos+2); | |
| 247 | } | ||
| 248 | ✗ | if(nargs >= pos+1) { | |
| 249 | ✗ | if(!lua_isnumber(L,pos+1)) { | |
| 250 | ✗ | return false; | |
| 251 | } | ||
| 252 | ✗ | xyzw[1] = lua_tonumber(L,pos+1); | |
| 253 | } | ||
| 254 | ✗ | if(nargs >= pos) { | |
| 255 | ✗ | if(!lua_isnumber(L,pos)) { | |
| 256 | ✗ | return false; | |
| 257 | } | ||
| 258 | ✗ | xyzw[0] = lua_tonumber(L,pos); | |
| 259 | } | ||
| 260 | } | ||
| 261 | ✗ | return true; | |
| 262 | } | ||
| 263 | |||
| 264 | ✗ | static int SetColor(lua_State* L) { | |
| 265 | ✗ | if(lua_gettop(L) < 2) { | |
| 266 | ✗ | return luaL_error( | |
| 267 | L, "'GLUP.SetColor()' invalid number of arguments" | ||
| 268 | ✗ | ); | |
| 269 | } | ||
| 270 | ✗ | if(!lua_isinteger(L,1)) { | |
| 271 | ✗ | return luaL_error( | |
| 272 | L, "'GLUP.SetColor()' argument should be an integer" | ||
| 273 | ✗ | ); | |
| 274 | } | ||
| 275 | ✗ | lua_Integer color = lua_tointeger(L,1); | |
| 276 | double rgba[4]; | ||
| 277 | ✗ | if(!get_vec4(L,rgba,2)) { | |
| 278 | ✗ | return luaL_error( | |
| 279 | L, "'GLUP.SetColor()' invalid arguments" | ||
| 280 | ✗ | ); | |
| 281 | } | ||
| 282 | ✗ | glupSetColor4dv(GLUPcolor(color),rgba); | |
| 283 | ✗ | return 0; | |
| 284 | } | ||
| 285 | |||
| 286 | ✗ | static int GetColor(lua_State* L) { | |
| 287 | ✗ | if(lua_gettop(L) != 1) { | |
| 288 | ✗ | return luaL_error( | |
| 289 | L, "'GLUP.GetColor()' invalid number of arguments" | ||
| 290 | ✗ | ); | |
| 291 | } | ||
| 292 | ✗ | if(!lua_isinteger(L,1)) { | |
| 293 | ✗ | return luaL_error( | |
| 294 | L, "'GLUP.GetColor()' argument should be an integer" | ||
| 295 | ✗ | ); | |
| 296 | } | ||
| 297 | ✗ | lua_Integer color = lua_tointeger(L,1); | |
| 298 | float rgba[4]; | ||
| 299 | ✗ | glupGetColor4fv(GLUPcolor(color),rgba); | |
| 300 | ✗ | lua_pushnumber(L,lua_Number(rgba[0])); | |
| 301 | ✗ | lua_pushnumber(L,lua_Number(rgba[1])); | |
| 302 | ✗ | lua_pushnumber(L,lua_Number(rgba[2])); | |
| 303 | ✗ | lua_pushnumber(L,lua_Number(rgba[3])); | |
| 304 | ✗ | return 4; | |
| 305 | } | ||
| 306 | |||
| 307 | ✗ | static int ClipPlane(lua_State* L) { | |
| 308 | ✗ | if(lua_gettop(L) != 4) { | |
| 309 | ✗ | return luaL_error( | |
| 310 | L, "'GLUP.ClipPlane()' invalid number of arguments" | ||
| 311 | ✗ | ); | |
| 312 | } | ||
| 313 | ✗ | if( | |
| 314 | ✗ | !lua_isnumber(L,1) || | |
| 315 | ✗ | !lua_isnumber(L,2) || | |
| 316 | ✗ | !lua_isnumber(L,3) || | |
| 317 | ✗ | !lua_isnumber(L,4) | |
| 318 | ) { | ||
| 319 | ✗ | return luaL_error( | |
| 320 | L, "'GLUP.ClipPlane()' invalid arguments" | ||
| 321 | ✗ | ); | |
| 322 | } | ||
| 323 | double eqn[4]; | ||
| 324 | ✗ | eqn[0] = lua_tonumber(L,1); | |
| 325 | ✗ | eqn[1] = lua_tonumber(L,2); | |
| 326 | ✗ | eqn[2] = lua_tonumber(L,3); | |
| 327 | ✗ | eqn[3] = lua_tonumber(L,4); | |
| 328 | ✗ | glupClipPlane(eqn); | |
| 329 | ✗ | return 0; | |
| 330 | } | ||
| 331 | |||
| 332 | ✗ | static int GetClipPlane(lua_State* L) { | |
| 333 | ✗ | if(lua_gettop(L) != 0) { | |
| 334 | ✗ | return luaL_error( | |
| 335 | L, "'GLUP.GetClipPlane()' invalid number of arguments" | ||
| 336 | ✗ | ); | |
| 337 | } | ||
| 338 | double eqn[4]; | ||
| 339 | ✗ | glupGetClipPlane(eqn); | |
| 340 | ✗ | lua_pushnumber(L,eqn[0]); | |
| 341 | ✗ | lua_pushnumber(L,eqn[1]); | |
| 342 | ✗ | lua_pushnumber(L,eqn[2]); | |
| 343 | ✗ | lua_pushnumber(L,eqn[3]); | |
| 344 | ✗ | return 4; | |
| 345 | } | ||
| 346 | |||
| 347 | ✗ | static int PushMatrix(lua_State* L) { | |
| 348 | ✗ | if(lua_gettop(L) != 0) { | |
| 349 | ✗ | return luaL_error( | |
| 350 | L, "'GLUP.PushMatrix()' invalid number of arguments" | ||
| 351 | ✗ | ); | |
| 352 | } | ||
| 353 | ✗ | if(!luaglup_trypushmatrix(L)) { | |
| 354 | ✗ | GLUPmatrix m = glupGetMatrixMode(); | |
| 355 | ✗ | const char* matrix_name = luaglup_matrixname(L,m); | |
| 356 | ✗ | return luaL_error( | |
| 357 | ✗ | L, (std::string("'GLUP.PushMatrix()' ") + | |
| 358 | ✗ | matrix_name + ":stack overflow").c_str() | |
| 359 | ✗ | ); | |
| 360 | } | ||
| 361 | ✗ | return 0; | |
| 362 | } | ||
| 363 | |||
| 364 | ✗ | static int PopMatrix(lua_State* L) { | |
| 365 | ✗ | if(lua_gettop(L) != 0) { | |
| 366 | ✗ | return luaL_error( | |
| 367 | L, "'GLUP.PopMatrix()' invalid number of arguments" | ||
| 368 | ✗ | ); | |
| 369 | } | ||
| 370 | ✗ | if(!luaglup_trypopmatrix(L)) { | |
| 371 | ✗ | GLUPmatrix m = glupGetMatrixMode(); | |
| 372 | ✗ | const char* matrix_name = luaglup_matrixname(L,m); | |
| 373 | ✗ | return luaL_error( | |
| 374 | ✗ | L, (std::string("'GLUP.PopMatrix()' ") + | |
| 375 | ✗ | matrix_name + ":stack underflow").c_str() | |
| 376 | ✗ | ); | |
| 377 | } | ||
| 378 | ✗ | return 0; | |
| 379 | } | ||
| 380 | |||
| 381 | ✗ | static int GetMatrix(lua_State* L) { | |
| 382 | ✗ | if(lua_gettop(L) != 1) { | |
| 383 | ✗ | return luaL_error( | |
| 384 | L, "'GLUP.GetMatrix()' invalid number of arguments" | ||
| 385 | ✗ | ); | |
| 386 | } | ||
| 387 | ✗ | if(!lua_isinteger(L,1)) { | |
| 388 | ✗ | return luaL_error( | |
| 389 | L, "'GLUP.GetMatrix()' invalid argument" | ||
| 390 | ✗ | ); | |
| 391 | } | ||
| 392 | double M[16]; | ||
| 393 | ✗ | glupGetMatrixdv(GLUPmatrix(lua_tointeger(L,1)),M); | |
| 394 | ✗ | for(int i=0; i<16; ++i) { | |
| 395 | ✗ | lua_pushnumber(L,M[i]); | |
| 396 | } | ||
| 397 | ✗ | return 16; | |
| 398 | } | ||
| 399 | |||
| 400 | |||
| 401 | ✗ | static int LoadMatrix(lua_State* L) { | |
| 402 | ✗ | if(lua_gettop(L) != 16) { | |
| 403 | ✗ | return luaL_error( | |
| 404 | L, "'GLUP.LoadMatrix()' invalid number of arguments" | ||
| 405 | ✗ | ); | |
| 406 | } | ||
| 407 | double M[16]; | ||
| 408 | ✗ | for(int i=0; i<16; ++i) { | |
| 409 | ✗ | if(!lua_isnumber(L,i+1)) { | |
| 410 | ✗ | return luaL_error( | |
| 411 | L, "'GLUP.LoadMatrix()' invalid argument" | ||
| 412 | ✗ | ); | |
| 413 | } | ||
| 414 | ✗ | M[i] = lua_tonumber(L,i+1); | |
| 415 | } | ||
| 416 | ✗ | glupLoadMatrixd(M); | |
| 417 | ✗ | return 0; | |
| 418 | } | ||
| 419 | |||
| 420 | ✗ | static int MultMatrix(lua_State* L) { | |
| 421 | ✗ | if(lua_gettop(L) != 16) { | |
| 422 | ✗ | return luaL_error( | |
| 423 | L, "'GLUP.MultMatrix()' invalid number of arguments" | ||
| 424 | ✗ | ); | |
| 425 | } | ||
| 426 | double M[16]; | ||
| 427 | ✗ | for(int i=0; i<16; ++i) { | |
| 428 | ✗ | if(!lua_isnumber(L,i+1)) { | |
| 429 | ✗ | return luaL_error( | |
| 430 | L, "'GLUP.MultMatrix()' invalid argument" | ||
| 431 | ✗ | ); | |
| 432 | } | ||
| 433 | ✗ | M[i] = lua_tonumber(L,i+1); | |
| 434 | } | ||
| 435 | ✗ | glupMultMatrixd(M); | |
| 436 | ✗ | return 0; | |
| 437 | } | ||
| 438 | |||
| 439 | ✗ | static int Begin(lua_State* L) { | |
| 440 | ✗ | if(lua_gettop(L) != 1) { | |
| 441 | ✗ | return luaL_error( | |
| 442 | L, "'GLUP.Begin()' invalid number of arguments" | ||
| 443 | ✗ | ); | |
| 444 | } | ||
| 445 | ✗ | if(!lua_isinteger(L,1)) { | |
| 446 | ✗ | return luaL_error( | |
| 447 | L, "'GLUP.Begin()' argument should be an integer" | ||
| 448 | ✗ | ); | |
| 449 | } | ||
| 450 | ✗ | if(luaglup_primitiveactive(L)) { | |
| 451 | ✗ | return luaL_error( | |
| 452 | L, "'GLUP.Begin()' called twice without GLUP.End()" | ||
| 453 | ✗ | ); | |
| 454 | } | ||
| 455 | ✗ | luaglup_setprimitiveactive(L,true); | |
| 456 | ✗ | lua_Integer prim = lua_tointeger(L,1); | |
| 457 | ✗ | glupBegin(GLUPprimitive(prim)); | |
| 458 | ✗ | return 0; | |
| 459 | } | ||
| 460 | |||
| 461 | ✗ | static int End(lua_State* L) { | |
| 462 | ✗ | if(lua_gettop(L) != 0) { | |
| 463 | ✗ | return luaL_error( | |
| 464 | L, "'GLUP.End()' invalid number of arguments" | ||
| 465 | ✗ | ); | |
| 466 | } | ||
| 467 | ✗ | if(!luaglup_primitiveactive(L)) { | |
| 468 | ✗ | return luaL_error( | |
| 469 | L, "'GLUP.End()' called without GLUP.Begin()" | ||
| 470 | ✗ | ); | |
| 471 | } | ||
| 472 | ✗ | luaglup_setprimitiveactive(L,false); | |
| 473 | ✗ | glupEnd(); | |
| 474 | ✗ | return 0; | |
| 475 | } | ||
| 476 | |||
| 477 | ✗ | static int Vertex(lua_State* L) { | |
| 478 | double xyzw[4]; | ||
| 479 | ✗ | if(!get_vec4(L,xyzw)) { | |
| 480 | ✗ | return luaL_error( | |
| 481 | L, "'GLUP.Vertex()' invalid arguments" | ||
| 482 | ✗ | ); | |
| 483 | } | ||
| 484 | ✗ | glupVertex4dv(xyzw); | |
| 485 | ✗ | return 0; | |
| 486 | } | ||
| 487 | |||
| 488 | ✗ | static int Color(lua_State* L) { | |
| 489 | double rgba[4]; | ||
| 490 | ✗ | if(!get_vec4(L,rgba)) { | |
| 491 | ✗ | return luaL_error( | |
| 492 | L, "'GLUP.Color()' invalid arguments" | ||
| 493 | ✗ | ); | |
| 494 | } | ||
| 495 | ✗ | glupColor4dv(rgba); | |
| 496 | ✗ | return 0; | |
| 497 | } | ||
| 498 | |||
| 499 | ✗ | static int TexCoord(lua_State* L) { | |
| 500 | double xyzw[4]; | ||
| 501 | ✗ | if(!get_vec4(L,xyzw)) { | |
| 502 | ✗ | return luaL_error( | |
| 503 | L, "'GLUP.TexCoord()' invalid arguments" | ||
| 504 | ✗ | ); | |
| 505 | } | ||
| 506 | ✗ | glupTexCoord4dv(xyzw); | |
| 507 | ✗ | return 0; | |
| 508 | } | ||
| 509 | |||
| 510 | ✗ | static int Normal(lua_State* L) { | |
| 511 | double xyzw[4]; | ||
| 512 | ✗ | if(!get_vec4(L,xyzw)) { | |
| 513 | ✗ | return luaL_error( | |
| 514 | L, "'GLUP.Normal()' invalid arguments" | ||
| 515 | ✗ | ); | |
| 516 | } | ||
| 517 | ✗ | glupNormal3dv(xyzw); | |
| 518 | ✗ | return 0; | |
| 519 | } | ||
| 520 | } | ||
| 521 | } | ||
| 522 | |||
| 523 | /** | ||
| 524 | * \brief Directly registers an automatically generated | ||
| 525 | * LUA wrapper for a GLUP function. | ||
| 526 | * \param[in] F the name of the function without the | ||
| 527 | * "glup" prefix | ||
| 528 | */ | ||
| 529 | #define DECLARE_GLUP_FUNC(F) \ | ||
| 530 | GEO::lua_bindwrapperwithname(L,glup##F,#F) | ||
| 531 | |||
| 532 | /** | ||
| 533 | * \brief Registers an automatically generated LUA wrapper | ||
| 534 | * for a GLUP function and change its name declared to LUA. | ||
| 535 | * \param[in] F the C++ name of the function (with prefix and | ||
| 536 | * namespace) | ||
| 537 | * \param[in] N a string with the name under which the function | ||
| 538 | * will be registered to LUA. | ||
| 539 | */ | ||
| 540 | #define DECLARE_GLUP_FUNC_WITH_NAME(F,N) \ | ||
| 541 | GEO::lua_bindwrapperwithname(L,F,N) | ||
| 542 | |||
| 543 | /** | ||
| 544 | * \brief Registers a specifically written function or LUA adapter | ||
| 545 | * to LUA. The generated name will be the name of the adapter with | ||
| 546 | * namespaces removed. | ||
| 547 | * \param[in] F the C++ name of the function (with namespace). | ||
| 548 | */ | ||
| 549 | #define DECLARE_GLUP_ADAPTER(F) \ | ||
| 550 | GEO::lua_bindwrapper(L,F) | ||
| 551 | |||
| 552 | // All used enum types need to be declared, | ||
| 553 | // this creates some specializations of the | ||
| 554 | // templates that communicate with the LUA | ||
| 555 | // stack. | ||
| 556 | // TODO: select the right functions using std::is_enum<> | ||
| 557 | namespace GEO { | ||
| 558 | ✗ | LUA_DECLAREENUMTYPE(GLUPtoggle); | |
| 559 | LUA_DECLAREENUMTYPE(GLUPtextureType); | ||
| 560 | LUA_DECLAREENUMTYPE(GLUPtextureMode); | ||
| 561 | ✗ | LUA_DECLAREENUMTYPE(GLUPpickingMode); | |
| 562 | ✗ | LUA_DECLAREENUMTYPE(GLUPclipMode); | |
| 563 | ✗ | LUA_DECLAREENUMTYPE(GLUPmatrix); | |
| 564 | } | ||
| 565 | |||
| 566 | ✗ | void init_lua_glup(lua_State* L) { | |
| 567 | using namespace LUAGLUPImpl; | ||
| 568 | using namespace GEO; | ||
| 569 | |||
| 570 | // Create the table used to store the matrix stack depths | ||
| 571 | // and begin/end status (both are used to recover from | ||
| 572 | // client-code errors). | ||
| 573 | ✗ | lua_newtable(L); | |
| 574 | ✗ | lua_setfield(L,LUA_REGISTRYINDEX,"GLUP"); | |
| 575 | |||
| 576 | ✗ | lua_newtable(L); | |
| 577 | |||
| 578 | // Enable/Disable constants | ||
| 579 | ✗ | DECLARE_GLUP_CONSTANT(LIGHTING); | |
| 580 | ✗ | DECLARE_GLUP_CONSTANT(VERTEX_COLORS); | |
| 581 | ✗ | DECLARE_GLUP_CONSTANT(DRAW_MESH); | |
| 582 | ✗ | DECLARE_GLUP_CONSTANT(CLIPPING); | |
| 583 | ✗ | DECLARE_GLUP_CONSTANT(INDIRECT_TEXTURING); | |
| 584 | ✗ | DECLARE_GLUP_CONSTANT(VERTEX_NORMALS); | |
| 585 | ✗ | DECLARE_GLUP_CONSTANT(PICKING); | |
| 586 | ✗ | DECLARE_GLUP_CONSTANT(ALPHA_DISCARD); | |
| 587 | |||
| 588 | // Colors | ||
| 589 | ✗ | DECLARE_GLUP_CONSTANT(FRONT_COLOR); | |
| 590 | ✗ | DECLARE_GLUP_CONSTANT(BACK_COLOR); | |
| 591 | ✗ | DECLARE_GLUP_CONSTANT(MESH_COLOR); | |
| 592 | ✗ | DECLARE_GLUP_CONSTANT(FRONT_AND_BACK_COLOR); | |
| 593 | |||
| 594 | // Picking | ||
| 595 | ✗ | DECLARE_GLUP_CONSTANT(PICK_PRIMITIVE); | |
| 596 | ✗ | DECLARE_GLUP_CONSTANT(PICK_CONSTANT); | |
| 597 | |||
| 598 | // Clipping | ||
| 599 | ✗ | DECLARE_GLUP_CONSTANT(CLIP_STANDARD); | |
| 600 | ✗ | DECLARE_GLUP_CONSTANT(CLIP_WHOLE_CELLS); | |
| 601 | ✗ | DECLARE_GLUP_CONSTANT(CLIP_STRADDLING_CELLS); | |
| 602 | ✗ | DECLARE_GLUP_CONSTANT(CLIP_SLICE_CELLS); | |
| 603 | |||
| 604 | // Matrices | ||
| 605 | ✗ | DECLARE_GLUP_CONSTANT(MODELVIEW_MATRIX); | |
| 606 | ✗ | DECLARE_GLUP_CONSTANT(PROJECTION_MATRIX); | |
| 607 | ✗ | DECLARE_GLUP_CONSTANT(TEXTURE_MATRIX); | |
| 608 | |||
| 609 | // Primitives | ||
| 610 | ✗ | DECLARE_GLUP_CONSTANT(POINTS); | |
| 611 | ✗ | DECLARE_GLUP_CONSTANT(LINES); | |
| 612 | ✗ | DECLARE_GLUP_CONSTANT(TRIANGLES); | |
| 613 | ✗ | DECLARE_GLUP_CONSTANT(QUADS); | |
| 614 | ✗ | DECLARE_GLUP_CONSTANT(TETRAHEDRA); | |
| 615 | ✗ | DECLARE_GLUP_CONSTANT(HEXAHEDRA); | |
| 616 | ✗ | DECLARE_GLUP_CONSTANT(PRISMS); | |
| 617 | ✗ | DECLARE_GLUP_CONSTANT(PYRAMIDS); | |
| 618 | ✗ | DECLARE_GLUP_CONSTANT(CONNECTORS); | |
| 619 | ✗ | DECLARE_GLUP_CONSTANT(SPHERES); | |
| 620 | |||
| 621 | // GLUP Functions | ||
| 622 | // There are three cases: | ||
| 623 | // 1) GLUP function is directly "wrappable" | ||
| 624 | // -> DECLARE_GLUP_FUNC | ||
| 625 | // 2) GLUP function is "wrappable" but needs to be renamed | ||
| 626 | // -> DECLARE_GLUP_FUNC_WITH_NAME | ||
| 627 | // 3) GLUP function needs a specific wrapper, written in | ||
| 628 | // the LUAGLUPImpl namespace | ||
| 629 | // -> DECLARE_GLUP_ADAPTER | ||
| 630 | |||
| 631 | ✗ | DECLARE_GLUP_FUNC(Enable); | |
| 632 | ✗ | DECLARE_GLUP_FUNC(Disable); | |
| 633 | ✗ | DECLARE_GLUP_FUNC(IsEnabled); | |
| 634 | ✗ | DECLARE_GLUP_ADAPTER(SetColor); | |
| 635 | ✗ | DECLARE_GLUP_ADAPTER(GetColor); | |
| 636 | ✗ | DECLARE_GLUP_FUNC_WITH_NAME(glupLightVector3f,"LightVector"); | |
| 637 | ✗ | DECLARE_GLUP_FUNC(SetPointSize); | |
| 638 | ✗ | DECLARE_GLUP_FUNC(GetPointSize); | |
| 639 | ✗ | DECLARE_GLUP_FUNC(SetMeshWidth); | |
| 640 | ✗ | DECLARE_GLUP_FUNC(GetMeshWidth); | |
| 641 | ✗ | DECLARE_GLUP_FUNC(SetCellsShrink); | |
| 642 | ✗ | DECLARE_GLUP_FUNC(GetCellsShrink); | |
| 643 | ✗ | DECLARE_GLUP_FUNC(SetAlphaThreshold); | |
| 644 | ✗ | DECLARE_GLUP_FUNC(GetAlphaThreshold); | |
| 645 | ✗ | DECLARE_GLUP_FUNC(PickingMode); | |
| 646 | ✗ | DECLARE_GLUP_FUNC(GetPickingMode); | |
| 647 | ✗ | DECLARE_GLUP_FUNC(PickingId); | |
| 648 | ✗ | DECLARE_GLUP_FUNC(GetPickingId); | |
| 649 | ✗ | DECLARE_GLUP_FUNC(BasePickingId); | |
| 650 | ✗ | DECLARE_GLUP_FUNC(GetBasePickingId); | |
| 651 | ✗ | DECLARE_GLUP_FUNC(ClipMode); | |
| 652 | ✗ | DECLARE_GLUP_FUNC(GetClipMode); | |
| 653 | ✗ | DECLARE_GLUP_ADAPTER(ClipPlane); | |
| 654 | ✗ | DECLARE_GLUP_ADAPTER(GetClipPlane); | |
| 655 | ✗ | DECLARE_GLUP_FUNC(MatrixMode); | |
| 656 | ✗ | DECLARE_GLUP_FUNC(GetMatrixMode); | |
| 657 | ✗ | DECLARE_GLUP_ADAPTER(PushMatrix); | |
| 658 | ✗ | DECLARE_GLUP_ADAPTER(PopMatrix); | |
| 659 | ✗ | DECLARE_GLUP_ADAPTER(GetMatrix); | |
| 660 | ✗ | DECLARE_GLUP_FUNC(LoadIdentity); | |
| 661 | ✗ | DECLARE_GLUP_ADAPTER(LoadMatrix); | |
| 662 | ✗ | DECLARE_GLUP_ADAPTER(MultMatrix); | |
| 663 | ✗ | DECLARE_GLUP_FUNC_WITH_NAME(glupTranslated,"Translate"); | |
| 664 | ✗ | DECLARE_GLUP_FUNC_WITH_NAME(glupScaled,"Scale"); | |
| 665 | ✗ | DECLARE_GLUP_FUNC_WITH_NAME(glupRotated,"Rotate"); | |
| 666 | ✗ | DECLARE_GLUP_ADAPTER(Begin); | |
| 667 | ✗ | DECLARE_GLUP_ADAPTER(End); | |
| 668 | ✗ | DECLARE_GLUP_ADAPTER(Vertex); | |
| 669 | ✗ | DECLARE_GLUP_ADAPTER(Color); | |
| 670 | ✗ | DECLARE_GLUP_ADAPTER(TexCoord); | |
| 671 | ✗ | DECLARE_GLUP_ADAPTER(Normal); | |
| 672 | |||
| 673 | ✗ | DECLARE_GLUP_COLOR("black", 0.0, 0.0, 0.0); | |
| 674 | ✗ | DECLARE_GLUP_COLOR("white", 1.0, 1.0, 1.0); | |
| 675 | ✗ | DECLARE_GLUP_COLOR("gray", 0.5, 0.5, 0.5); | |
| 676 | ✗ | DECLARE_GLUP_COLOR("red", 1.0, 0.0, 0.0); | |
| 677 | ✗ | DECLARE_GLUP_COLOR("green", 0.0, 1.0, 0.0); | |
| 678 | ✗ | DECLARE_GLUP_COLOR("blue", 0.0, 0.0, 1.0); | |
| 679 | ✗ | DECLARE_GLUP_COLOR("yellow", 1.0, 1.0, 0.0); | |
| 680 | ✗ | DECLARE_GLUP_COLOR("pink", 1.0, 0.75, 0.793); | |
| 681 | ✗ | DECLARE_GLUP_COLOR("brown",0.6445,0.164,0.164); | |
| 682 | |||
| 683 | ✗ | DECLARE_GLUP_FUNC(SetSpecular); | |
| 684 | ✗ | DECLARE_GLUP_FUNC(GetSpecular); | |
| 685 | |||
| 686 | ✗ | lua_setglobal(L, "GLUP"); | |
| 687 | |||
| 688 | |||
| 689 | ✗ | } | |
| 690 | |||
| 691 | ✗ | void adjust_lua_glup_state(lua_State* L) { | |
| 692 | using namespace LUAGLUPImpl; | ||
| 693 | |||
| 694 | ✗ | if(glupCurrentContext() == nullptr) { | |
| 695 | ✗ | return; | |
| 696 | } | ||
| 697 | |||
| 698 | ✗ | if(luaglup_primitiveactive(L)) { | |
| 699 | ✗ | glupEnd(); | |
| 700 | ✗ | luaglup_setprimitiveactive(L,false); | |
| 701 | } | ||
| 702 | |||
| 703 | ✗ | luaglup_adjustmatrixstack(L,GLUP_MODELVIEW_MATRIX); | |
| 704 | ✗ | luaglup_adjustmatrixstack(L,GLUP_PROJECTION_MATRIX); | |
| 705 | ✗ | luaglup_adjustmatrixstack(L,GLUP_TEXTURE_MATRIX); | |
| 706 | } | ||
| 707 |