lib/SmallChange/nodekits/SmAnnotationAxis.cpp

Tue Dec 13 15:35:52 2011 +0100

author
Tarjei Kvamme <tarjei.loset.kvamme@kongsberg.com>
date
Tue Dec 13 15:35:52 2011 +0100
changeset 1048
92bf2633a0df
parent 1011
239e70af5d84
permissions
-rw-r--r--

SIMRESERVOIR-3849: Use textMaterial to color the text when using an SmTextureText2Collector, as is done otherwise.

     1 /**************************************************************************\
     2  *
     3  *  This file is part of the SmallChange extension library for Coin.
     4  *  Copyright (C) 1998-2003 by Systems in Motion.  All rights reserved.
     5  *
     6  *  This library is free software; you can redistribute it and/or
     7  *  modify it under the terms of the GNU General Public License
     8  *  ("GPL") version 2 as published by the Free Software Foundation.
     9  *  See the file LICENSE.GPL at the root directory of this source
    10  *  distribution for additional information about the GNU GPL.
    11  *
    12  *  For using SmallChange with software that can not be combined with the
    13  *  GNU GPL, and for taking advantage of the additional benefits of our
    14  *  support services, please contact Systems in Motion about acquiring
    15  *  a Coin Professional Edition License.
    16  *
    17  *  See <URL:http://www.coin3d.org> for  more information.
    18  *
    19  *  Systems in Motion, Teknobyen, Abels Gate 5, 7030 Trondheim, NORWAY.
    20  *  <URL:http://www.sim.no>.
    21  *
    22 \**************************************************************************/
    24 #include "SmAnnotationAxis.h"
    25 #include <Inventor/nodes/SoSeparator.h>
    26 #include <Inventor/elements/SoModelMatrixElement.h>
    27 #include <Inventor/elements/SoProjectionMatrixElement.h>
    28 #include <Inventor/elements/SoViewingMatrixElement.h>
    29 #include <Inventor/elements/SoCacheElement.h>
    30 #include <Inventor/elements/SoViewportRegionElement.h>
    31 #include <Inventor/elements/SoViewVolumeElement.h>
    32 #include <Inventor/elements/SoCullElement.h>
    33 #include <Inventor/actions/SoGLRenderAction.h>
    34 #include <Inventor/actions/SoGetBoundingBoxAction.h>
    35 #include <Inventor/nodes/SoSwitch.h>
    36 #include <Inventor/nodes/SoInfo.h>
    37 #include <Inventor/nodes/SoMaterial.h>
    38 #include <Inventor/nodes/SoLineSet.h>
    39 #include <Inventor/nodes/SoSeparator.h>
    40 #include <Inventor/nodes/SoVertexProperty.h>
    41 #include <Inventor/SbTime.h>
    42 #include <Inventor/sensors/SoAlarmSensor.h>
    43 #include <Inventor/sensors/SoOneShotSensor.h>
    44 #include <SmallChange/nodes/SmTextureText2.h>
    45 #include <SmallChange/nodes/SmTextureText2Collector.h>
    46 #include <cstring>
    48 // *************************************************************************
    50 SO_KIT_SOURCE(SmAnnotationAxis);
    52 // *************************************************************************
    54 class SmAnnotationAxisP {
    56 public:
    57   SmAnnotationAxisP(SmAnnotationAxis * master) {
    58     this->master = master;
    59   }
    61   SmAnnotationAxis * master;
    62   SbList <int> axisidx;
    63   SoOneShotSensor * regen_sensor;
    65   void add_anno_text(const int level,
    66                      SbList <int> & list,
    67                      const SbMatrix & projm, 
    68                      const SbVec2s & vpsize,
    69 		     const float gap,
    70                      const SbVec3f * pos, int i0, int i1);
    72   SbTime lastchanged;
    73   SoAlarmSensor * alarm;
    75   static void alarmCB(void * closure, SoSensor * s) {
    76     SmAnnotationAxisP * thisp = (SmAnnotationAxisP*) closure;
    77     thisp->master->touch();
    78   }
    79 };
    81 #define PRIVATE(p) ((p)->pimpl)
    82 #define PUBLIC(p) ((p)->master)
    84 // *************************************************************************
    86 SmAnnotationAxis::SmAnnotationAxis()
    87 {
    88   PRIVATE(this) = new SmAnnotationAxisP(this);
    89   PRIVATE(this)->regen_sensor = NULL;
    90   PRIVATE(this)->alarm = new SoAlarmSensor(SmAnnotationAxisP::alarmCB, PRIVATE(this));
    91   PRIVATE(this)->lastchanged = SbTime::zero();
    93   SO_KIT_CONSTRUCTOR(SmAnnotationAxis);
    94   SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
    95   SO_KIT_ADD_CATALOG_ENTRY(textMaterial, SoMaterial, FALSE, topSeparator, text, TRUE);
    96   SO_KIT_ADD_CATALOG_ENTRY(text, SmTextureText2, FALSE, topSeparator, axisSwitch, TRUE);
    97   SO_KIT_ADD_CATALOG_ENTRY(axisSwitch, SoSwitch, FALSE, topSeparator, "", FALSE);
    98   SO_KIT_ADD_CATALOG_ENTRY(noAxis, SoInfo, FALSE, axisSwitch, axisSep, FALSE);
    99   SO_KIT_ADD_CATALOG_ENTRY(axisSep, SoSeparator, FALSE, axisSwitch, "", FALSE);
   100   SO_KIT_ADD_CATALOG_ENTRY(axisMaterial, SoMaterial, FALSE, axisSep, axisLineSet, TRUE);
   101   SO_KIT_ADD_CATALOG_ENTRY(axisLineSet, SoLineSet, FALSE, axisSep, "", FALSE);
   103   SO_KIT_ADD_FIELD(annotation, (""));
   104   SO_KIT_ADD_FIELD(annotationPos, (0.0f, 0.0f, 0.0f));
   105   SO_KIT_ADD_FIELD(annotationGap, (30.0f));
   106   SO_KIT_ADD_FIELD(renderAxis, (FALSE));
   107   SO_KIT_ADD_FIELD(axisTickSize, (0.0f, 0.0f, 0.0f));
   108   SO_KIT_ADD_FIELD(annotationOffset, (0.0f, 0.0f, 0.0f));
   109   SO_KIT_ADD_FIELD(annotationRot, (0.0f));
   111   this->annotation.setNum(0);
   112   this->annotationPos.setNum(0);
   113   this->annotation.setDefault(TRUE);
   114   this->annotationPos.setDefault(TRUE);
   116   SO_KIT_INIT_INSTANCE();
   118   SoSwitch * sw = static_cast<SoSwitch*>(this->getAnyPart("axisSwitch", TRUE));
   119   sw->whichChild.connectFrom(&this->renderAxis);
   121   SmTextureText2 * t = static_cast<SmTextureText2*>(this->getAnyPart("text", TRUE));
   122   t->justification = SmTextureText2::CENTER;
   123   t->rotation.connectFrom(&this->annotationRot);
   125   PRIVATE(this)->regen_sensor = new SoOneShotSensor(regen_geometry, this);
   126 }
   128 SmAnnotationAxis::~SmAnnotationAxis()
   129 {
   130   delete PRIVATE(this)->alarm;
   131   delete PRIVATE(this)->regen_sensor;
   132   delete PRIVATE(this);
   133 }
   135 void
   136 SmAnnotationAxis::initClass(void)
   137 {
   138   SO_KIT_INIT_CLASS(SmAnnotationAxis, SoBaseKit, "BaseKit");
   139 }
   141 void 
   142 SmAnnotationAxis::getBoundingBox(SoGetBoundingBoxAction * action)
   143 {
   144   SoState * state = action->getState();
   146   // supply an approximate bbox and always invalidate the bbox cache
   147   SoCacheElement::invalidate(state);
   149   SbBox3f bbox;
   150   bbox.makeEmpty();
   151   for (int i = 0; i < this->annotationPos.getNum(); i++) {
   152     bbox.extendBy(this->annotationPos[i]);
   153   }
   155   if (!bbox.isEmpty()) {
   156     action->extendBy(bbox);
   157     action->setCenter(bbox.getCenter(), TRUE);
   158   }
   159   inherited::getBoundingBox(action);
   160 }
   162 void 
   163 SmAnnotationAxis::GLRender(SoGLRenderAction * action)
   164 {
   165   SoState * state = action->getState();
   167   SbBool render = TRUE;
   169   // don't create render caches for this node
   170   SoCacheElement::invalidate(state);
   172   SbMatrix projmatrix;
   173   projmatrix = (SoModelMatrixElement::get(state) *
   174                 SoViewingMatrixElement::get(state) *
   175                 SoProjectionMatrixElement::get(state));
   177   SbVec2s vpsize = SoViewportRegionElement::get(state).getViewportSizePixels();
   178   const SbViewVolume & vv = SoViewVolumeElement::get(state);
   179   float maxsize = SbMax(vpsize[0], vpsize[1]);
   181   SbList <int> l1;
   182   if (this->annotationPos.getNum() >= 2) {
   183     l1.truncate(0);
   184     PRIVATE(this)->add_anno_text(0, l1, projmatrix,
   185 				 vpsize,
   186                                  this->annotationGap.getValue(),
   187                                  this->annotationPos.getValues(0), 
   188                                  0, this->annotationPos.getNum() - 1); 
   190   }
   191   if (SmTextureText2CollectorElement::isCollecting(state)) {
   192     if (this->annotation.getNum()) {
   193       SoMaterial * material = static_cast<SoMaterial*>(this->getAnyPart("textMaterial", TRUE));
   194       SmTextureText2 * text = static_cast<SmTextureText2*>(this->getAnyPart("text", TRUE));
   195       SbMatrix modelmatrix = SoModelMatrixElement::get(state);
   196       SbVec3f pos;
   197       SbColor4f col(material->diffuseColor[0], 1.0f - material->transparency[0]);
   199       for (int i = 0; i < l1.getLength(); i++) {
   200         pos = this->annotationPos[l1[i]] + this->annotationOffset.getValue();
   201         modelmatrix.multVecMatrix(pos, pos);
   203         SmTextureText2CollectorElement::add(state,
   204                                             this->annotation.getValues(0)[l1[i] % this->annotation.getNum()],
   205                                             SmTextureFontElement::get(state),
   206                                             pos,
   207                                             -1.0,
   208                                             col,
   209                                             static_cast<SmTextureText2::Justification>(text->justification.getValue()),
   210                                             static_cast<SmTextureText2::VerticalJustification>(text->verticalJustification.getValue()));
   212         if (text->string.getNum()) text->string.setNum(0);
   213       }
   214     }
   215   }
   216   else {  
   217     if (l1 != PRIVATE(this)->axisidx) {
   218       // avoid that we update the scene graph and trigger redraws too often
   219       SbTime curtime = SbTime::getTimeOfDay();
   220       if ((curtime.getValue() - PRIVATE(this)->lastchanged.getValue()) < 0.5) {
   221         if (!PRIVATE(this)->alarm->isScheduled()) {
   222           PRIVATE(this)->alarm->setTimeFromNow(1.0);
   223           PRIVATE(this)->alarm->schedule();
   224         }
   225       }
   226       else {
   227         PRIVATE(this)->lastchanged = curtime;
   228         SmTextureText2 * t = static_cast<SmTextureText2*>(this->getAnyPart("text", TRUE));
   229         assert(t);
   230         t->position.setNum(l1.getLength());
   231         t->string.setNum(l1.getLength());
   232         SbVec3f * pos = t->position.startEditing();
   233         SbString * text = t->string.startEditing();
   234         for (int i = 0; i < l1.getLength(); i++) {
   235           pos[i] = this->annotationPos[l1[i]] + this->annotationOffset.getValue();
   236           text[i] = this->annotation.getNum() > 0 ?
   237             this->annotation.getValues(0)[l1[i]%this->annotation.getNum()] : "";
   238         }
   239         t->position.finishEditing();
   240         t->string.finishEditing();
   242         PRIVATE(this)->axisidx = l1;
   243       }
   244     }
   245   }
   246   if (render) inherited::GLRender(action);
   247 }
   249 void 
   250 SmAnnotationAxis::notify(SoNotList * list)
   251 {
   252   if (PRIVATE(this)->regen_sensor) {
   253     SoField * f = list->getLastField();
   254     if ((f == &this->annotationPos) ||
   255         (f == &this->renderAxis) ||
   256         (f == &this->axisTickSize)) {
   257       PRIVATE(this)->regen_sensor->schedule();
   258     }
   259   }
   260   inherited::notify(list);
   261 }
   263 void
   264 SmAnnotationAxis::regen_geometry(void * userdata, SoSensor * s)
   265 {
   266   SmAnnotationAxis * thisp = (SmAnnotationAxis*) userdata;
   267   if (thisp->renderAxis.getValue()) {
   268     SoLineSet * ls = static_cast<SoLineSet*>(thisp->getAnyPart("axisLineSet", TRUE));
   269     SoVertexProperty * vp = static_cast<SoVertexProperty*> (ls->vertexProperty.getValue());
   270     if (vp == NULL) {
   271       vp = new SoVertexProperty;
   272       ls->vertexProperty = vp;
   273     }
   274     SbVec3f ticksize = thisp->axisTickSize.getValue();
   276     const int numanno = thisp->annotationPos.getNum();
   277     const int numlines = 1 + ((ticksize.length() > 0.0f) ? numanno : 0); 
   278     const int numcoords = numanno + ((ticksize.length() > 0.0f) ? numanno*2 : 0);
   280     vp->vertex.setNum(numcoords);
   281     ls->numVertices.setNum(numlines);
   283     const SbVec3f * src = thisp->annotationPos.getValues(0);
   284     SbVec3f * pts = vp->vertex.startEditing();
   285     int32_t * v = ls->numVertices.startEditing();
   287     v[0] = numanno;
   289     int i;
   291     for (i = 0; i < numanno; i++) {
   292       pts[i] = thisp->annotationPos[i];
   293     }
   294     if (ticksize.length() > 0.0f) {
   295       for (i = 0; i < numanno; i++) {
   296         v[i+1] = 2;
   297         pts[i*2+numanno] = src[i];
   298         pts[i*2+1+numanno] = src[i] + ticksize;
   299       }
   300     }
   302     vp->vertex.finishEditing();
   303     ls->numVertices.finishEditing();
   304   }
   305 }
   307 // *************************************************************************
   309 void 
   310 SmAnnotationAxisP::add_anno_text(const int level,
   311                                  SbList <int> & list,
   312                                  const SbMatrix & projm, 
   313 				 const SbVec2s & vpsize,
   314                                  const float gap,
   315                                  const SbVec3f * pos, int i0, int i1)
   316 {
   317   if (i0 == i1) return;
   319   int mid = (i0 + i1) / 2;
   320   SbVec3f p[3];
   321   p[0] = pos[i0];
   322   p[1] = pos[mid];
   323   p[2] = pos[i1];
   325   int i;
   326   for (i = 0; i < 3; i++) {
   327     projm.multVecMatrix(p[i], p[i]);
   328   }
   330   if (level == 0) { // special case to handle the corner points
   331     if ((p[0][2] < 1.0f) && (p[2][2] < 1.0f)) {
   332       SbVec3f d = p[2]-p[0];
   333       d[0] = SbAbs(d[0]) * float(vpsize[0]) * 0.5f;
   334       d[1] = SbAbs(d[1]) * float(vpsize[1]) * 0.5f;
   335       d[2] = 0.0f;
   337       float len = d.length();
   338       if (len > gap) {
   339         list.append(i0);
   340         list.append(i1);
   341       }
   342     }
   343     else if (p[0][2] < 1.0f) {
   344       list.append(i0);
   345     }
   346     else if (p[2][2] < 1.0f) {
   347       list.append(i1);
   348     }
   349   }
   351   if ((mid == i0) || (mid == i1)) return;
   353   if (p[1][2] < 1.0f) {
   354     SbBool add = FALSE;
   355     float len = 0.0f;
   356     if (p[0][2] < 1.0f) {
   357       SbVec3f d = p[1]-p[0];
   358       d[0] = SbAbs(d[0]) * float(vpsize[0]) * 0.5f;
   359       d[1] = SbAbs(d[1]) * float(vpsize[1]) * 0.5f;
   360       d[2] = 0.0f;
   362       len = d.length();
   363     }
   364     else if (p[2][2] < 1.0f) {
   365       SbVec3f d = p[1]-p[2];
   366       d[0] = SbAbs(d[0]) * float(vpsize[0]) * 0.5f;
   367       d[1] = SbAbs(d[1]) * float(vpsize[1]) * 0.5f;
   368       d[2] = 0.0f;
   369       len = d.length();
   370     }
   371     if (len > gap) {
   372       list.append(mid);
   373     }
   374   }
   375   add_anno_text(level+1, list, projm, vpsize, gap, pos, i0, mid);
   376   add_anno_text(level+1, list, projm, vpsize, gap, pos, mid, i1);
   377 }
   379 // *************************************************************************

Kongsberg Oil & Gas Technologies repositories