From bb6e768ac2663cc7603aadac42d22b64ebd45bc4 Mon Sep 17 00:00:00 2001 From: Maxime Graulich <maxime.graulich@gmail.com> Date: Mon, 8 Jul 2013 08:37:46 +0000 Subject: [PATCH] Use Trackball for rotation, scale around the start point and translate on the current 2D plane --- contrib/mobile/Trackball.cpp | 327 +++++++++++++++ contrib/mobile/Trackball.h | 79 ++++ contrib/mobile/androidGModel.cpp | 36 +- contrib/mobile/androidGModel.h | 25 +- contrib/mobile/drawContext.cpp | 683 +++++++++++++++++++++++++++++++ contrib/mobile/drawContext.h | 65 +++ contrib/mobile/movePosition.h | 45 ++ 7 files changed, 1216 insertions(+), 44 deletions(-) create mode 100644 contrib/mobile/Trackball.cpp create mode 100644 contrib/mobile/Trackball.h create mode 100644 contrib/mobile/drawContext.cpp create mode 100644 contrib/mobile/drawContext.h create mode 100644 contrib/mobile/movePosition.h diff --git a/contrib/mobile/Trackball.cpp b/contrib/mobile/Trackball.cpp new file mode 100644 index 0000000000..3b01bdbafd --- /dev/null +++ b/contrib/mobile/Trackball.cpp @@ -0,0 +1,327 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +/* + * Modified for inclusion in Gmsh (rotmatrix as a vector + + * float->double + optional use of hyperbolic sheet for z-rotation) + */ +#include <math.h> +#include "Trackball.h" +#include <iostream> +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (.8) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static double tb_project_to_sphere(double, double, double); +static void normalize_quat(double [4]); +using namespace std ; + +void +vzero(double *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +void +vset(double *v, double x, double y, double z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +void +vsub(const double *src1, const double *src2, double *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +void +vcopy(const double *v1, double *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +void +vcross(const double *v1, const double *v2, double *cross) +{ + double temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +double +vlength(const double *v) +{ + return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +void +vscale(double *v, double div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +void +vnormal(double *v) +{ + vscale(v,1.0/vlength(v)); +} + +double +vdot(const double *v1, const double *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void +vadd(const double *src1, const double *src2, double *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(double q[4], double p1x, double p1y, double p2x, double p2y) +{ + double a[3]; /* Axis of rotation */ + double phi; /* how much to rotate about axis */ + double p1[3], p2[3], d[3]; + double t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1,p1x,p1y,tb_project_to_sphere(TRACKBALLSIZE,p1x,p1y)); + vset(p2,p2x,p2y,tb_project_to_sphere(TRACKBALLSIZE,p2x,p2y)); + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1,p2,d); + t = vlength(d); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0 * asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void axis_to_quat(double a[3], double phi, double q[4]) +{ + vnormal(a); + vcopy(a,q); + vscale(q,sin(phi/2.0)); + q[3] = cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static double +tb_project_to_sphere(double r, double x, double y) +{ + double d, t, z; + + d = sqrt(x*x + y*y); + + if (d < r ) { + z = sqrt(r*r - d*d); + } else { + z = 0.; + } + + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(double q1[4], double q2[4], double dest[4]) +{ + static int count=0; + double t1[4], t2[4], t3[4]; + double tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void +normalize_quat(double q[4]) +{ + int i; + double mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void +build_rotmatrix(double m[16], double q[4]) +{ + m[0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); + m[1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); + m[2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); + m[3] = 0.0; + + m[4] = 2.0 * (q[0] * q[1] + q[2] * q[3]); + m[5]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); + m[6] = 2.0 * (q[1] * q[2] - q[0] * q[3]); + m[7] = 0.0; + + m[8] = 2.0 * (q[2] * q[0] - q[1] * q[3]); + m[9] = 2.0 * (q[1] * q[2] + q[0] * q[3]); + m[10] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); + m[11] = 0.0; + + m[12] = 0.0; + m[13] = 0.0; + m[14] = 0.0; + m[15] = 1.0; +} diff --git a/contrib/mobile/Trackball.h b/contrib/mobile/Trackball.h new file mode 100644 index 0000000000..6a46832022 --- /dev/null +++ b/contrib/mobile/Trackball.h @@ -0,0 +1,79 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void +trackball(double q[4], double p1x, double p1y, double p2x, double p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void +add_quats(double *q1, double *q2, double *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void +build_rotmatrix(double m[16], double q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void +axis_to_quat(double a[3], double phi, double q[4]); + +double trackballsize() ; diff --git a/contrib/mobile/androidGModel.cpp b/contrib/mobile/androidGModel.cpp index 9d6e0b499f..0827a1aa07 100644 --- a/contrib/mobile/androidGModel.cpp +++ b/contrib/mobile/androidGModel.cpp @@ -14,7 +14,7 @@ #include <gmsh/PViewOptions.h> #include "androidGModel.h" -#include "drawGModel.h" +#include "drawContext.h" onelab::server *getOnelab() {return onelab::server::instance();} @@ -32,6 +32,7 @@ class MobileMessage : public GmshMessage { if(level == "Error") { + LOGE("%s", message.c_str()); if(message.size() <= 26 || message.substr(message.size()-25,25) != "check the log for details") return; if(!gCallbackObject) @@ -48,15 +49,12 @@ class MobileMessage : public GmshMessage env->CallVoidMethod(gCallbackObject, mid, jstr); env->DeleteLocalRef(jstr); env->DeleteLocalRef(jClass); - LOGE("%s", message.c_str()); return; } else if(level == "Progress") { if(!gCallbackObject) return; - //if ((gJavaVM->GetEnv((void**)&env, JNI_VERSION_1_6)) < 0) - // return; if ((gJavaVM->AttachCurrentThread(&env, NULL)) < 0) return; jstring jstr = env->NewStringUTF(message.c_str()); @@ -76,7 +74,7 @@ class MobileMessage : public GmshMessage requestRender(); return; } - LOGI("%s", message.c_str()); + LOGI("%s:\t%s", level.c_str(), message.c_str()); } }; @@ -109,47 +107,37 @@ JNIEXPORT jlong JNICALL Java_org_geuz_onelab_Gmsh_init Msg::SetCallback(new MobileMessage()); const char* name = env->GetStringUTFChars(jname, NULL); - return reinterpret_cast<jlong>(new drawGModel()); + return reinterpret_cast<jlong>(new drawContext()); } JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_loadFile (JNIEnv *env, jobject obj, jlong jptr, jstring jname) { const char* filename = env->GetStringUTFChars(jname, NULL); - ((drawGModel *)jptr)->load(filename); + ((drawContext *)jptr)->load(filename); } JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_initView (JNIEnv *env, jobject obj, jlong jptr, jint w, jint h) { - ((drawGModel *)jptr)->initView(w,h); + ((drawContext *)jptr)->initView(w,h); } JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_drawView (JNIEnv *env, jobject obj, jlong jptr) { - ((drawGModel *)jptr)->drawView(); -} -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setTranslation - (JNIEnv *env, jobject obj, jlong jptr, jfloat tx, jfloat ty, jfloat tz) -{ - ((drawGModel *)jptr)->setTranslation(tx, ty, tz); -} -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setScale - (JNIEnv *env, jobject obj, jlong jptr, jfloat sx, jfloat sy, jfloat sz) -{ - ((drawGModel *)jptr)->setScale(sx, sy, sz); + ((drawContext *)jptr)->drawView(); } -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setRotate - (JNIEnv *env, jobject obj, jlong jptr, jfloat rx, jfloat ry, jfloat rz) +JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_eventHandler + (JNIEnv *env, jobject obj, jlong jptr, jint jevent, jfloat jx, jfloat jy) { - ((drawGModel *)jptr)->setRotation(rx, ry, rz); + ((drawContext *)jptr)->eventHandler(jevent, jx, jy); } JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setShow (JNIEnv *env, jobject obj, jlong jptr, jstring jwhat, jboolean value) { const char* what = env->GetStringUTFChars(jwhat, NULL); if(strcmp(what, "mesh") == 0) - ((drawGModel *)jptr)->showMesh(value); + ((drawContext *)jptr)->showMesh(value); else if(strcmp(what, "geom") == 0) - ((drawGModel *)jptr)->showGeom(value); + ((drawContext *)jptr)->showGeom(value); } JNIEXPORT jlong JNICALL Java_org_geuz_onelab_Gmsh_getOnelabInstance (JNIEnv *env , jobject obj) diff --git a/contrib/mobile/androidGModel.h b/contrib/mobile/androidGModel.h index 9302ef6879..21192e45a3 100644 --- a/contrib/mobile/androidGModel.h +++ b/contrib/mobile/androidGModel.h @@ -5,6 +5,7 @@ #ifndef _Included_org_geuz_onelab_Gmsh #define _Included_org_geuz_onelab_Gmsh void requestRender(); +unsigned char *getBitmapFromString(const char *text); #ifdef __cplusplus extern "C" { #endif @@ -42,27 +43,11 @@ JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_drawView /* * Class: org_geuz_onelab_Gmsh - * Method: setTranslation - * Signature: (JFFF)V + * Method: eventHandler + * Signature: (JIFF)V */ -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setTranslation - (JNIEnv *, jobject, jlong, jfloat, jfloat, jfloat); - -/* - * Class: org_geuz_onelab_Gmsh - * Method: setScale - * Signature: (JFFF)V - */ -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setScale - (JNIEnv *, jobject, jlong, jfloat, jfloat, jfloat); - -/* - * Class: org_geuz_onelab_Gmsh - * Method: setRotate - * Signature: (JFFF)V - */ -JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_setRotate - (JNIEnv *, jobject, jlong, jfloat, jfloat, jfloat); +JNIEXPORT void JNICALL Java_org_geuz_onelab_Gmsh_eventHandler + (JNIEnv *, jobject, jlong, jint, jfloat, jfloat); /* * Class: org_geuz_onelab_Gmsh diff --git a/contrib/mobile/drawContext.cpp b/contrib/mobile/drawContext.cpp new file mode 100644 index 0000000000..ac6ff3ef50 --- /dev/null +++ b/contrib/mobile/drawContext.cpp @@ -0,0 +1,683 @@ +#if !defined(BUILD_ANDROID) +#define BUILD_IOS 1 +#endif + +#include <map> + +#if defined(BUILD_IOS) +#include <OpenGLES/ES1/gl.h> +#include <OpenGLES/ES1/glext.h> + +#include <Gmsh/Gmsh.h> +#include <Gmsh/GModel.h> +#include <Gmsh/MElement.h> +#include <Gmsh/VertexArray.h> +#include <Gmsh/onelab.h> +#include <Gmsh/onelabUtils.h> +#include <Gmsh/PView.h> +#include <Gmsh/PViewOptions.h> +#include <Gmsh/Context.h> +#include <Gmsh/StringUtils.h> + +#include <GetDP/GetDP.h> +#endif + +#if defined(BUILD_ANDROID) +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <gmsh/Gmsh.h> +#include <gmsh/GModel.h> +#include <gmsh/MElement.h> +#include <gmsh/VertexArray.h> +#include <gmsh/onelab.h> +#include <gmsh/onelabUtils.h> +#include <gmsh/PView.h> +#include <gmsh/PViewOptions.h> +#include <gmsh/Context.h> +#include <gmsh/StringUtils.h> + +#include <getdp/GetDP.h> + +#include "androidGModel.h" +#endif + +#include "drawContext.h" +#include "Trackball.h" + +static bool locked = false; + +drawContext::drawContext() +{ + new GModel(); + GmshInitialize(); + GmshSetOption("Mesh", "SurfaceFaces", 1.); + GmshSetOption("General", "Terminal", 1.); +#ifdef DEBUG + GmshSetOption("General", "Verbosity", 99.); +#else + GmshSetOption("General", "Verbosity", 10.); +#endif + onelabUtils::setFirstComputationFlag(false); + for(int i = 0; i < 3; i++){ + _translate[i] = 0.; + _scale[i] = 1.; + } + setQuaternion(0., 0., 0., 1.); + + _fillMesh = false; + _showMesh = false; + _showGeom = true; + _gradiant = true; +} + +static void checkGlError(const char* op) { + for (GLint error = glGetError(); error; error = glGetError()) + Msg::Error("%s: glError (0x%x)",op,error); +} + +void drawContext::load(std::string filename) +{ + if(locked) return; + // clear previous GModel, onelab datas and PView + GModel::list.clear(); + PView::list.clear(); + onelab::server::instance()->clear(); + + // open the file with Gmsh + GmshOpenProject(filename); + + // run getdp witout parameter + onelab_cb("check"); + + // to allow the firs run + onelab::server::instance()->setChanged(true, "Gmsh"); + onelab::server::instance()->setChanged(true, "GetDP"); +} + +void drawContext::eventHandler(int event, float x, float y) +{ + this->_current.set(this->_scale, this->_translate, this->_right, this->_left, this->_bottom, this->_top, this->_width, this->_height, x, y); + switch(event) + { + case 0: // finger(s) press the screen + // in this case x and y represent the start point + this->_start.set(this->_scale, this->_translate, this->_right, this->_left, this->_bottom, this->_top, this->_width, this->_height, x, y); + this->_previous.set(this->_scale, this->_translate, this->_right, this->_left, this->_bottom, this->_top, this->_width, this->_height, x, y); + break; + case 1: // finger move (translate) + // in this case x and y represent the current point + _translate[0] += (this->_current.wnr[0] - this->_previous.wnr[0]); + _translate[1] += (this->_current.wnr[1] - this->_previous.wnr[1]); + _translate[2] = 0.; + break; + case 2: // fingers move (scale) + // in this case we don't care about previous and current position, x represent the scale + this->_scale[0] = this->_scale[1] = this->_scale[2] = x; + this->_start.recenter(this->_scale, this->_translate); // FIXME somethink change the value of win + break; + case 3: // fingers move (rotate) + this->addQuaternion((2. * this->_previous.win[0] - this->_width) / this->_width, + (this->_height - 2. * this->_previous.win[1]) / this->_height, + (2. * this->_current.win[0] - this->_width) / this->_width, + (this->_height - 2. * this->_current.win[1]) / this->_height); + break; + case 4: // release the finger(s) + // Do nothink ? + break; + default: // all other reset the position + setQuaternion(0., 0., 0., 1.); + for(int i = 0; i < 3; i++){ + _translate[i] = 0.; + _scale[i] = 1.; + } + break; + } + this->_previous.set(this->_scale, this->_translate, this->_right, this->_left, this->_bottom, this->_top, this->_width, this->_height, x, y); +} + +void drawContext::setQuaternion(double q0, double q1, double q2, double q3) +{ + this->_quaternion[0] = q0; + this->_quaternion[1] = q1; + this->_quaternion[2] = q2; + this->_quaternion[3] = q3; +} + +void drawContext::addQuaternion(double p1x, double p1y, double p2x, double p2y) +{ + double quat[4]; + trackball(quat, p1x, p1y, p2x, p2y); + add_quats(quat, this->_quaternion, this->_quaternion); +} + +void drawContext::buildRotationMatrix() +{ + build_rotmatrix(_rotate, _quaternion); + for(int i=0; i<16;i++) + _rotatef[i] = (float)_rotate[i]; +} + +void drawContext::OrthofFromGModel() +{ + SBoundingBox3d bb = GModel::current()->bounds(); + double ratio = (double)(this->_width ? this->_width : 1.) / (double)(this->_height ? this->_height : 1.); + double modelh = bb.max().y() - bb.min().y(), modelw = bb.max().x() - bb.min().x(); + double modelratio = (modelw ? modelw : 1.) / (modelh ? modelh : 1.); + double xmin = -ratio, xmax = ratio, ymin = -1., ymax = 1.; + xmin = bb.min().x(); + xmax = bb.max().x(); + ymin = bb.min().x() / ratio; + ymax = bb.max().x() / ratio; + xmax += (xmax - xmin) / 5.; + xmin -= (xmax - xmin) / 5.; + ymax += (ymax - ymin) / 5.; + ymin -= (ymax - ymin) / 5.; + + // clipping + double zmax = std::max(fabs(bb.min().z()), fabs(bb.max().z())); + double clip = zmax * 5.; + clip = 1.; + + GLint matrixMode; + glGetIntegerv(GL_MATRIX_MODE, &matrixMode); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + this->_left = (xmin != 0 || xmax != 0)? xmin : -ratio; + this->_right = (xmin != 0 || xmax != 0)? xmax : ratio; + this->_top = (xmin != 0 || xmax != 0)? ymax : 1.0; + this->_bottom = (xmin != 0 || xmax != 0)? ymin : -1.0; + glOrthof(this->_left, this->_right, this->_bottom, this->_top, -clip, clip); + + glMatrixMode(matrixMode); +} +void drawContext::initView(int w, int h) +{ + this->_height = h; + this->_width = w; + glViewport(0, 0, w, h); + + this->OrthofFromGModel(); + + glClearColor(.83,.85,.98,1.); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +void drawArray(VertexArray *va, GLint type, bool colorArray=false) +{ + if(!va) return; + glEnable(GL_BLEND); + glEnable(GL_RESCALE_NORMAL); + glShadeModel(GL_SMOOTH); + glVertexPointer(3, GL_FLOAT, 0, va->getVertexArray()); + glEnableClientState(GL_VERTEX_ARRAY); + glNormalPointer(GL_BYTE, 0, va->getNormalArray()); + glEnableClientState(GL_NORMAL_ARRAY); + if(colorArray) + { + glColorPointer(4, GL_UNSIGNED_BYTE, 0, va->getColorArray()); + glEnableClientState(GL_COLOR_ARRAY); + } + glDrawArrays(type, 0, va->getNumVertices()); + glDisable(GL_POLYGON_OFFSET_FILL); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glDisable(GL_RESCALE_NORMAL); + glDisable(GL_BLEND); +} + +void drawVector(double x, double y, double z, double dx, double dy, double dz) +{ + double l = sqrt(dx * dx + dy * dy + dz * dz), lt; + double n[3], t[3], u[3]; + + if(l == 0.0) return; + + GLfloat line[] = { + (GLfloat)x, (GLfloat)y, (GLfloat)z, + (GLfloat)(x+dx), (GLfloat)(y+dy), (GLfloat)(z+dz), + }; + glVertexPointer(3, GL_FLOAT, 0, line); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawArrays(GL_LINES, 0, 2); + glDisableClientState(GL_VERTEX_ARRAY); + + n[0] = dx / l; + n[1] = dy / l; + n[2] = dz / l; + + if((fabs(n[0]) >= fabs(n[1]) && fabs(n[0]) >= fabs(n[2])) || + (fabs(n[1]) >= fabs(n[0]) && fabs(n[1]) >= fabs(n[2]))) { + t[0] = n[1]; + t[1] = -n[0]; + t[2] = 0.; + } + else { + t[0] = 0.; + t[1] = n[2]; + t[2] = -n[1]; + } + + lt = sqrt(t[0] * t[0] + t[1] * t[1] + t[2] * t[2]); + t[0] /= lt; + t[1] /= lt; + t[2] /= lt; + + u[0] = n[1] * t[2] - n[2] * t[1]; + u[1] = n[2] * t[0] - n[0] * t[2]; + u[2] = n[0] * t[1] - n[1] * t[0]; + + lt = sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]); + u[0] /= lt; + u[1] /= lt; + u[2] /= lt; + + double f1 = 0.75; // Stem lenght + double b = 0.1 * l; + + GLfloat arrow[] = { + (GLfloat)(x + dx), (GLfloat)(y + dy), (GLfloat)(z + dz), + (GLfloat)(x + f1 * dx + b * (t[0])), (GLfloat)(y + f1 * dy + b * (t[1])), (GLfloat)(z + f1 * dz + b * (t[2])), + (GLfloat)(x + f1 * dx + b * (-t[0])), (GLfloat)(y + f1 * dy + b * (-t[1])), (GLfloat)(z + f1 * dz + b * (-t[2])), + + (GLfloat)(x + dx), (GLfloat)(y + dy), (GLfloat)(z + dz), + (GLfloat)(x + f1 * dx + b * (-u[0])), (GLfloat)(y + f1 * dy + b * (-u[1])), (GLfloat)(z + f1 * dz + b * (-u[2])), + (GLfloat)(x + f1 * dx + b * (u[0])), (GLfloat)(y + f1 * dy + b * (u[1])), (GLfloat)(z + f1 * dz + b * (u[2])), + }; + glVertexPointer(3, GL_FLOAT, 0, arrow); + glEnableClientState(GL_VERTEX_ARRAY); + glEnable(GL_LINE_SMOOTH); + glDrawArrays(GL_TRIANGLES, 0, 6); + glDisableClientState(GL_VERTEX_ARRAY); + glDisable(GL_LINE_SMOOTH); + +} + +void drawContext::drawVectorArray(PViewOptions *opt, VertexArray *va) +{ + if(!va || va->getNumVerticesPerElement() != 2) return; + + for(int i = 0; i < va->getNumVertices(); i += 2){ + float *s = va->getVertexArray(3 * i); + float *v = va->getVertexArray(3 * (i + 1)); + double l = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + double lmax = opt->tmpMax; + if((l && opt->vectorType) && lmax) + { + double scale = (opt->arrowSizeMax - opt->arrowSizeMin) / lmax; + if(opt->arrowSizeMin && l) scale += opt->arrowSizeMin / l; + double dx = scale * v[0]; + double dy = scale * v[1]; + double dz = scale * v[2]; + GLubyte *color = (GLubyte *)va->getColorArray(4 * i); + glColor4ub(*(color), *(color+1), *(color+2), *(color+3)); + if(fabs(dx) > 1. || fabs(dy) > 1. || fabs(dz) > 1.) + { + double d = (this->_right - this->_left) / this->_width / _scale[0]; + dx *= d; dy *= d; dz *= d; + double x = s[0], y = s[1], z = s[2]; + drawVector(x,y,z,dx,dy,dz); + } + } + } +} + +void drawContext::drawPView(PView *p) +{ + PViewOptions *opt = p->getOptions(); + PViewData *data = p->getData(true); + if(!opt->visible) return; + + glPointSize((GLfloat)opt->pointSize); + glLineWidth((GLfloat)opt->lineWidth); + + drawArray(p->va_points, GL_POINTS,true); + drawArray(p->va_lines, GL_LINES,true); + drawArray(p->va_triangles, GL_TRIANGLES,true); + + glLineWidth(1); + glPointSize(1); + + drawVectorArray(p->getOptions(), p->va_vectors); +} + +void drawContext::drawScale() +{ + glPushMatrix(); + glLoadIdentity(); + // Draw the scale bar + if(PView::list.size() < 1) return; + PView *p = PView::list[PView::list.size()-1]; + PViewOptions *opt = p->getOptions(); + + double width = 6*(this->_right -this->_left) / 10.; + double height = (this->_top - this->_bottom) / 20.; + double box = width / (opt->nbIso ? opt->nbIso : 1); + double xmin = this->_left + (this->_right - this->_left -width)/2.; + double ymin = this->_bottom + height; + + GLfloat *vertex = (GLfloat *)malloc(opt->nbIso*3*4*sizeof(GLfloat)); + GLubyte *color = (GLubyte *)malloc(opt->nbIso*4*4*sizeof(GLubyte)); + for(int i = 0; i < opt->nbIso; i++){ + if(opt->intervalsType == PViewOptions::Discrete || opt->intervalsType == PViewOptions::Numeric) + { + unsigned int col = opt->getColor(i, opt->nbIso); + color[i*4*4+0] = color[i*4*4+4] = color[i*4*4+8] = color[i*4*4+12] = (GLubyte)CTX::instance()->unpackRed(col); + color[i*4*4+1] = color[i*4*4+5] = color[i*4*4+9] = color[i*4*4+13] = (GLubyte)CTX::instance()->unpackGreen(col); + color[i*4*4+2] = color[i*4*4+6] = color[i*4*4+10] = color[i*4*4+14] = (GLubyte)CTX::instance()->unpackBlue(col); + color[i*4*4+3] = color[i*4*4+7] = color[i*4*4+11] = color[i*4*4+15] = (GLubyte)CTX::instance()->unpackAlpha(col); + vertex[i*3*4+0] = xmin + i * box; + vertex[i*3*4+1] = ymin; + vertex[i*3*4+2] = 0.; + vertex[i*3*4+3] = xmin + i * box; + vertex[i*3*4+4] = ymin + height; + vertex[i*3*4+5] = 0.; + vertex[i*3*4+6] = xmin + (i + 1) * box; + vertex[i*3*4+7] = ymin; + vertex[i*3*4+8] = 0.; + vertex[i*3*4+9] = xmin + (i + 1) * box; + vertex[i*3*4+10] = ymin + height; + vertex[i*3*4+11] = 0.; + } + else if(opt->intervalsType == PViewOptions::Continuous) + { + double dv = (opt->tmpMax - opt->tmpMin) / (opt->nbIso ? opt->nbIso : 1); + double v1 = opt->tmpMin + i * dv; + unsigned int col1 = opt->getColor(v1, opt->tmpMin, opt->tmpMax, true); + color[i*4*4+0] = color[i*4*4+4] = (GLubyte)CTX::instance()->unpackRed(col1); + color[i*4*4+1] = color[i*4*4+5] = (GLubyte)CTX::instance()->unpackGreen(col1); + color[i*4*4+2] = color[i*4*4+6] = (GLubyte)CTX::instance()->unpackBlue(col1); + color[i*4*4+3] = color[i*4*4+7] = (GLubyte)CTX::instance()->unpackAlpha(col1); + vertex[i*3*4+0] = xmin + i * box; + vertex[i*3*4+1] = ymin; + vertex[i*3*4+2] = 0.; + vertex[i*3*4+3] = xmin + i * box; + vertex[i*3*4+4] = ymin + height; + vertex[i*3*4+5] = 0.; + double v2 = opt->tmpMin + (i + 1) * dv; + unsigned int col2 = opt->getColor(v2, opt->tmpMin, opt->tmpMax, true); + color[i*4*4+8] = color[i*4*4+12] = (GLubyte)CTX::instance()->unpackRed(col2); + color[i*4*4+9] = color[i*4*4+13] = (GLubyte)CTX::instance()->unpackGreen(col2); + color[i*4*4+10] = color[i*4*4+14] = (GLubyte)CTX::instance()->unpackBlue(col2); + color[i*4*4+11] = color[i*4*4+15] = (GLubyte)CTX::instance()->unpackAlpha(col2); + vertex[i*3*4+6] = xmin + (i + 1) * box; + vertex[i*3*4+7] = ymin; + vertex[i*3*4+8] = 0.; + vertex[i*3*4+9] = xmin + (i + 1) * box; + vertex[i*3*4+10] = ymin + height; + vertex[i*3*4+11] = 0.; + } + else + { + unsigned int col = opt->getColor(i, opt->nbIso); + color[i*4*4+0] = color[i*4*4+4] = color[i*4*4+8] = color[i*4*4+12] = (GLubyte)CTX::instance()->unpackRed(col); + color[i*4*4+1] = color[i*4*4+5] = color[i*4*4+9] = color[i*4*4+13] = (GLubyte)CTX::instance()->unpackGreen(col); + color[i*4*4+2] = color[i*4*4+6] = color[i*4*4+10] = color[i*4*4+14] = (GLubyte)CTX::instance()->unpackBlue(col); + color[i*4*4+3] = color[i*4*4+7] = color[i*4*4+11] = color[i*4*4+15] = (GLubyte)CTX::instance()->unpackAlpha(col); + vertex[i*3*4+0] = xmin + i * box; + vertex[i*3*4+1] = ymin; + vertex[i*3*4+2] = 0.; + vertex[i*3*4+3] = xmin + i * box; + vertex[i*3*4+4] = ymin + height; + vertex[i*3*4+5] = 0.; + vertex[i*3*4+6] = xmin + (i + 1) * box; + vertex[i*3*4+7] = ymin; + vertex[i*3*4+8] = 0.; + vertex[i*3*4+9] = xmin + (i + 1) * box; + vertex[i*3*4+10] = ymin + height; + vertex[i*3*4+11] = 0.; + } + } + + glVertexPointer(3, GL_FLOAT, 0, vertex); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, color); + glEnableClientState(GL_COLOR_ARRAY); + if(opt->intervalsType == PViewOptions::Discrete || opt->intervalsType == PViewOptions::Numeric || opt->intervalsType == PViewOptions::Continuous) + glDrawArrays(GL_TRIANGLE_STRIP, 0, opt->nbIso*4); + else + glDrawArrays(GL_LINES, 0, opt->nbIso*4); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + free(vertex); + free(color); + glPopMatrix(); +} + +void drawContext::drawMesh() +{ + GModel::current()->fillVertexArrays(); + glColor4f(0,0,0,1.); + for(GModel::fiter it = GModel::current()->firstFace(); it != GModel::current()->lastFace(); it++){ + if(_fillMesh) drawArray((*it)->va_triangles, GL_TRIANGLES); + else drawArray((*it)->va_lines, GL_LINES); + } +} + +void drawContext::drawPost() +{ + if(PView::list.empty()) return ; + + for(unsigned int i = 0; i < PView::list.size(); i++){ + PView::list[i]->fillVertexArrays(); + drawPView(PView::list[i]); + } +} + +void drawContext::drawGeom() +{ + glColor4f(0,0,1.,1.); + glLineWidth(3); + for(GModel::eiter it = GModel::current()->firstEdge(); it != GModel::current()->lastEdge(); it++){ + GEdge *e = *it; + int N = e->minimumDrawSegments() + 1; + Range<double> t_bounds = e->parBounds(0); + double t_min = t_bounds.low(); + double t_max = t_bounds.high(); + + // Create a VA for this edge + GLfloat edge[N*3]; + + for(unsigned int i=0; i < N; i++) { + double t = t_min + (double)i / (double)(N-1) * (t_max - t_min); + GPoint p = e->point(t); + edge[i*3] = p.x(); edge[i*3+1] = p.y(); edge[i*3+2] = p.z(); + } + // Then print the VA + glVertexPointer(3, GL_FLOAT, 0, edge); + glEnableClientState(GL_VERTEX_ARRAY); + glDrawArrays(GL_LINE_STRIP, 0, N); + glDisableClientState(GL_VERTEX_ARRAY); + } + glLineWidth(1); +} + +void drawContext::drawAxes(double x0, double y0, double z0, double h) +{ + glLineWidth(5); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(x0, y0, z0); + glMultMatrixf(_rotatef); + glTranslatef(-x0, -y0, -z0); + + const GLfloat axes[] = { + (GLfloat)x0, (GLfloat)y0, (GLfloat)z0, + (GLfloat)(x0+h), (GLfloat)y0, (GLfloat)z0, + (GLfloat)x0, (GLfloat)y0, (GLfloat)z0, + (GLfloat)x0, (GLfloat)(y0+h), (GLfloat)z0, + (GLfloat)x0, (GLfloat)y0, (GLfloat)z0, + (GLfloat)x0, (GLfloat)y0, (GLfloat)(z0+h), + }; + const GLubyte colors[] = { + 255, 0, 0, 255, + 255, 0, 0, 255, + 0, 0, 255, 255, + 0, 0, 255, 255, + 0, 255, 0, 255, + 0, 255, 0, 255, + }; + glVertexPointer(3, GL_FLOAT, 0, axes); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); + glEnableClientState(GL_COLOR_ARRAY); + glDrawArrays(GL_LINES, 0, 6); + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glPopMatrix(); + glLineWidth(1); +} + +void drawContext::drawView() +{ + this->OrthofFromGModel(); + + glMatrixMode(GL_MODELVIEW); + // fill the background + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if(_gradiant) + { + glPushMatrix(); + glLoadIdentity(); + const GLfloat squareVertices[] = { + (GLfloat)this->_top, (GLfloat)this->_left, -5., + (GLfloat)this->_top, (GLfloat)this->_right, -5., + (GLfloat)this->_bottom, (GLfloat)this->_left, -5., + (GLfloat)this->_bottom, (GLfloat)this->_right, -5., + }; + const GLubyte squareColors[] = { + 255, 255, 255, 255, + 255, 255, 255, 255, + 190, 200, 255, 255, + 190, 200, 255, 255, + }; + glVertexPointer(3, GL_FLOAT, 0, squareVertices); + glEnableClientState(GL_VERTEX_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors); + glEnableClientState(GL_COLOR_ARRAY); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); + glPopMatrix(); + } + checkGlError("Draw background"); + // + glLoadIdentity(); + glScalef(_scale[0], _scale[1], _scale[2]); + glTranslatef(_translate[0], _translate[1], _translate[2]); + this->buildRotationMatrix(); + glMultMatrixf(_rotatef); + //glTranslatef(this->_translate[0]/this->_height,this->_translate[1]/this->_width,0); + //glScalef(this->_scale[0], this->_scale[1], this->_scale[2]); + checkGlError("Initialize position"); + + // + this->drawAxes(this->_right - (this->_top - this->_bottom)/9.0, this->_bottom + (this->_top - this->_bottom)/9.0, 0, (this->_top - this->_bottom)/10.); + this->drawPost(); + if(_showGeom) this->drawGeom(); + if(_showMesh) this->drawMesh(); + //this->drawScale(); + checkGlError("Draw model,post-pro,..."); +} + +std::vector<std::string> commandToVector(const std::string cmd) +{ + std::vector<std::string> ret; + int pos=0, last=0; + while((pos = cmd.find("-", last+1)) != std::string::npos) + { + ret.push_back(cmd.substr(last,pos-1-last)); + last = pos; + } + ret.push_back(cmd.substr(last,cmd.size()-1)); + return ret; +} + +int onelab_cb(std::string action) +{ + Msg::Debug("Ask onlab to %s", action.c_str()); + if(action == "stop") + { + onelab::string o("GetDP/Action", "stop"); + o.setVisible(false); + o.setNeverChanged(true); + onelab::server::instance()->set(o); + return 0; + } + if(locked) return -1; + locked = true; + int redraw = 0; + if(action == "reset") + { + onelab::server::instance()->clear(); + onelabUtils::runGmshClient(action, true); + action = "check"; + } + + Msg::ResetErrorCounter(); + + if(action == "compute") + { + onelabUtils::initializeLoop("1"); + onelabUtils::initializeLoop("2"); + onelabUtils::initializeLoop("3"); + } + + do + { + if(onelabUtils::runGmshClient(action, true)) + redraw = 1; + + if(redraw == 0 && !onelab::server::instance()->getChanged("GetDP"))continue; + + std::vector<onelab::string> ps; + onelab::server::instance()->get(ps, "GetDP/1ModelName"); + if(ps.empty()){ + std::vector<std::string> split = SplitFileName(GModel::current()->getFileName()); + std::string name(split[0] + split[1]); + onelab::string o("GetDP/1ModelName", name, "Model name"); + o.setKind("file"); + onelab::server::instance()->set(o); + } + onelab::string o("GetDP/Action", action); + o.setVisible(false); + o.setNeverChanged(true); + onelab::server::instance()->set(o); + + if(action == "compute" && (onelab::server::instance()->getChanged("Gmsh") || onelab::server::instance()->getChanged("GetDP"))) + { + std::string filename = GModel::current()->getFileName(); + std::vector<std::string> args; + args.push_back("getdp"); + std::vector<onelab::string> onelabArgs; + onelab::server::instance()->get(onelabArgs, "GetDP/1ModelName"); + args.push_back((onelabArgs.empty())? SplitFileName(filename)[0] + SplitFileName(filename)[1] : onelabArgs[0].getValue()); + onelab::server::instance()->get(onelabArgs, "GetDP/9ComputeCommand"); + std::vector<std::string> compute = commandToVector((onelabArgs.empty())? "" : onelabArgs[0].getValue().c_str()); + args.insert( args.end(), compute.begin(), compute.end() ); + args.push_back("-onelab"); + args.push_back("GetDP"); + GetDP(args, onelab::server::instance()); + } + if(action == "check" && (onelab::server::instance()->getChanged("Gmsh") || onelab::server::instance()->getChanged("GetDP"))) + { + std::string filename = GModel::current()->getFileName(); + std::vector<std::string> args; + args.push_back("getdp"); + std::vector<onelab::string> onelabArgs; + args.push_back(SplitFileName(filename)[0] + SplitFileName(filename)[1]); + onelab::server::instance()->get(onelabArgs, "GetDP/9CheckCommand"); + args.push_back((onelabArgs.empty())? "" : onelabArgs[0].getValue()); + args.push_back("-onelab"); + args.push_back("GetDP"); + GetDP(args, onelab::server::instance()); + } + } while(action == "compute" && (onelabUtils::incrementLoop("3") || onelabUtils::incrementLoop("2") || onelabUtils::incrementLoop("1"))); + + locked = false; + + return redraw; +} + +// vim:set ts=2: diff --git a/contrib/mobile/drawContext.h b/contrib/mobile/drawContext.h new file mode 100644 index 0000000000..f89c1de5bc --- /dev/null +++ b/contrib/mobile/drawContext.h @@ -0,0 +1,65 @@ +#ifndef _DRAW_GMODEL_H_ +#define _DRAW_GMODEL_H_ + +#if !defined(BUILD_ANDROID) +#define BUILD_IOS 1 +#endif + +#include <string> + +#if defined(BUILD_IOS) +#include <Gmsh/PView.h> +#include <Gmsh/PViewOptions.h> +#include <Gmsh/Context.h> +#endif + +#include "movePosition.h" + +int onelab_cb(const std::string); + +class drawContext{ +private: + float _translate[3], _scale[3]; // current translation and scale + double _rotate[16]; // current rotation matrix (double for Trackball) + float _rotatef[16]; // current rotation matrix (float for OpenGL ES) + double _quaternion[4]; // current quaternion used for rotation + movePosition _start, _previous, _current; // store informations about user interactions + int _width, _height; // size of OpenGL context in pixel + float _left, _right, _top, _bottom; // value of "border" + bool _gradiant, // show the background gradiant + _showGeom, // show the Geometry + _showMesh, // show the Mesh + _fillMesh; // fill the Mesh + + void OrthofFromGModel(void); + void drawPView(PView *p); + void drawVectorArray(PViewOptions *opt, VertexArray *va); + +public: + drawContext(); + ~drawContext(){} + void load(std::string filename); + void eventHandler(int event, float x=0, float y=0); + void setQuaternion(double q0, double q1, double q2, double q3); + void addQuaternion(double p1x, double p1y, double p2x, double p2y); + void buildRotationMatrix(); + void setTranslate(int i, float t) {if(i>=0 && i<3) this->_translate[i] = t;} + float getTranslate(int i) {if(i>=0 && i<3) return this->_translate[i]; return 0;} + void setScale(int i, float s) {if(i>=0 && i<3) this->_scale[i] = s;} + float getScale(int i) {if(i>=0 && i<3) return this->_scale[i]; return 0;} + void initView(int w, int h); + void drawView(); + void drawAxes(double x0=0., double y0=0., double z0=0., double h=0.5); + void drawGeom(); + void drawMesh(); + void drawPost(); + void drawScale(); + void useGradiant(bool gradiant=true) {_gradiant = gradiant;} + void showGeom(bool show=true) {_showGeom = show;} + void showMesh(bool show=true) {_showMesh = show;} + void fillMesh(bool show=true) {_fillMesh = show;} + bool isShowedMesh(){return _showMesh;} + bool isShowedGeom(){return _showGeom;} +}; + +#endif diff --git a/contrib/mobile/movePosition.h b/contrib/mobile/movePosition.h new file mode 100644 index 0000000000..b8e62cc5d8 --- /dev/null +++ b/contrib/mobile/movePosition.h @@ -0,0 +1,45 @@ +class movePosition { + public: + float win[3]; // window coordinates + float wnr[3]; // world coordinates BEFORE rotation + float s[3]; // scaling state when the event was recorded + float t[3]; // translation state when the event was recorded + movePosition() + { + for(int i = 0; i < 3; i++) + win[i] = wnr[i] = s[i] = t[i] = 0.; + } + movePosition(const movePosition &instance) + { + for(int i = 0; i < 3; i++){ + win[i] = instance.win[i]; + wnr[i] = instance.wnr[i]; + s[i] = instance.s[i]; + t[i] = instance.t[i]; + } + } + void set(float scale[3], float translate[3], float vxmax, float vxmin, float vymin, float vymax, int width, int height, int x, int y) + { + for(int i = 0; i < 3; i++){ + s[i] = scale[i]; + t[i] = translate[i]; + } + win[0] = (float)x; + win[1] = (float)y; + win[2] = 0.; + + wnr[0] = + (vxmin + win[0] / (float)width * (vxmax - vxmin)) / scale[0] - translate[0]; + wnr[1] = + (vymax - win[1] / (float)height * (vymax - vymin)) / scale[1] - translate[1]; + wnr[2] = 0.; + } + void recenter(float scale[3], float translate[3]) const + { + // compute the equivalent translation to apply *after* the scaling so that + // the scaling is done around the point which was clicked: + translate[0] = t[0] * (s[0] / scale[0]) - wnr[0] * (1. - (s[0] / scale[0])); + translate[1] = t[1] * (s[1] / scale[1]) - wnr[1] * (1. - (s[1] / scale[1])); + } +}; + -- GitLab