two loops of execution: the haptic loop and the graphic ... · pdf filetauchi – tampere...

53
TAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 Two loops of execution: the haptic loop and the graphic loop. Forces and counter-forces are generated and summed together to produce a sense of tactile surface / force feedback. Force interpolation.

Upload: nguyenngoc

Post on 17-Mar-2018

217 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Summary of lecture #1

•Two loops of execution: the haptic loop and the graphic loop.

•Forces and counter-forces are generated and summed together to produce a sense of tactile surface / force feedback.

•Force interpolation.

Page 2: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Summary of lecture #1

Many levels of development:•X3D•Python•C++•Any mixture of previous three

Page 3: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

X3D & Python

Page 4: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

X3D & Python

● Define the scene with X3D markup language● Add scripted behavior with Python

Limitations: ● No new surfaces, geometries etc. ● Might slow down the larger systems if all functionality

is scripted

Page 5: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

X3D + Python: example<?xml version="1.0" encoding="UTF-8"?><Transform translation="0 0 -0.1"><Group> <DynamicTransform mass="20" inertiaTensor="0.1 0 0 0 0.1 0 0 0 0.1"> <Shape> <Appearance> <Material diffuseColor="1 0 0" DEF="VARI"/> <FrictionalSurface dynamicFriction="0.6" staticFriction="0.2"/> </Appearance> <Box DEF="BOX" size="0.2 0.2 0.2"/> </Shape> </DynamicTransform> <PythonScript DEF="PS" url="pressure.py" /> <ROUTE fromNode="BOX" fromField="force" toNode="PS" toField="pressurePoint" /> <ROUTE fromNode="PS" fromField="pressurePoint" toNode="VARI" toField="diffuseColor" /></Group></Transform>

Video:

Pre

ssur

e

Page 6: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

X3D + Python: example

from H3DInterface import *

class MyForceSensor(TypedField(SFColor,MFVec3f)):

def update(self,event):

force = event.getValue()

if(len(force)>0):force = max(force[0].x, force[0].y, force[0].z) / 25

else:

force = 0

if(force > 1.0):

force=1.0

return RGB(force, 0.3, 0.3)

pressurePoint = MyForceSensor()

Page 7: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Python tips

The field has member functions getRoutesIn and getRoutesOut.

Global field time contains the current time (from Scene::time)

eventSink is a global field that you can route your fields to. If you do so, the field will be updated once in each scene-graph loop.

Page 8: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

More Python tips

PeriodicUpdate is a field template modifier that makes your field to update once in every scene-graph loop.

init function will be run once when the python file is loaded. traverseSG function is called once in every scene-graph loop.

Page 9: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PeriodicUpdate example

class Foobar(PeriodicUpdate(SFColor)):def update(self, event):

print "foo"return event.getValue()

class Func(TypedField(SFColor,SFTime)):def update(self,event):

print "UPDATE"return RGB(random(),random(),

random())periodicfunc = Func()time.route(periodicfunc)

Page 10: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Even More Python tips

The module H3DUtils has some very useful classes and functions. The most important one is the TimerCallback class for which you can add callback functions to be called after a certain period. This is “one-off” function call, that is, the function is removed from the TimerCallback once it has been called.

Page 11: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

TimerCallback

from H3DUtil import *

def callfunc(): global timec print “boo!” timec.addCallback(time.getValue()+1, callfunc, [])

timec = TimeCallback()timec.addCallback(time.getValue()+1, callfunc, [])

Page 12: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Accessing the X3D side

You can do a lot of things from within the Python code. You can, for example, access the haptic device and the scene-graph. For example, to add an element to a scene-graph from Python do:

X3D:<Transform DEF="RYHMA">

</Transform>

<PythonScript url="mytimer.py" >

<Group USE="RYHMA" containerField="references"/>

</PythonScript>

Python:globgroup = references.getValue()[0] globgroup.children.push_back(mybox)

Video:

PyS

cene

Page 13: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Programming haptics

Part II: The C++ side of things

Page 14: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Basics: Field

• As with Python, C++ side also deals with fields and nodes.

• But when you get the incoming value as a event parameter for the update function in Python, you get the incoming value as a member variable in C++:

Python: def update(self, event):

C++: virtual void update() {

value = static_cast<SFFloat>(event.ptr)->getValue()}

Page 15: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Fields

• Note also that the Python returns a value in the update() method whereas in C++ you'll place the outbound value to the member variable value

• As with Python, the C++ Field has routes_in and routes_out, but as a member variables:

Class FloatSum: public SFFloat {virtual void update() {

SFFloat::update();value = 0;for( FieldVector::iterator i = routes_in.begin();

I != routes_in.end(); i++) {value += *i;

}}

}

Page 16: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

AutoUpdate

There are the same field template modifiers as in Python. The AutoUpdate looks like this:

Class AutoFloat: public AutoUpdate< SFFloat > {virtual void update() {

value = 0;...

}}

Page 17: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

TypedField

And here's TypedField

Class AeroFloat: public TypedField< SFFloat, Types< SFInt32, SFBool > > {

virtual void update() {int x = static_cast<SFInt32 *>( routes_in[0] )->getValue();bool val2 = static_cast< SFBool *> ( routes_in[1])->getValue();...

}}

Page 18: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PeriodicUpdate

class MyTicker : public PeriodicUpdate<TypedField<SFFloat, Types<SFTime>>>

{

virtual void update()

{

value = 2.0;

cout << value << endl;

}

};

Page 19: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

eventSink

class MyTicker : public TypedField<SFFloat, Types<SFTime>>

{

virtual void update()

{

value = 2.0;

cout << value << endl;

}

virtual void upToDate()

{

update();

}

};

MyTicker mtick = MyTicker();

mtick.route(scene->eventSink);

Page 20: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Field member functions

For all fields:route( Field )routeNoEvent( Field )unroute ( Field )touch()

For MFields an SFields: getValue()setValue( value)

Page 21: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Nodes

• Check the Node basics from the Part I of the slides• There are many ways to create a Node in C++:

1.Load it from X3D file with the X3D::createX3DFromURL or X3D::createX3DNodeFromURL function

2.Create it from X3D string with the X3D::createX3DFromString

3.Just create it: Node foo = new Node()• There are other methods too.

Page 22: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Loading from file / URL

X3D:• Define a X3D file with the wanted objects.

Optionally name the objects with the DEF attribute:<Shape DEF=”pallo”/>

C++:• Load the X3D file with

createX3DFromURL( url, ... )• Command returns a pointer to a Group

Page 23: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

DEFNodes

• DEFNodes provide a mapping between defined DEF names in X3D and the nodes they refer to.

• In C++ create an instance of DEFNodes. • And give it as a second parameter for the

createX3D... function:createX3DFromURL( url, defnodes )

• Now you can access the named X3D nodes from C++ with the getNode() method:

defnodes->getNode( “pallo” )

Page 24: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Creating Nodes

Creating Nodes from string is pretty much similar to creating Nodes from URL:

createX3DFromString( string, DEFNodes )

Using the createX3DNodeFrom... methods will return pointer to a single Node instead of a group. DEFNodes will also apply to these functions.

There are also functions to handle VRML files.

Page 25: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Using Nodes in C++

• Create a new Node

• Get the scene-graph root from the Scene

• Add the new Node to the children of the scene-graph root

Page 26: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Nodes in C++ vs. X3D

<Shape>

<Appearance>

<Material diffuseColor="1 0 0" "/>

<SmoothSurface/>

</Appearance>

<Box size="0.2 0.2 0.2"/>

</Shape>

...

H3D::Material material = H3D::Material();

material.diffuseColor->setValue(

H3D::RGB(0.0,0.3,0.3));

H3D::SmoothSurface surf = H3D::SmoothSurface();

H3D::Appearance app = H3D::Appearance();

app.material->setValue(&material);

app.surface->setValue(&surf);

H3D::Box box = H3D::Box();

box.size->setValue(

H3DUtil::ArithmeticTypes::Vec3f(0.2,0.2,0.2));

H3D::Shape shape = H3D::Shape();

shape.appearance->setValue(&app);

shape.geometry->setValue(&box);

...

scene->sceneRoot->setValue( myGroup );

Page 27: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PressureBox exampe

Let's recreate the Python pressure box example in C++.

I used the H3DLoad.cpp file as a starting point because it will handle all the mandatory stuff and allows one to change the application behavior from the H3DLoad settings utility.

Page 28: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PressureBox 1/3

...

X3D::DEFNodes myDefNodes;

AutoRef< Node > group( X3D::createX3DNodeFromString(

"<DynamicTransform mass=\"20\" DEF=\"GROUP\"/>", &myDefNodes ) );

H3D::Material material = H3D::Material();

material.diffuseColor->setValue(H3D::RGB(0.0,0.3,0.3));

SmoothSurface surf = SmoothSurface();

H3D::Appearance app = H3D::Appearance();

app.material->setValue(&material);

app.surface->setValue(&surf);

H3D::Box box = H3D::Box();

box.size->setValue(H3DUtil::ArithmeticTypes::Vec3f(0.15,0.15,0.15));

Page 29: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PressureBox 2/3

H3D::Shape shape = H3D::Shape();

shape.appearance->setValue(&app);

shape.geometry->setValue(&box);

DynamicTransform *dt;

myDefNodes.getNode("GROUP",dt);

dt->children->push_back(&shape);

MyForceSensor mfs = MyForceSensor();

box.force->route(&mfs);

mfs.route(material.diffuseColor);

...

scene->sceneRoot->setValue( group.get() );

Scene::mainLoop();

Page 30: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

PressureBox 3/3

class MyForceSensor : public TypedField<H3D::SFColor,Types<MFVec3f>>

{

virtual void update()

{

if(static_cast<MFVec3f *>(routes_in[0])->getSize()>0) {

H3DUtil::ArithmeticTypes::Vec3f foo=

static_cast<MFVec3f *>(routes_in[0])->getValue()[0];

H3DFloat force = max(max(abs(foo.x), abs(foo.y)), abs(foo.z))/22;

if(force > 1.0)

force = 1.0;

value = RGB(force,0.3,0.3);

} else {

value = RGB(0.0,0.3,0.3);

}

}

};

Page 31: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Nodes

•Subclass from Node class or one of its subclasses•Define the node fields •Make a constructor•Export the Node fields to be used in X3D etc.

Page 32: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Nodes 2class MyFirstNode : public Node

{

class InnerField : public AutoUpdate<SFFloat> {

virtual void update()

{

value = static_cast<SFFloat *>(event.ptr)->getValue() / 2.0;

cout << value << endl;

}

};

public:

MyFirstNode( Inst<InnerField> _varvalue = 0 );

auto_ptr< InnerField > mvar;

};

MyFirstNode::MyFirstNode(Inst<InnerField> _varvalue ) : mvar( _varvalue )

{

}

Page 33: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Nodes 3: exporting fields

Add the H3DNodeDatabase to the header file:class MyFirstNode : public Node

...

public:

static H3DNodeDatabase database;

};

In the cpp file, add the new Node to the database:H3DNodeDatabase MyFirstNode::database( “MyFirstNode”,

&(newInstance<MyFirstNode>),

typeid( MyfirstNode ),

&Node::database );

The parameters are: node name in X3D, node constructor, typeid and the node parent.

Page 34: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Nodes 4: exporting fields

And then define the node fields with the proper access type:

Namespace MyFirstNodeInternals {

FIELDDB_ELEMENT( MyFirstNode, mvar, INPUT_OUTPUT );

}

<Group>

<MyFirstNode mvar=”2.0”/>

</Group>

And now you can use your field in X3D and Python:

Page 35: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new geometries 1/4

• Graphical Nodes inherit from the H3DDisplayListObject.

• Such field has a internal field called displayList that is responsible of creating OpenGL display list for rendering.

• Display list speeds up the rendering as it will only be updated once one of its inbound routes create an event.

• That means that if you want that some field affects the rendering, you must route it to the displayList field.

Page 36: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new geometries 2/4

#ifndef __TRIANGLE2D_H__#define __TRIANGLE2D_H__

#include <X3DGeometryNode.h>#include <SFVec2f.h>

namespace H3D { class Triangle2D : public X3DGeometryNode { public: class SFBound: public X3DGeometryNode::SFBound { virtual void update() { SFFloat b = static_cast< SFFloat * >( routes_in[0] )->getValue(); BoxBound *bb = new BoxBound; bb->size->setValue( Vec3f( b.getValue(), b.getValue(), 0.0 ) ); value = bb; } }; Triangle2D( Inst< SFNode > _metadata = 0, Inst< SFBound > _bound = 0, Inst< DisplayList > _displayList = 0, Inst< MFBool > _isTouched = 0, Inst< MFVec3f > _force = 0, Inst< MFVec3f > _contactPoint = 0, Inst< MFVec3f > _contactNormal = 0, Inst< SFFloat > _size = 0, Inst< SFBool > _solid = 0 ); virtual void render(); virtual void traverseSG( TraverseInfo &ti ); virtual int nrTriangles() { return 1; } auto_ptr< SFFloat > size; auto_ptr< SFBool > solid; static H3DNodeDatabase database; };}#endif

Page 37: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new geometries 3/4#include <Triangle2D.h>

using namespace H3D;

// Add this node to the H3DNodeDatabase system.H3DNodeDatabase Triangle2D::database( "Triangle2D", &(newInstance<Triangle2D>), typeid( Triangle2D ), &X3DGeometryNode::database );

namespace Triangle2DInternals { FIELDDB_ELEMENT( Triangle2D, size, INPUT_OUTPUT ); FIELDDB_ELEMENT( Triangle2D, solid, INPUT_OUTPUT );}Triangle2D::Triangle2D( Inst< SFNode > _metadata, Inst< SFBound > _bound, Inst< DisplayList > _displayList, Inst< MFBool > _isTouched, Inst< MFVec3f > _force, Inst< MFVec3f > _contactPoint, Inst< MFVec3f > _contactNormal, Inst< SFFloat > _size, Inst< SFBool > _solid ): X3DGeometryNode( _metadata, _bound, _displayList, _isTouched, _force, _contactPoint,

_contactNormal ), size ( _size ), solid ( _solid ){ type_name = "Rectangle2D"; database.initFields( this ); size->setValue( 2.0 ); solid->setValue( false ); size->route( bound ); size->route( displayList ); solid->route( displayList );}

Page 38: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new geometries 4/4

void Triangle2D::render() { H3DFloat half= size->getValue() / 2; glBegin( GL_TRIANGLES );

glVertex3f(-half,-half, 0.0f);glVertex3f( 0.0f , half, 0.0f);glVertex3f( half,-half, 0.0f);

glEnd();}

void Triangle2D::traverseSG( TraverseInfo &ti ) { X3DGeometryNode::traverseSG( ti ); // use backface culling if solid is true if( solid->getValue() ) useBackFaceCulling( true ); else useBackFaceCulling( false );}

Page 39: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Render & traverseSG

render() method draws the graphical representation of the Node

traverseSG() method does the haptic rendering. The X3DGeometryNode has a common functionality for all nodes.

Page 40: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 1/7

Making new surfaces is a two-fold process since HAPI deals with the haptics and any node that will be placed in the scene-graph needs to be a descendant of Node class. When making new surfaces:• Create a HAPI surface that subclasses

HAPISurfaceObject or one of its sublasses. • Create a H3D surface that subclasses the

H3DSurfaceNode or one of its subclasses

Page 41: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 2/7

To make a functional HAPI Surface, you only need to override the getProxyMovement and getForces methods: namespace HAPI {

class MySurface:public HAPISurfaceObject { public: MySurface( HAPIFloat _stiffness = 0.35, HAPIFloat _damping = 0, HAPIFloat _static_friction = 0, HAPIFloat _dynamic_friction = 0 ); virtual ~MySurface(); virtual void getProxyMovement( ContactInfo &contact_info ); virtual void getForces( ContactInfo &contact_info ) };}

MySurface header file

Page 42: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 3/7 : ContactInfo

These methods get a ContactInfo instance as a parameter.

• The contactInfo class contains the information related to this current contact of the avatar and the object.

• By modifying the ContactInfo instance you can introduce new force effects for your surfaces.

getProxyMovement should use the ContactInfo.setLocalProxyMovement to adjust the movement of the proxy

getForces should use the ContactInfo.setGlobalForce to create the haptic effect.

Page 43: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

ContactInfo

The ContactInfo has the following member variables:

Vec3 contact_point_global; // The point of contact in global coordinates.

Vec3 probe_position_global; // The position of the haptics device in global coordinates.

Vec3 tex_coord; // The texture coordinate at the contact point.

Vec3 x_axis; // The axes of the local coordinate space in global coordinates.

Vec3 y_axis;

Vec3 z_axis;

Vec3 origin_global; // The origin of the local coordinate space in global coordinates.

Collision::GeometryPrimitive * geom_primitive; // the primitive the point of contact was detected.

HAPIHapticShape *haptic_shape; // the HAPIHapticShape on which the point of contact was detected

Vec3 force_global; // output force in global coordinates.

Vec3 torque_global; // output torque in global coordinates.

Vec2 proxy_movement_local; // The proxy movement in local coordinates.

bool has_inverse; // true if the inverse member has been calculated (from global to local space)

Matrix4 inverse; // The matrix from global to local space (if the has_inverse member)

HAPIHapticsDevice *hd; // The haptics device that has made the contact.

INP

UT

OU

TP

UT

Page 44: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

ContactInfo

The ContactInfo has the following member variables:

Vec3 contact_point_global; // The point of contact in global coordinates.

Vec3 probe_position_global; // The position of the haptics device in global coordinates.

Vec3 tex_coord; // The texture coordinate at the contact point.

Vec3 x_axis; // The axes of the local coordinate space in global coordinates.

Vec3 y_axis;

Vec3 z_axis;

Vec3 origin_global; // The origin of the local coordinate space in global coordinates.

Collision::GeometryPrimitive * geom_primitive; // the primitive the point of contact was detected.

HAPIHapticShape *haptic_shape; // the HAPIHapticShape on which the point of contact was detected

Vec3 force_global; // output force in global coordinates.

Vec3 torque_global; // output torque in global coordinates.

Vec2 proxy_movement_local; // The proxy movement in local coordinates.

bool has_inverse; // true if the inverse member has been calculated (from global to local space)

Matrix4 inverse; // The matrix from global to local space (if the has_inverse member)

HAPIHapticsDevice *hd; // The haptics device that has made the contact.

INP

UT

OU

TP

UT

Page 45: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 4/7

The cpp file for the new HAPI surface:

using namespace HAPI;

MySurface::MySurface( HAPIFloat _stiffness, HAPIFloat _damping , HAPIFloat _static_friction , HAPIFloat _dynamic_friction ) : FrictionSurface(_stiffness, _damping, _static_friction, _dynamic_friction), direction(0){}

MySurface::~MySurface() {};

virtual void MySurface::getProxyMovement( ContactInfo &contact_info) {}virtual void MySurface::getForces( ContactInfo &contact_info ) {

contact_info.setGlobalForce((contact_info.contact_point_global - contact_info.probe_position_global));

}

Page 46: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 5/7

The H3D Surface header file looks like this: class PullSurface: public H3DSurfaceNode { public: class UpdatePullforce: public SFFloat { public: virtual void setValue( const H3DFloat &f, int id = 0 ); protected: virtual void update(); }; PullSurface( Inst< UpdatePullforce> _pforce = 0);

void initialize();

auto_ptr< UpdatePullforce > pforce;

static H3DNodeDatabase database;

protected: H3DDouble conversion_to_HAPI;};

Page 47: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 6/7

The H3D Surface cpp file: H3DNodeDatabase PullSurface::database( "PullSurface", &(newInstance<PullSurface>), typeid( PullSurface ), &H3DSurfaceNode::database );

namespace PullSurfaceInternals { FIELDDB_ELEMENT( PullSurface, pforce, INPUT_OUTPUT );}

PullSurface::PullSurface( Inst< UpdatePullforce> _pforce): pforce( _pforce), conversion_to_HAPI( 0.7 ) { type_name = "PullSurface"; database.initFields( this ); pforce->setValue( 0.5 );}

void PullSurface::initialize() { hapi_surface.reset( new HAPI::MySurface( pforce->getValue() * conversion_to_HAPI, 0 ) );}

Page 48: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Making new Surfaces 7/7

void PullSurface::UpdatePullforce::setValue( const H3DFloat &f, int id ){ SFFloat::setValue( f, id ); PullSurface *ss = static_cast< PullSurface * >( getOwner() ); if( ss->hapi_surface.get() ) { static_cast< HAPI::MySurface * >( ss->hapi_surface.get() ) ->stiffness = f * ss->conversion_to_HAPI; }}

void PullSurface::UpdatePullforce::update() { SFFloat::update(); cout << value << endl; PullSurface *ss = static_cast< PullSurface * >( getOwner() ); if( ss->hapi_surface.get() ) { static_cast< HAPI::MySurface * >( ss->hapi_surface.get() ) ->stiffness = value * ss->conversion_to_HAPI; }}

Page 49: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Global forces

• HAPI class HAPIForceEffect is a base class for all global force effects.

• Extending the class you can easily generate effects that will affect the haptic device.

• In simplest case just implement the calculateForces method.– This method is called 1000 times in a second.– So do not do any heavy calculation in it!– Also you should avoid accessing the field network

while doing the calculation.• Take the force into use in a traverseSG method of

any Node by calling TraverseInfo.addForceEffect or TraverseInfo.addForceEffectToAll method.

Page 50: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

onValueChange template modifier

• A field template modifier that adds virtual function onValueChange to the class.

• The onValueChange method can be overridden in the sublasses to perform a function when the field value changes.

Page 51: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

DeformableShape

A X3DShapeNode that makes it possible to deform a shape by touching it with the haptic device.• The shape must be defined with the

X3DComposedGeometryNode• origCoord – the original coordinates of the

GeometryNode• deformedCoord – the coordinates of

GeometryNode when being in contact with the haptic device

• restingCoord – the coordinates the geometry goes back when there is no more contact with the haptic device

Page 52: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Possible applications

•Sculpting•Integrate physics engine to H3D•Implement collision detection (with mass & force?)•CAD / planning / decoration application•Block editor•Heightmap / tile / ?? editor•Origami editor!•Your own idea?

Page 53: Two loops of execution: the haptic loop and the graphic ... · PDF fileTAUCHI – Tampere Unit for Computer-Human Interaction Summary of lecture #1 •Two loops of execution: ... return

TAUCHI – Tampere Unit for Computer-Human Interaction

Links

H3D homepage:http://www.h3d.org

X3D specifications: http://www.web3d.org/x3d/specifications/#x3d-spec