JaRMoS  1.1
Java Reduced Model Simulations
 All Classes Namespaces Files Functions Variables Enumerator Groups Pages
OpenGLBase.java
Go to the documentation of this file.
1 package jarmos.visual;
2 
3 import jarmos.Log;
6 
7 import java.nio.FloatBuffer;
8 import java.nio.ShortBuffer;
9 
18 public class OpenGLBase {
19 
20  public enum Orientation {
23  }
24 
25  public static final float FRAME_INCREASE = 0.01f;
26 
30  private int[] _color_off;
31 
35  private int _faces_off = 0;
36 
40  private int _indexwf_off = 0;
41 
45  private int[] _normal_off;
46 
50  private int[] _vertex_off;
51 
52  // Camera control
53  private Camera camera;
54 
55  private Orientation orientation = Orientation.LANDSCAPE;
56 
60  private int currentColorField = 0;
61 
62  private int currentFrame = 0;
63 
64  private float currentFramef = 0f;
65 
66  protected FloatBuffer floatBuf;
67 
71  public boolean isContinuousRotation = true;
72 
76  public boolean isFrontFace = true;
77 
78  private boolean ispaused = false;
79 
80  private String[] names;
81 
82  private float pos[] = null;
83 
87  private float scaleFactor = 1.0f;
88 
89  private float[] orthoproj = null;
90 
91  protected ShortBuffer shortBuf;
92 
93  private VisualizationData vData;
94 
95  private int w, h;
96 
103  this(vData, 700, 400);
104  }
105 
106  public OpenGLBase(VisualizationData vData, int width, int height) {
107  this.vData = vData;
108  // Use the (perhaps global) buffers from VisData
109  floatBuf = vData.getFloatBuffer();
110  shortBuf = vData.getShortBuffer();
111  setSize(width, height);
112  }
113 
114  public void setSize(int width, int height) {
115  w = width;
116  h = height;
117  updateOrthographicProjection();
118  // Log.d("OpenGLBase", "set size: w"+width+" h"+height);
119  }
120 
125  public void resetView() {
126  camera = new Camera(0f, -getBoxSize(), 0f, 0f, 1f, 0f, 0f, 0f, 1f);
127  pos = new float[] { 0f, 0f };
128  scaleFactor = 1.0f;
129  isFrontFace = true;
130  // Log.d("OpenGLBase", "reset view!");
131  }
132 
133  private void updateOrthographicProjection() {
134  float exrat, ax = 0, ay = 0; // marginal extension ratio
135  if (is2D())
136  exrat = 0.65f * getBoxSize();
137  else
138  exrat = 0.95f * getBoxSize();
139  switch (orientation) {
140  case PORTRAIT:
141  ax = 1.0f;
142  ay = (float) w / (float) h;
143  break;
144  case LANDSCAPE:
145  ax = (float) h / (float) w;
146  ay = 1.0f;
147  }
148  orthoproj = new float[] { -exrat / ax, exrat / ax, -exrat / ay, exrat / ay, -100, 100 };
149  // Log.d("OpenGLBase", "OrthProj update: "+Arrays.toString(orthoproj));
150  }
151 
156  public void addPos(float posx, float posy) {
157  pos[0] += posx;
158  pos[1] += posy;
159  }
160 
161  /*
162  * Conversion method for FV discretized field variables who give solution values on faces rather than nodes.
163  *
164  * Computes the node color as mean of all adjacent face colors.
165  *
166  * TODO move this algorithm to ROMSim, as other visualization libraries might be able to directly set colors for
167  * faces.
168  */
169  private float[] elementToVertexColors(float[] faceCol) {
170  GeometryData gData = vData.getGeometryData();
171  int numTimeSteps = faceCol.length / (4 * gData.numFaces);
172  float[] nodeCol = new float[numTimeSteps * gData.getNumVertices() * 4];
173 
174  // float T = numTimeSteps * nodes;
175  // for (int ts = 0; ts < T; ts++) {
176  // nodeCol[4*ts] = ts/T;
177  // nodeCol[4*ts+1] = 0;
178  // nodeCol[4*ts+2] = 0;
179  // nodeCol[4*ts+3] = 0.8f;
180  // }
181  // Perform summary for each timestep (if more than one)!
182  for (int ts = 0; ts < numTimeSteps; ts++) {
183  int face_off = ts * 4 * gData.numFaces;
184  int node_off = ts * 4 * gData.getNumVertices();
185  float[] valuesAdded = new float[gData.getNumVertices()];
186  for (int f = 0; f < gData.numFaces; f++) {
187  // Edge 1
188  int n1 = gData.faces[3 * f];
189  nodeCol[node_off + 4 * n1] += faceCol[face_off + 4 * f];
190  nodeCol[node_off + 4 * n1 + 1] += faceCol[face_off + 4 * f + 1];
191  nodeCol[node_off + 4 * n1 + 2] += faceCol[face_off + 4 * f + 2];
192  nodeCol[node_off + 4 * n1 + 3] += faceCol[face_off + 4 * f + 3];
193  valuesAdded[n1]++;
194  // Edge 2
195  int n2 = gData.faces[3 * f + 1];
196  nodeCol[node_off + 4 * n2] += faceCol[face_off + 4 * f];
197  nodeCol[node_off + 4 * n2 + 1] += faceCol[face_off + 4 * f + 1];
198  nodeCol[node_off + 4 * n2 + 2] += faceCol[face_off + 4 * f + 2];
199  nodeCol[node_off + 4 * n2 + 3] += faceCol[face_off + 4 * f + 3];
200  valuesAdded[n2]++;
201  // Edge 3
202  int n3 = gData.faces[3 * f + 2];
203  nodeCol[node_off + 4 * n3] += faceCol[face_off + 4 * f];
204  nodeCol[node_off + 4 * n3 + 1] += faceCol[face_off + 4 * f + 1];
205  nodeCol[node_off + 4 * n3 + 2] += faceCol[face_off + 4 * f + 2];
206  nodeCol[node_off + 4 * n3 + 3] += faceCol[face_off + 4 * f + 3];
207  valuesAdded[n3]++;
208  }
209  // Compute means
210  for (int n = 0; n < gData.getNumVertices(); n++) {
211  nodeCol[node_off + 4 * n] /= valuesAdded[n];
212  nodeCol[node_off + 4 * n + 1] /= valuesAdded[n];
213  nodeCol[node_off + 4 * n + 2] /= valuesAdded[n];
214  nodeCol[node_off + 4 * n + 3] /= valuesAdded[n];
215  }
216  }
217  return nodeCol;
218  }
219 
220  private String getShortFillState(int curFloatBufOffset) {
221  return Math.round((curFloatBufOffset / (double)shortBuf.capacity()) * 100) + "%";
222  }
223 
224  private String getFloatFillState(int off) {
225  return Math.round((off / (double)floatBuf.capacity()) * 100) + "%";
226  }
227 
228  protected void frameRendered() {
229  /*
230  * Draw next animation frame if there are more than one
231  */
232  if (!ispaused && (vData.numFrames > 1 || _vertex_off.length > 1)) {
233  currentFramef += FRAME_INCREASE * vData.numFrames;
234  currentFrame = (int) Math.floor(currentFramef);
235  if (currentFrame >= vData.numFrames) {
236  currentFrame = 0;
237  currentFramef = 0;
238  }
239  }
240 
241  if (!is2D()) {
242  /*
243  * Set yawing/pitching rotation angles and update camera
244  */
245  camera.SetRotation(-pos[0], -pos[1]);
246  /*
247  * Update rotation if continuous
248  */
249  if (isContinuousRotation) {
250  float minrot = 0.16f / scaleFactor;
251  float sgnx = Math.signum(pos[0]), sgny = Math.signum(pos[1]);
252  pos[0] = sgnx * Math.max(minrot, Math.min(24.00f, sgnx * pos[0] * 0.95f));
253  pos[1] = sgny * Math.max(minrot, Math.min(24.00f, sgny * pos[1] * 0.95f));
254  }
255  }
256  }
257 
258  protected float getBoxSize() {
259  return vData.getGeometryData().boxsize;
260  }
261 
262  protected int getCurrentColorOffset() {
263  return _color_off[currentColorField] + (currentFrame) * (vData.getGeometryData().getNumVertices() * 4);
264  }
265 
266  protected int getCurrentNormalsOffset() {
267  return _normal_off[currentFrame];
268  }
269 
270  protected int getCurrentVertexOffset() {
271  return _vertex_off[currentFrame];
272  }
273 
274  protected int getCurrentWireframeOffset() {
275  return _indexwf_off;
276  }
277 
278  protected int getFaceOffset() {
279  return _faces_off;
280  }
281 
286  protected int getHeight() {
287  return h;
288  }
289 
290  protected int getNumFaces() {
291  return vData.getGeometryData().numFaces;
292  }
293 
294  protected float[] getOrtographicProj() {
295  return orthoproj;
296  }
297 
298  protected float[] getRotationMatrix() {
299  return camera.getRotationMatrix();
300  }
301 
302  protected float getScalingFactor() {
303  return scaleFactor;
304  }
305 
310  protected int getWidth() {
311  return w;
312  }
313 
314  protected float getXTranslation() {
315  return pos[0] * getBoxSize() / 20f;
316  }
317 
318  protected float getYTranslation() {
319  return pos[1] * getBoxSize() / 20f;
320  }
321 
328  protected void initRendering() {
329 
330  GeometryData gData = vData.getGeometryData();
331 
332  resetView();
333 
334  /*
335  * Fill the buffers
336  */
337  currentFrame = 0;
338  currentFramef = 0.0f;
339 
340  /*
341  * Clear and init the buffers
342  */
343  floatBuf.clear();
344  shortBuf.clear();
345  int curShortBufOffset = 0;
346  int curFloatBufOffset = 0;
347 
351  float[][] v = gData.getVertices();
352  _vertex_off = new int[v.length];
353  for (int i = 0; i < v.length; i++) {
354  _vertex_off[i] = curFloatBufOffset;
355  floatBuf.put(v[i]);
356  curFloatBufOffset += v[i].length;
357  Log.d("OpenGLBase", "FloatBuffer: Added " + v[i].length + " float values for " + gData.getNumVertices()
358  + " vertices in set " + (i + 1) + ". Fill state: " + getFloatFillState(curFloatBufOffset));
359  }
360 
364  _faces_off = curShortBufOffset;
365  shortBuf.put(gData.faces);
366  curShortBufOffset += gData.faces.length;
367  Log.d("OpenGLBase", "ShortBuffer: Added " + gData.faces.length + " short values for " + gData.numFaces
368  + " element faces. Fill state: " + getShortFillState(curShortBufOffset));
369 
373  _indexwf_off = curShortBufOffset;
374  shortBuf.put(gData.faceWireframe);
375  curShortBufOffset += gData.faceWireframe.length;
376  Log.d("OpenGLBase", "ShortBuffer: Added " + gData.faceWireframe.length
377  + " short values for faces wireframe. Fill state: " + getShortFillState(curShortBufOffset));
378 
384  _color_off = new int[vData.getNumVisFeatures()];
385  names = new String[_color_off.length];
386  for (int i = 0; i < vData.getNumVisFeatures(); i++) {
387  _color_off[i] = curFloatBufOffset;
388  VisualFeature vf = vData.getVisualizationFeature(i);
389  float[] col = vf.Colors;
390  names[i] = vf.Name;
391  if (vf.Source != null && vf.Source.descriptor.Mapping == FieldMapping.ELEMENT) {
392  col = elementToVertexColors(col);
393  }
394  floatBuf.put(col);
395  curFloatBufOffset += col.length;
396  Log.d("OpenGLBase", "FloatBuffer: Added " + col.length + " floats for color field '" + vf.Name + "' ("
397  + (i + 1) + "). Fill state: " + getFloatFillState(curFloatBufOffset));
398  }
399 
400  // Init array for 3D object
401  if (!gData.is2D()) {
402  _normal_off = new int[gData.normal.length];
403  for (int i = 0; i < _normal_off.length; i++) {
404  _normal_off[i] = curFloatBufOffset;
405  floatBuf.put(gData.normal[i]);
406  curFloatBufOffset += gData.normal[i].length;
407  Log.d("OpenGLBase", "FloatBuffer: Added " + gData.normal[i].length
408  + " floats for 3D normal data. Fill state: " + getFloatFillState(curFloatBufOffset));
409  }
410  }
411  }
412 
413  public boolean is2D() {
414  return vData.getGeometryData().is2D();
415  }
416 
417  // public boolean isPaused() {
418  // return ispaused;
419  // }
420 
424  public void nextColorField() {
425  currentColorField++;
426  currentColorField %= vData.getNumVisFeatures();
427  Log.d("OpenGLBase", "Next color field '" + names[currentColorField] + "' (" + (currentColorField + 1) + "/"
428  + _color_off.length + ")");
429  }
430 
434  public void prevColorField() {
435  if (--currentColorField == -1)
436  currentColorField = vData.getNumVisFeatures() - 1;
437  Log.d("OpenGLBase", "Previous color field '" + names[currentColorField] + "' (" + (currentColorField + 1) + "/"
438  + _color_off.length + ")");
439  }
440 
444  public void togglePause() {
445  ispaused = !ispaused;
446  }
447 
453  public void setOrientation(Orientation o) {
454  Log.d("OpenGLBase", "set orientation:" + o.toString());
455  orientation = o;
456  updateOrthographicProjection();
457  }
458 
459  // /**
460  // * @param pzoom
461  // */
462  // public void zoom(float pzoom) {
463  // pzoom = (pzoom < 1) ? 1 : pzoom;
464  // scaleFactor = pzoom;
465  // }
466 
470  public void zoomIn() {
471  scaleFactor *= 1.1f;
472  }
473 
477  public void zoomOut() {
478  scaleFactor = Math.max(scaleFactor * 0.9f, 0.15f);
479  }
480 }
void initRendering()
Initializes the rendering process (Vertex, face, color and normal openGL buffers) ...
FieldMapping Mapping
Unused so far, as mixed field mappings are not yet implemented.
void setSize(int width, int height)
void setOrientation(Orientation o)
Sets the current orientation.
static final float FRAME_INCREASE
Definition: OpenGLBase.java:25
void prevColorField()
Shows the next color field, if available.
boolean isFrontFace
Flag that indicates whether the front face should be rendered or not.
Definition: OpenGLBase.java:76
boolean isContinuousRotation
Flag that indicates whether the object rotates continuously in the 3D case.
Definition: OpenGLBase.java:71
Simple class for feature that can be visualized.
void nextColorField()
Shows the next color field, if available.
LogicSolutionField Source
ELEMENT
The field variables are to be mapped to geometry elements, e.g.
A container class for all model visual data.
void togglePause()
pause the animation if there is any
The field mapping determines how the DoF of the solution are mapped into the given geometry...
Provides a Log class imitating the Android Log class when not used on android systems.
Definition: Log.java:11
OpenGLBase(VisualizationData vData)
Creates an OpenGLBase with the default size.
Extracted the Camera class from GLRenderer.
Definition: Camera.java:11
This is a container class for all geometry-related data of a reduced model.
void addPos(float posx, float posy)
OpenGLBase(VisualizationData vData, int width, int height)
Base class for OpenGL visualisation.
Definition: OpenGLBase.java:18
void zoomOut()
zoom out
void resetView()
Sets the initial position away from the model in the y-direction looking toward the center of the mod...