Sophie

Sophie

distrib > Mandriva > 2007.0 > i586 > media > contrib-release > by-pkgid > 72ca020c3e58903e15410e6277d9d7a5 > files > 75

hackwhite_dune-0.29-0.beta421.1mdv2007.0.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" 
   "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html> 
<head>
 <title>White_dune developer documentation</title> 
</head> 
<body>
<h1>White_dune developer documentation</h1>
<h2>"white_dune", what's that ?</h2> 
<p>
"white_dune" is a continuation of the "dune" project by Stephan F. White.<br>
"dune" is a graphical VRML97 Editor, simple NURBS modeller and animation 
tool with some OpenGL scene rendering capabilities.
</p>
<h2>white_dune program overview</h2>
<p>
In princple, the structure of the white_dune program can be written as:
<ol>
 <li> 
  evaluate commandline parameters
 </li>
 <li>
  enter GUI (Grapical User Interface) mainloop
 </li>
</ol>
For details, see the file <b>main.cpp</b>
</p>
<h2>white_dune GUI overview</h2>
<p>
The GUI of white_dune consists of 2 parts:
<ol>
 <li>
  2D GUI<br>
  This handles two dimensional operations like opening windows,
  display icons, menus, buttons etc.<br>
  2D GUI operations are seperated in a extra programming level,
  called swt (Stephan White Toolkit).<br>
  Currently, there are two different implementations of swt written in C,
  one for Motif/Lesstif (Unix/Linux) and one for Win32 (M$Windows).<br>
  For details, see the directory <b>swt</b>.
  swt use M$Windows rc files. For details about the implementation 
  on M$Windows machines see the directory <b>swt/rc</b>.<br>
 </li>
 <li>3D GUI<br>
  This handles three dimensional operations. This is displaying 3D data
  (rendering, implemented in OpenGL) and manipulating 3D Objects.<br>
  Some 3D operations, like mouseinput and reaction to desktop events
  (e.g. resize of Windows) are handled in connection with the 2D GUI
  (see the file <b>Scene3DView.cpp</b> for details).<br>
  Additional, there are other sources of information for manipulating 
  3D Objects (also handled in <b>Scene3DView.cpp</b>): input from
  devices like joystick, dialbox or spaceball. Code for input
  from this devices is located in the file <b>InputDevice.cpp</b>.
 </li>
</ol>
</p>
<p>
The 2D GUI mainloop of white_dune is event driven. Typical events are
mouse-movement, mouse-click, resize of window and so on.<br>
Additionally the mainloop can produce timer events.<br>
When a event occures, the matching callback function is started.
The callbacks work for every subwindow of white_dune.<br>
The following image shows the subwindows (red text) of the mainwindow.<br>
<center>
<img src=dune.png alt="subwindows of the mainwindow" align="top">
</center><br>
Some 2D GUI events are distributed to the different subwindows.
The distribution of this events is based on inheritance.<br>
The class <b>SceneView</b> define inheritable 2D GUI callbacks like 
<i>OnMouseMove</i> and is parent class to the classes 
<b>ChannelView</b>, <b>FieldView</b>, <b>Scene3DView</b>, 
<b>SceneGraphView</b>, <b>SceneTreeView</b>, <b>StatusBar</b>,
<b>ToolbarWindow</b> and <b>PanedWindow</b>. <b>PanedWindow</b> is 
parent class to the class <b>MainWindow</b>.
</p> 
<p>
A additional callback <i>OnUpdate</i> is used to distribute 
messages like <i>UPDATE_FIELD</i> or <i>UPDATE_ADD_NODE</i> to the 
child classes of <b>SceneView</b>. <i>OnUpdate</i> is started by
the function <i>UpdateViews</i> of class <b>Scene</b>.<br>
</p> 
<p>
Some operations require additional input of data. Then a "Dialog" 
is opened, that block the data input to all other windows.<br>
<center>
<img src=dialog.jpg alt="a example of a dialog" align="top">
</center><br>
*Dialog classes are all inheritable from the class <b>Dialog</b>,
which implements functions like SaveData() and Validate().<br>
The layout of Dialogs (as well as the layout of the menues) is defined 
in the dune*.rc files.
</p>
<h2> VRML implementation overview</h2>
<p>
The class <b>Scene</b> (Scene.h/cpp) can be identified with one VRML file. 
For example Scene.write() writes the VRML file to disk.
</p> 
<p>
The global variable <i>TheApp</i> of class <b>DuneApp</b> (DuneApp.h/cpp)
can be identified with things that are global to all VRML files.
</p>
<p>
The internals of each VRML Nodes are implemented in the files named
Node<b>NodeName</b> (for example Node<b>Transform</b> (NodeTransform.h/cpp), 
Node<b>Shape</b> (NodeShape.h/cpp) or Node<b>Box</b> (NodeBox.h/cpp)).
</p>
<p>
Every Node<b>NodeName</b>.h file contain 2 classes: the 
class Node<b>NodeName</b> which contain functionality 
like draw() for 3D rendering of shapes and the class
Proto<b>NodeName</b> which are used to build the definitions
of the VRML97 standard.<br>
For example, the definiton of the Transform Node in
the ISO/IEC 14772 standard <br>
<img src=standard.jpg alt="example from vrml standard" align="top"><br>
is implemented in the constructor of the class Proto<b>Transform</b>
(in file NodeTransform.cpp):<br>
<pre>
ProtoTransform::ProtoTransform(Scene *scene)
  : Proto(scene, "Transform")
{
    addEventIn(MFNODE, "addChildren");
    addEventIn(MFNODE, "removeChildren");
    center.set(addExposedField(SFVEC3F, "center", new SFVec3f(0.0f, 0.0f, 0.0f)));
    children.set (addExposedField(MFNODE, "children", new MFNode(), CHILD_NODE));
    rotation.set(addExposedField(SFROTATION, "rotation", new SFRotation(0.0f, 0.0f, 1.0f, 0.0f)));
    scale.set(addExposedField(SFVEC3F, "scale", new SFVec3f(1.0f, 1.0f, 1.0f), new SFFloat(0.0f)));
    scaleOrientation.set(addExposedField(SFROTATION, "scaleOrientation",new SFRotation(0.0f, 0.0f, 1.0f, 0.0f)));
    translation.set(addExposedField(SFVEC3F, "translation", new SFVec3f(0.0f, 0.0f, 0.0f)));
    bboxCenter.set(addField(SFVEC3F, "bboxCenter", new SFVec3f(0, 0, 0)));
    bboxSize.set(addField(SFVEC3F, "bboxSize", new SFVec3f(-1, -1, -1), new SFFloat(-1.0f)));
}
</pre>
Different fields are internally handled as integer values.<br>
The variables center, children, rotation, scale, scaleOrientation, translation,
bboxCenter and bboxSize are of type "fieldIndex", something like a readonly
integer, that can be only set once.<br>
There are NodeTransform memberfunctions to get and set field values.
For example, the memberfunctions for the field "center" of class 
"NodeTransform" are:<br><br>
<table border=0 cellpadding=0 cellspacing=0>
<tr><td nowrap align=right valign=top><a href="doxygen_out_html/html/classSFVec3f.html">SFVec3f</a> *&nbsp;</td><td valign=bottom><a  href="doxygen_out_html/html/classNodeTransform.html#a17">center</a> (void)</td></tr>
<tr><td nowrap align=right valign=top>void&nbsp;</td><td valign=bottom><a  href="doxygen_out_html/html/classNodeTransform.html#a18">center</a> (<a  href="doxygen_out_html/html/classSFVec3f.html">SFVec3f</a> *value)</td></tr>
<tr><td nowrap align=right valign=top>void&nbsp;</td><td valign=bottom><a  href="doxygen_out_html/html/classNodeTransform.html#a19">center</a> (<a  href="doxygen_out_html/html/classSFVec3f.html">SFVec3f</a> &amp;value)</td></tr>
<tr><td nowrap align=right valign=top>int&nbsp;</td><td valign=bottom><a  href="doxygen_out_html/html/classNodeTransform.html#a20">center_Field</a> (void)</td></tr>
</table>
<br>
The memberfunctions "something_Field()" deliver the integer number of a field 
that is needed for example for a 
<a href="doxygen_out_html/html/classMoveCommand.html#a0">
MoveCommand</a> to move nodes in the scenegraph.
</p>
<p>
Functionality common to all Nodes (like writing a Node to a file (Node.write())
is in the class Node (file Node.h/cpp). All Node<b>NodeName</b> classes are
subclasses of the class Node.<br>
Some of the memberfunctions of the class Node are virtual and can be
overwritten by the Node<b>NodeName</b> classes (for example, the
class NodeScript need a special version of Node.write()).<br>
Here is a list of important virtual Node memberfunctions:
<ul>
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a17>getType()</a></b><br>
      deliver a <a href=doxygen_out_html/html/Node_8h.html#a83>
      value</a> needed to identify different nodes. For example,
      the transform node deliver DUNE_TRANSFORM.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a2>write</a></b><br>
      write the node to a VRML file.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a30>update</a></b><br>
      update a node after a field change.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a63>setHandle</a></b><br>
      change a node field from handles (e.g. white boxes in the Scene3DView, 
      that can be moved around with the mouse).
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a62>getHandle</a></b><br>
      get the value of a handle.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a61>drawHandles</a></b><br>
      draw the handle in the Scene3DView.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a55>preDraw</a></b><br>
      do operations that prepare the drawing of nodes in the Scene3DView.
  <li><b><a href=doxygen_out_html/html/classNodeData.html#a58>draw</a></b><br>
      drawing the nodes in the Scene3DView (and internally to find
      mouse hits).      
</ul>
Some geometry nodes (like ElevationGrid) are implemented as a subclass of
<b>MeshBasedNode</b>. The MeshBasedNode class is used for geometry that
can implemented as a IndexedFaceSet type of mesh. The MeshBasedNode class 
provides important virtual Node memberfunctions like <b>draw</b>.
The creation of the mesh in a MeshBasedNode is done via the virtual
function <b>createMesh</b>.<br>
Some geometry nodes (like NodeSuperShape) are implemented as a subclass
of <b>MeshMorphingNode</b> which is a subclass of MeshBasedNode by itself.
A MeshMorphingNode can write a morphing animation of a IndexedFaceSet,
when "File-&gt;Export As...-&gt;Export as &Pure VRML97..." or
"File-&gt;Export As...-&gt;Export as VRML level &X3DV..." is used.
</p>
<h2>VRML97 parser</h2>
<p>
Dune need to read and parse ("understand") VRML97 files.<br>
This is done with using the tools lex/yacc (it looks like, the advanced 
tools flex and bison from the GNU project are needed). <br>
The file lexer.l do the lexical analysis (detect things like "what is
a string", "what is a number", "what is that VRML97 keyword").<br>
The file parser.y do the grammatical analysis (detect and prove, if the
tokens found by the lexical analysis form valid VRML contructions 
(like Node or ROUTE statements). If some tokens of the grammar are valid,
the action part of the command in the parser.y file create the matching
VRML Nodes, Numbers etc.
</p>
<h2>Dangerous constructs</h2>
<p>
The buildin stringtype ("MyString") can be misleading, it act very
pointerlike. For example be carefull about constructs like the following:
<br>
<pre>
  MyString str = node->getProto()->getName();
  str += "something"; 
</pre>
This do not only copy the name of a Proto of "node" to str and append
"something" to it, it also appends "something" to the name of a Proto !
<p>
</p>
In this situation, it is better to use something like
<pre>
  MyString str = strdup(node->getProto()->getName());
  str += "something"; 
</pre>
or
<pre>
  MyString str = "";
  str += node->getProto()->getName();
  str += "something"; 
</pre>
</p>
<h2>"Adding a new (scripted) geometry node to white_dune"-cookbook</h2>
<p>
<ul>
<li>Select a name of the new node (here "Something")
<br><br>
<li> add a ID_NEW_SOMETHING to resource.h.m4, usually via adding a new m4 macro
     M4_ID(SOMETHING) 
<br><br>
<li> Add
<br><pre> 
  MENUITEM "Something",                  ID_NEW_SOMETHING
</pre>
  under
<br><pre>  
  POPUP "Scripted PROTOs (slow)"
       BEGIN
</pre>
  and
<br><pre> 
      ID_NEW_SOMETHING      "Create a new Something Scripted PROTO\nSomething Scripted"
</pre>
  to all src/dune.*.rc files. See <a href="#localisation">the chapter about 
  localisation</a> for more informations about handling the needed language 
  translations.
<br><br>
<li>
  add a DUNE_SOMETHING to the matching place (sorted by the alphabet) to
  the matching enum in Node.h
<br><br>
<li> add a
<br><pre>
  _protos["Something"] = new ProtoSomething(this);
</pre>
  in a matching place (sorted by the alphabet of the DUNE_SOMETHING in the 
  list in Node.h) in Scene::Scene() and add
<br><pre>
  #include "NodeSomething.h"
</pre>
  to Scene.cpp
<br><br>
<li> copy a similar Node*.h/cpp to NodeSomething.h/cpp and change
  the fields/EventIns and draw, setHandle etc. functions.<br>
  Do not forget the getType() function.
<br><br>
<li> add a
<br><pre>
  DUNE_SOMETHING,       ID_NEW_SOMETHING,
</pre>
  to
<br><pre>
  static int buttonsScripted[] = {
</pre>
  in Windows.cpp
<br><br>
<li>Use gimp to include a new icon (16 pixels width) of your node 
     (nodenames need to be sorted by the alphabet) into res/node_icons.bmp
     (or res_color/node_icons.bmp for UNIX type compilation with configure)
     <br><br>
  Warning: DO NOT change the numbers of colors in this bitmap file !
     <br><br>
  When you have gimp version 1.2 installed as "gimp", you can 
  use the script "batch/inserticon.sh" under Linux/UNIX/MacOSX by typing
<BR><pre>
         sh batch/inserticon.sh DUNE_SOMETHING
</pre>
  gimp will then open and select the matching node icons that has to be
  moved 16 pixels to left. Use "edit->cut" and "edit->paste" then move
  the icons to the left border of the gimp window. Draw your new icon
  in the new 16 pixels wide white gap.   
<br><br>
<li> add a
<BR><pre>
        case ID_NEW_SOMETHING:
        CreateGeometryNode("Something");
        break;
</pre>
  to MainWindow::OnCommand(int id) in MainWindow.cpp
<br><br>
<li> A scripted node makes only sense with a VRML97 PROTO statement.
     Put your PROTO into the docs/scriptedNodes directory. 
<br><br>
<li> add the name of your NodeSomething.cpp file into the matching place
     in the src/Makefile.in file and to the M$Windows project.
<br><br>
<li> Do not forget the GPL license, which forces you to public somehow
     the complete sources, if you want to redistribute a modified version 
     of white_dune...
</ul>
The Implementation of a regular new (eg. X3D) Node is similar.
</p>
<h2><a name="localisation">Localisation: translating the program to foreign 
    languages</a></h2>
<p>
It requires absolute no programming skills to translate the program to a 
foreign language, if the foreign languages uses ASCII characters:<br>
you only need to copy the file "src/dune.english.rc" into a similar file,
use a texteditor with search and replace und at end translate the strings
in this file to the foreign language.<br>
</p>
<p>
The problems when trying to translate the program to a foreign
language with non ASCII characters (like chinease UTF8 characters) are
untested/unknown.
</p>
<p>
To complete the task to create a new runnable program a compatible compiler
is needed. Of course, this task can be done (after publicing the main
translation file src/dune.something.rc) by a programmer later, it do not need to 
be done by the translator.<br>
All "src/dune.*.rc" files are copied together into one src/dune.rc file during the 
run of "configure" and "make".<br>
This means, that for creating a new runnable program, you need either a 
UNIX like system (e.g. Linux or MacOSX) or a bunch of unixtools:<br>
m4, make, cat, grep and sh (e.g. bash or ksh).<br>
A complete free/opensource installable collection of unixtools for M$Windows 
is called cygwin and is available for free from the internet.<br>
</p>
<p>
For Translaton, first search the ISO 3166 two characters of your language
(e.g. "en" for english, "de" for german, "it" for italian, etc...)
and build the uppercase version of this characters (e.g. EN for english,
DE for german, IT for italian, etc).
</p>
<p>
Second, select a src/dune.something.rc file. In the simpler case, do not select
"src/dune.english.rc" cause this requires more complicated search and replace
commands.<br>
<ul>
 <li>
  In case of translating "src/dune.english.rc", you have to replace the following
  characters in the whole file:<br>
  <ul>
   <li>IDR_ with IDR_DE_ for german, IDR_ with IDR_IT_ for italian etc</li>
   <li>IDD_ with IDD_DE_ for german, IDD_ with IDD_IT_ for italian etc</li>
   <li>IDS_ with IDS_DE_ for german, IDS_ with IDS_IT_ for italian etc</li>
  </ul>
  Now search for the first occurance of STRINGTABLE DISCARDABLE in 
  src/dune.english.rc and replace (starting at this point)<br>
  <ul>
   <li>ID_ with ID_DE_ for german, ID_ with ID_IT_ for italian etc</li>
  </ul>
 </li>
 <li>
  In case of translating a other "src/dune.*.rc" than "src/dune.english.rc", you 
  simply have to replace the term _??_ in the whole file, where ?? marks
  the uppercase ISO 3166 two characters. E.g. if you translate 
  "src/dune.german.rc" to "src/dune.italian.rc", you have to replace _DE_ with
  _IT_ in the whole file, thats all.
 </li>
</ul>
</p>
<p>
Third you need to translate all the strings in the new src/dune.something.rc file.
A so called string is a term that starts with a " and ends with a "<br>
For example, the translation of the line from src/dune.english.rc
<BR><pre>
    POPUP "&File"
</pre>
to german language in src/dune.german.rc would result in
<BR><pre>
    POPUP "&Datei"
</pre>
where the german word Datei is the translation of the english word File.
The "&" sign marks the keyboard shortcut. The next character after "&"
should not be ambient in the same level of a menu.
</p>
<p>
After the translation of the strings is ready, the translation step is
ready. On a Linux/UNIX/MacOSX/cygwin system with the gawk (GNU awk) program 
you can use 
<BR><pre>
sh test/testmenus.sh
</pre>
one the commandline to use some consistency testing of the new rc file.
</p>
<p>
The new file src/dune.something.rc can be now publiced (e.g. in a usenet
group like comp.lang.vrml, or at 
<a href="http://sourceforge.net/tracker/?group_id=3356&atid=103356">the 
sourceforge site for the original dune project</a>).
</p>
<p>
For a recompilation, you first need to extend the list of lanugages, 
white_dune understands.<br>
Currently you need to extend the list of known languages in the file
src/languages.m4. E.g. to extend the list of known languages from 
english (empty default) and german (DE) in src/languages.m4
<BR><pre>
define(`M4_LANGUAGES_CONFIG',`
DE,german')
</pre>
to english, italian (IT) and german, then change the list to
<BR><pre>
define(`M4_LANGUAGES_CONFIG',`
IT,italian,
DE,german')
</pre>
or extent to english, italian and spanish (ES) and german, then change the list
to
<BR><pre>
define(`M4_LANGUAGES_CONFIG',`
IT,italian,
ES,spanish,
DE,german')
</pre>
Take care that the last language line (here with "DE,german") do not end
with a comma.
</p>
<p>
The final step is rebuilding the needed files for compilation. On a 
Linux/UNIX/MacOSX/cygwin system, this is done automatically by using 
"sh build.sh"<br>
(or "configure && make").<br>
On other systems, at least a text editor and a port of the m4 program is 
required.<br>
With the texteditor, copy all dune.*.rc files together and store the
result in the file "dune.rc"<br>
With m4 you need to execute the following commands in the src directory:<br>
<br>
m4 resource.h.m4 &gt; resource.h<br>
m4 CommandlineLanguages.h.m4 &gt; CommandlineLanguages.h<br>
</p>
<p>
After recompilation (see the file INSTALL for details), the new language can 
be used with a commandline parameter.
The name of the new commandline parameter is the minus sign followed by
the second word in the new line in M4_LANGUAGES_CONFIG.<br>
E.g. if you added "IT,italian," to M4_LANGUAGES_CONFIG, the new commandline
parameter to switch to the italien language is -italien
</p>
<p>
All that have to be done now is to add the new commandline parameter to the 
documentation in the manpage file man/dune.1
</p>
<h2>Localisation from a programmers point of view</a></h2>
<p>
When handling text messages from a programmers point of view, always try to 
use the function "swLoadString" to get a language related string (e.g. for a 
errormessage) from the "src/dune.rc" file. The first argument of the 
swLoadString file is a identifier, like IDS_INTERNAL_ERROR, which refers to 
the message in the default (english) language. To get the current language 
translation, add the term TheApp->getLang() to the idenifier, e.g . with 
swLoadString(IDS_INTERNAL_ERROR + TheApp->getLang(),...
</p>
<p>
As a programmer, take care about the fact, that each program code 
modification (e.g. addition of new menu items) in one of the 
src/dune.something.rc 
files requires the change of a all other "src/dune.somelanguage.rc" files.<br>
Cause a programmer is usually not a multilingual genius, the addition of
a new menuitem, icon tooltip or errormessage comes with a translation 
problem. There are two possible solutions: either use a dictionary/internet 
translation service like babelfish.altavista.com, or leave the english 
word in the src/dune.something.rc file and hope for modification by users.<br>
To leave the line blank cause of a unknown foreign word is not a option,
cause this can result in a crash of the program when used in this foreign
language.<br>
The addition of a new icon tooltip or errormessage also requires the
inclusion of a new "#define" command which can be usually found in the 
resource.h file.<br>
Do not change the resource.h file directly. The file resource.h is a 
autogenerated file, that could be overwritten at each run of the "make" 
command or "configure" command.<br>
</p>
<h2> class overview</h2>
<p>
The name of most sourcefiles in the "src" directory is identical 
to the name of the major contained class.
</p>
<p>
The following class/filenames have special meanings:
<ul>
  <li>
     <b>Node</b>SomeNodeName:<br>
        Implement details for the VRML Node "SomeNodeName"  
  </li>
  <li>
     Something<b>Dialog</b>, Something<b>Window</b>, Something<b>View</b>:<br>
        Implement details for the graphical user interface (GUI) 
  </li>
  <li>
     Something<b>App</b>:<br>
        Implement details for data global to the whole application
  </li>
  <li>
     Something<b>Command</b>:<br>
        Implement details for sending internal commands 
  </li>
  <li>
     <b>SF</b>Something, <b>MF</b>Something:<br>
        Implement details for VRML datatypes
  </li>
</ul>
</p>
<p>
If <a href=http://www.stack.nl/~dimitri/doxygen>doxygen</a>
is installed, a class hierarchy of white_dune can be produced by typing <br>
<br>
<pre>
         make documentation
</pre>
and can then be found <a href=doxygen_out_html/html/hierarchy.html>here</a>.
</p>
</body>