=========================
HOOPS For Java developers
=========================

Introduction
============

The HOOPS/Java integration consists of Java wrappers to HOOPS/3DGS, HOOPS/MVO, and HOOPS/Stream. This document describes how to use the HOOPS/Java integration to build a Java application that incorporates the HOOPS/3DF components. Some familiarity with Java, HOOPS/3DGS, and HOOPS/MVO is assumed. 


Platform/compiler support
=========================

The HOOPS/Java integration is supported under the J2SE Development Kit 6.0 (JDK 6.0), on the Windows 32-bit and 64-bit platforms. It is also supported on Linux platforms.


Compilation and runtime information
===================================

The following steps are required to compile and run a HOOPS/Java based application: 

**Compiling**: You must place the HOOPS/3DF and HOOPS/Java *.jar* files in your classpath. This can either be done via the command line for both compiling and running, or it can be set in the manifest file for your project. The files are:    

* *HJ<version>.jar*
* *HIJ<version>.jar*
* *HJMVO<version>.jar*
* *HJSTREAM<version>.jar*
* *HJCanvas<version>.jar*

.. raw:: html

	<strong>Executing</strong>: Ensure that the following files are in your application's directory.
		<ul>
		  <li>.jar files: <strong>(discussed above) </strong></li>
		  <li>Java wrapper libraries:     
			<ul>
			  <li>For HOOPS/3DGS:
					<ul>
						<li><strong><em>Windows</em></strong>: 
							<ul>
								<li>*hj<version>.dll*</li>
								<li>*hij<version>.dll*</li>
							</ul>
						</li>
						<li><strong><em>Linux</em></strong>:
							<ul>
								<li>*hj<version>.so*</li>
								<li>*hij<version>.so*</li>
							</ul>
					</ul>
			  </li>
			  <li>For HOOPS/MVO:	
					<ul>		
						<li><strong><em>Windows</em></strong>: *hjmvo<version>.dll*</li>
						<li><strong><em>Linux</em></strong>: *hjmvo<version>.so*</li>
					</ul>
			  </li>
			  <li>For HOOPS/Stream:
					<ul>
						<li><strong><em>Windows</em></strong>: *hjstream<version>.dll*</li> 
						<li><strong><em>Linux</em></strong>: *hjstream<version>.so*</li>
					</ul>
			  </li>
			</ul>
		  </li>
		  <li>native libraries:
			   <ul>
					<li>For HOOPS/3DGS:
						<ul>		
							<li><strong><em>Windows</em></strong>: *hoops<version>_vc<MS Visual Studio Version>.dll*</li>
							<li><strong><em>Linux</em></strong>: *hoops<version>.so*</li>
						</ul>
					<li>For HOOPS/MVO:
						<ul>
							<li><strong><em>Windows</em></strong>: *hoops_mvo<version>_vc<MS Visual Studio Version>.dll*</li> 
							<li><strong><em>Linux</em></strong>: *hoops_mvo<version>.so*</li>
						</ul>
					</li>
					<li>For HOOPS/Stream:
						<ul>
							<li><strong><em>Windows</em></strong>: *hoops_stream<version>_vc<MS Visual Studio Version>.dll*</li>
							<li><strong><em>Linux</em></strong>: *hoops_stream<version>.so*</li>
						</ul>
			</ul>
		  </li>
		</ul>

The above files should all be located in your *<hoops>/bin/nt_i386_<Visual Studio Version>* directory on Windows, and your *<hoops>/bin* directory under Linux. 

For Linux platforms, prior to execution, you must execute two export commands. Below is a list based on the platform you are using:

For 32-bit Linux (on a 32-bit machine ONLY)::

	$ cd bin/linux
	$ export LD_LIBRARY_PATH=./:../../Dev_Tools/hoops_3dgs/lib/linux/
	$ export LD_PRELOAD=./libhoops<version>.so:./libopengl2<version>hdi.so

For 64-bit Linux (on a 64-bit machine ONLY)::

	$ cd bin/linux_x86_64
	$ export LD_LIBRARY_PATH=./:../../Dev_Tools/hoops_3dgs/lib/linux_x86_64/
	$ export LD_PRELOAD=./libhoops<version>.so:./libopengl2<version>hdi.so


Interface notes: General usage
==============================

The routines and classes of the HOOPS/3DGS, HOOPS/MVO and HOOPS/Stream toolkits are all generally accessible via the Java wrappers, with a few exceptions and notes covered below. Developers should refer to the API reference manual for each component, and can additionally leverage the Intellisense capabilities of the NetBeans IDE to see listings of class members and function/method arguments. 


HOOPS/3DGS-specific
-------------------

**Routine prefixes**

Each HOOPS/3DGS routine name, such as ``Insert_Polyline`` in your HOOPS program must have a prefix before the name will actually be usable on your computer system. The prefix varies depending on which language you're calling from, and sometimes depending on the brand of the language you're calling from. When calling from Java, all calls to the HOOPS/3GS API are made through the ``HJ`` class, such as::

	StringBuffer ex = new StringBuffer ("");
	HJ.Show_Alias("?picture", ex); 

**Multi-threading**

You must call ``Define_System_Options("multi-threading=full")`` as your first HOOPS call. This is because Java apps must be thought of as multi-threaded, since the garbage collector will run on a separate thread and may trigger HOOPS calls on a separate thread if it invokes certain destructors.

**HOOPS routines available in Java**

Most functions available under C are available in Java except for: 

* ``Define_Callback_Name``
* ``Define_Exit_Handler``
* ``UnDefine_Exit_Handler``
* ``Define_Callback_Name``
* ``UnDefine_Callback_Name``
* ``Show_Callback_Name``
* ``Define_Error_Handler``


Differences between using HOOPS with Java and C
-----------------------------------------------

The largest difference between using HOOPS with Java and C is found when you have a write-back value, i.e. you pass a pointer to a function and it writes a value or values to that location. Because Java does not have pointers, we have to use other means of passing in by reference.

For example, the C HOOPS code that uses a ``char*``::

	char ex[1024];
	HC_Show_Alias("?picture", ex);
	printf("?picture=%s\n",ex);

...is replaced in Java by ``StringBuffer``:: 

	StringBuffer ex = new StringBuffer (1024);

	HJ.Show_Alias("?picture", ex);
	System.out.println("?picture="+ex); 

**NOTE:** You must always pass a new or empty ``StringBuffer``, as ``HJ`` uses ``append`` internally to return the string. You must also call ``ensureCapacity`` to guarantee the buffer has a minimum size before anything can be written into it. For example::

	StringBuffer buf = new StringBuffer();
	buf.ensureCapacity(1024);
	HJ.Show_Color(buf);

The C HOOPS code that uses ``&[float_value]``::

	float x,y,z;
	HC_Open_Segment("?picture");
		HC_Show_Camera_Position(&x, &y, &z);
	HC_Close_Segment();
	printf("x=%f y=%f z=%f\n", x, y, z); 

...is replaced in Java by single element float arrays::

	float[] x = new float[1]; 
	float[]  y = new float[1]; 
	float[]  z = new float[1]; 

	HJ.Open_Segment("?picture");
	HJ.Show_Camera_Position(x, y, z); 
	HJ.Close_Segment();
	System.out.println("x=" + x[0] + "y=" + y[0] + "z=" + z[0]); 

Arrays can be used in Java in a similar manner as they are used in C. Thus, the C HOOPS code::

	float v1[3] = {1.0f,0.0f,0.0f};
	float v2[3] = {0.0f,1.0f,0.0f};
	float v3[3];
	HC_Compute_Cross_Product(v1,v2,v3);
	printf("%f %f %f\n", v3[0], v3[1], v3[2]); 

...is replaced in Java by:::

	float[] v1 = {1.0f,0.0f,0.0f};
	float[] v2 = {0.0f,1.0f,0.0f};
	float[] v3 = new float[3];
	HJ.Compute_Cross_Product(v1,v2,v3);
	System.out.println( v3[0]+" "+v3[1]+" "+ v3[2]); 

It's important to allocate enough room in the array, lest HOOPS writes into unallocated memory and causes a segfault.

**HOOPS keys**

Another difference when using HOOPS with Java is found when dealing with HOOPS keys. In Java, you should use the Java ``long``::

	long key = 0;

	key = HJ.Open_Segment("?picture");
	   ...
	HJ.Open_Segment_By_Key(key); 


**Datatype names and language declarations in Java**

The Java datatypes translate as follows: 

.. raw:: html

	<center>
	  <table border ="1" cols="3" width="580">
		<tr>
		  <td><b>HOOPS</b></td>
		  <td><b>HOOPS (HC) type</b></td>
		  <td><b> Java type</b></td>
		</tr>
		<tr>
		  <td>'string'</td>
		  <td>const char *</td>
		  <td>String</td>
		</tr>
		<tr>
		  <td>'writes string'</td>
		  <td>char *</td>
		  <td>StringBuffer</td>
		</tr>
		<tr>
		  <td>'HC_KEY'</td>
		  <td>HC_KEY</td>
		  <td>long</td>
		</tr>
		<tr>
		  <td>'int'</td>
		  <td>int</td>
		  <td>int</td>
		</tr>
		<tr>
		  <td>'writes int'</td>
		  <td>&amp;int</td>
		  <td>int[1]</td>
		</tr>
		<tr>
		  <td>'float'</td>
		  <td>float</td>
		  <td>float</td>
		</tr>
		<tr>
		  <td>'writes float'</td>
		  <td>&float</td>
		  <td>float[1]</td>
		</tr>
		<tr>
		  <td>'point'</td>
		  <td>float[3]</td>
		  <td>float[3]</td>
		</tr>
		<tr>
		  <td>'writes point'</td>
		  <td>&float</td>
		  <td>float[]</td>
		</tr>
		<tr>
		  <td>'writes bytes'</td>
		  <td>unsigned char *</td>
		  <td>byte[]</td>
		</tr>
		<tr>
		  <td>'writes ints'</td>
		  <td>&amp;int</td>
		  <td>int[]</td>
		</tr>
	  </table>
	</center>


HOOPS Intermediate Mode
-----------------------

The HOOPS Intermediate Mode library provides a means for an application to trap the HOOPS update cycle at certain points in the rendering pipeline through a set of callback classes. When you trap the update cycle at a callback point, you can decide what and how something is drawn, or even abort the process itself. The HOOPS I.M. library also provides a set of functions you can call from your callback class to draw to the display in an "immediate mode" style and to query the graphics database and the device characteristics. In the HOOPS/3dGS Programming Guide, you can learn more about :doc:`HOOPS I.M. </prog_guide/3dgs/08_1_im_overview>` and how to :ref:`implement and use the callback classes <prog_guide/3dgs/08_1_im_overview:Callbacks for C++/C#/Java Developers>`.

Any callback class, which has a virtual function with an array as a parameter, is not available in Java. This is because Java doesn't have any concept of a pointer so functions with array arguments cannot be mapped properly. 


HOOPS/MVO and HOOPS/Stream
==========================

The capabilities and limitations of HOOPS/MVO for Java are largely analogous to those of C#. After reviewing this section, you can learn more by clicking :ref:`here <general/language_csharp:HOOPS/MVO classes in C#/Java>`.

**Member variables**

Member variables are accessed via helper set/get functions with a capitalized member name appended to the end of set/get. For example:

C++:

* class: ``HOpCameraManipulate``
* member: ``m_pRelativeOrbitOperator``

Java:

* class: ``HOpCameraManipulate``
* method: ``HBaseOperator getM_pRelativeOrbitOperator()``

Note that the first letter after "get" or "set" -- in this case, "M" from ``m_pRelativeOrbitOperator`` -- is capitalized for Java accessor methods.

**Array handling**

*Methods in the C++ classes which return arrays (as a return type) return the array through a parameter in Java*

Example signature::

	public GetWorldBounding(float[] values, int count);

Sample usage::

	// tk is a valid BstreamFileToolkit
	float[] bounds = new float[6];
	tk.GetWorldBounding(bounds, 6);

*Array member variables return the array via a get_[variable name] method and are read-only*

Example signature::

	public get_point_list(HPoint[] values, int count);

Sample usage::

	// shell is valid HShell
	// values is valid HPoint[] array
	shell.get_point_list(values, values.length);

**``HFileInputResult`` and ``HFileOutputResult``**

You should use the enum HFileIOResult wherever HFileInputResult or HFileOutputResult are mentioned in our documentation. For example::

	HFileIOResult result = myView.GetModel().Read("c:/datasets/bnc.hsf", myView);

	if (result != HFileIOResult.HIO_OK)
	{
	  // ... error
	}

**``HUtilityPMI`` usage**

The ``HUtilityPMI`` classes have several caveats.

1. ``PMI::String`` is ``PMI_String`` in Java. For example::
  
	PMI_String[] datum_labels = new  PMI_String[3];
	datum_labels[0]  = new PMI_String("A-B");
	datum_labels[1]  = new PMI_String("C");
	datum_labels[2]  = new PMI_String("D");

2. PMI Type/SubType enums are placed in Java packages. For example, ``PMI::DiameterModifier::Type`` is ``com.techsoft.hoops.PMI.DiameterModifier.Type``
 
3. Enum array parameters (in or out) and Enum output params require Java ``int[]`` arrays

Out param example - 1st param in ``GetDiameterModifierType``. 

C++ prototype::

	class  PMI::FeatureControlFrameEntity<br />
	void  GetDiameterModifierType(DiameterModifier::Type & out_diameter_modifier_type, TextAttributes & out_text_attributes) const;
     
Java code::

	FeatureControlFrameEntity  fcf = new FeatureControlFrameEntity(HJ.Create_Segment("pmi/fcf"));
	int[]  diameter_modifier_type = new int[1];
	TextAttributes[]  label_attributes;
	fcf.GetDiameterModifierType(diameter_modifier_type,  text_attributes);

4. Array param example - 4th param in ``SetDatumReferences``

C++ prototype::

	class  PMI::FeatureControlFrameEntity
	void  SetDatumReferences(unsigned int in_count, String const in_labels[],  TextAttributes const in_label_attributes[],DatumModifier::Type  const in_modifiers[], TextAttributes const in_modifier_attributes[]);

Java code::

	int[]  datum_modifiers = new int[3];
	datum_modifiers[0]  =  com.techsoft.hoops.PMI.DatumModifier.Type.MaximumMaterialCondition.swigValue();
	datum_modifiers[1]  =  com.techsoft.hoops.PMI.DatumModifier.Type.RegardlessOfFeatureSize.swigValue();
	datum_modifiers[2]  = com.techsoft.hoops.PMI.DatumModifier.Type.LeastMaterialCondition.swigValue();
	//  ... declare/populate other variables
	fcf.SetDatumReferences(3,  datum_labels, datum_label_attributes, datum_modifiers,  datum_modifier_attributes);

5. Casting between PMI enums and Java ``int``

To convert a Java PMI enum to an ``int`` value, use ``[enum value].swigValue()``. For example::

	int v =  com.techsoft.hoops.PMI.DatumModifier.Type.MaximumMaterialCondition.swigValue();

To convert from an ``int`` to an ``enum``, use ``[enum].swigToEnum()``. For example::

	int[]  tolerance_type = new int[1];
	fcf.GetToleranceType(tolerance_type,  text_attributes);
	com.techsoft.hoops.PMI.Tolerance.Type  e = com.techsoft.hoops.PMI.Tolerance.Type.swigToEnum(tolerance_type[0])


HOOPS/Stream notes
------------------

Do not use ``BStreamFileToolkit::PrepareBuffer``. Instead, do the following:

* Call ``HJSTREAM.PrepareBuffer(BStreamFileToolkit tk, byte[] b, int s)``, to setup the buffer.
* Call ``HJSTREAM.ReleaseBuffer(byte[] b, int s)`` to retrieve the next buffer of HSF data from the toolkit. This would be called before processing the buffer of HSF data.
