OpenSceneGraph - Cloack of Invisibility - rendering

I’m new using OSG and I’m having some issues trying to solve a problem.
I’ve created a scene (a quad and two spheres, with a fixed background) and I’m trying to occlude one of the spheres with a transparent quad. I mean, to make a "Cloak of Invisibility" so I can see the background image through it, but not the sphere (or whatever in the projective line) that it’s behind it.
I'm totally stuck as all the tests I've been doing haven't got me even close to what I want. I’d be really grateful if you could help me with this, any idea (or code!) would be more than welcome!! =)
I attach the code of the simple scene that I’m using to make the tests.
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Depth>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/ShapeDrawable>
#include <osg/BlendFunc>
#include <osgGA/TrackBallManipulator>
int main ()
{
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
osg::ref_ptr<osg::Image> image = osgDB::readImageFile( "C:/OpenSceneGraph-3.4.0/esc.jpg" );
texture->setDataVariance(osg::Object::DYNAMIC);
texture->setResizeNonPowerOfTwoHint(false);
texture->setImage( image.get() );
// Background
osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(osg::Vec3(),osg::Vec3(1.0f,0.0f,0.0f),osg::Vec3(0.0f, 1.0f, 0.0f));
quad->getOrCreateStateSet()->setTextureAttributeAndModes( 0, texture.get() );
osg::ref_ptr<osg::Geode> geodeBack = new osg::Geode;
geodeBack->addDrawable( quad.get() );
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setCullingActive( false );
camera->setClearMask( 0 );
camera->setAllowEventFocus( false );
camera->setReferenceFrame( osg::Transform::ABSOLUTE_RF );
camera->setRenderOrder( osg::Camera::POST_RENDER );
camera->setProjectionMatrix( osg::Matrix::ortho2D( 0.0, 1.0, 0.0, 1.0) );
camera->addChild( geodeBack.get() );
osg::StateSet* ss = camera->getOrCreateStateSet();
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
ss->setMode(GL_DEPTH, osg::StateAttribute::ON);
ss->setAttributeAndModes( new osg::Depth( osg::Depth::LEQUAL,0.99,1.0 ) );
// Quad geometry
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
vertices->push_back( osg::Vec3(-1.0f, 1.0f,-1.0f) );
vertices->push_back( osg::Vec3( 0.0f, 1.0f,-1.0f) );
vertices->push_back( osg::Vec3( 0.0f, 1.0f, 0.0f) );
vertices->push_back( osg::Vec3(-1.0f, 1.0f, 0.0f) );
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
normals->push_back( osg::Vec3(0.0f,-1.0f, 0.0f) );
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back( osg::Vec4(1.0f, 1.0f, 1.0f, 0.0f) );
osg::ref_ptr<osg::Geometry> quad2 = new osg::Geometry;
quad2->setVertexArray( vertices.get() );
quad2->setNormalArray( normals.get() );
quad2->setNormalBinding( osg::Geometry::BIND_OVERALL );
quad2->setColorArray( colors.get() );
quad2->setColorBinding( osg::Geometry::BIND_OVERALL );
quad2->addPrimitiveSet( new osg::DrawArrays(GL_QUADS, 0, 4) );
osg::ref_ptr<osg::Geode> geodeTransp = new osg::Geode;
geodeTransp->addDrawable( quad2.get() );
osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc;
blendFunc->setFunction( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
osg::StateSet* stateset = geodeTransp->getOrCreateStateSet();
stateset->setAttributeAndModes( blendFunc );
// I'd see both spheres if I uncomment this. Otherwise I'd see the blue osg default background
//stateset->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
// Sphere 1
osg::ref_ptr<osg::ShapeDrawable> shape1 = new osg::ShapeDrawable;
shape1->setShape( new osg::Sphere(osg::Vec3(-0.3f,0.5f,-0.3f), 0.2f) );
shape1->setColor( osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) );
// Sphere 2
osg::ref_ptr<osg::ShapeDrawable> shape2 = new osg::ShapeDrawable;
shape2->setShape( new osg::Sphere(osg::Vec3(-0.7f,1.5f,-0.7f), 0.2f) );
shape2->setColor( osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) );
osg::ref_ptr<osg::Geode> geodeFront = new osg::Geode;
geodeFront->addDrawable( shape1.get() );
geodeFront->addDrawable( shape2.get() );
osg::ref_ptr<osg::Group> root = new osg::Group;
root->addChild( camera.get() );
root->addChild( geodeTransp.get() );
root->addChild( geodeFront.get() );
osgViewer::Viewer viewer;
viewer.setSceneData( root.get() );
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
osg::Vec3d eye( -0.5, -3.0, -0.5 );
osg::Vec3d center( -0.5, 0.0, -0.5 );
osg::Vec3d up( 0.0, 0.0, 1.0 );
viewer.getCamera()->setViewMatrixAsLookAt( eye, center, up );
viewer.realize();
while(!viewer.done()) {
viewer.frame();
}
return 0;
}
Thanks in advance,
Cheers,
Alvaro

If I correctly understood what you're after, you should simply render in this specific order:
the background plane
the "invisibility" quad
all the other object (i.e. the two spheres, etc...)
So that everything rendered after the quad, will be masked by it if happens to be behind it. In OSG you can achieve that by assigning explicitly the renderbin to use for the different (groups of) nodes in their stateset:
osg::StateSet* stateset = backgroundNode->getOrCreateStateSet();
stateset->setRenderBinDetails(1, "RenderBin");
// and increasing the number for the other nodes...

Related

Createjs, how to use the mouse to draw a rectangle in the stage

sample
I want to use the mouse to draw a rectangle on the stage,but the rect can't change size.
this is code:
var planetText,selectBox=new createjs.Shape(),x, y, width, height;
stage.on('mousedown',function(event){
x = event.stageX;y = event.stageY;
selectBox.graphics.beginFill('#ffffff').drawRect(x, y, 100, 100);
selectBox.set({alpha:0.5});
planetText = new createjs.Text(x+','+y +','+0+','+0, "16px Arial", "#ffffff");
planetText.set({textAlign:'center',textBaseline:'middle',x:x,y:y});
//console.log(selectBox);
stage.addChild(selectBox);
stage.addChild(planetText);
stage.update();
});
stage.addEventListener('pressmove',function (event){
//console.log(event);
width = event.stageX - x;
height = event.stageY - y;
planetText.text = x + ',' + y +','+width+','+height;
//selectBox.set({w:width,h:height});
createjs.Tween.get(selectBox).to({width:width,height:height},100,createjs.Ease.bounceIn());
stage.update();
});
stage.on('pressup',function(event){
//console.log(self.selectBox);
createjs.Tween.get(selectBox).to({alpha:0},300,createjs.Ease.bounceIn());
stage.removeChild(selectBox);
stage.update();
});
how to fixed it , thx~
Have a look at this question/answer:
Change Color of Shape Mid Tween
Basically, there is no width/height of display objects in EaselJS, but you can change the actual drawing command any time. You can also change the scaleX/scaleY, and set the stroke to ignoreScale:
shape.graphics.setStrokeStyle(1, null, null, null, true); // 5th param
Further reading:
http://blog.createjs.com/new-command-approach-to-easeljs-graphics/
http://blog.createjs.com/update-width-height-in-easeljs/

Three.js, Camera rotation around a point

I'm trying to make a camera rotation and zoom around a point.
I don't want to use THREE.TrackBallControls because as i see, it only modify the fov when zooming, it is not what i want.
I'm using this simple equation : http://en.wikipedia.org/wiki/Sphere#Equations_in. To compute a point on the sphere, this point will be the position of the camera.
In three.js
var point = new THREE.Vector3(
radius * Math.cos(theta) * Math.sin(phi),
radius * Math.sin(theta) * Math.sin(phi),
radius * Math.cos(phi)
);
point.add(center);
To manipulate it, i use :
left mouse, for rotation : x coord === theta and y coord === phi
middle mouse, for zooming : zoom in/out === radius
It doesn't work well, especially for 'phi' rotation, maybe because it's define between 0 and PI.
Maybe there is a better solution using Quaternion.Slerp ?
edit :
My camera :
aspectRatio = container.offsetWidth / container.offsetHeight;
camera = new THREE.OrthographicCamera( -aspectRatio * viewSize / 2, aspectRatio * viewSize / 2, viewSize / 2, -viewSize / 2, -10, 10 );
camera.position.x = 0.004;
camera.position.y = 0.004;
camera.position.z = 0.004;
camera.lookAt(new THREE.Vector3(0, 0, 0))
scene.add(camera);
My OrbitControls :
controls = new THREE.OrbitControls ( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.keyPanSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
when using left mouse (rotation) the camera.position change.
when using middle mouse (zoom) the camera.position is still the same.
check made in the render function :
function render() {
// update camera controls
controls.update();
console.log(camera.position);
// actually render the scene
renderer.render( scene, camera );
}

How to draw a texture as background in gtk?

I want to add a texture as background in a gtk container, is it possible?
What I want is similar to the repeat-x repeat-y properties in css, but it's not supported in gtk yet, so, how to do it without any ugly hacks?. Another example is what nautilus have, where you can change the background.
thanks :)
pd:sorry 4 ma english
I did it this way:
private bool draw_background (Cairo.Context cr) {
int width = this.get_allocated_width ();
int height = this.get_allocated_height ();
cr.set_operator (Cairo.Operator.CLEAR);
cr.paint ();
cr.set_operator (Cairo.Operator.OVER);
var background_style = this.get_style_context ();
background_style.render_background (cr, 0, 0, width, height);
background_style.render_frame (cr, 0, 0, width, height);
var pat = new Cairo.Pattern.for_surface (new Cairo.ImageSurface.from_png (Build.PKGDATADIR + "/files/texture.png"));
pat.set_extend (Cairo.Extend.REPEAT);
cr.set_source (pat);
cr.paint_with_alpha (0.6);
return false;
}

Rotating camera around the X-axis (three.js)

I am trying to rotate the camera around to X-axis of the scene.
At this point my code is like this:
rotation += 0.05;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
This makes the camera move around but during the rotation something weird happens and either the camera flips, or it skips some part of the imaginary circle it's following.
You have only provided a snippet of code, so I have to make some assumptions about what you are doing.
This code:
rotation += 0.05;
camera.position.x = 0;
camera.position.y = Math.sin(rotation) * 500;
camera.position.z = Math.cos(rotation) * 500;
camera.lookAt( scene.position ); // the origin
will cause the "flipping" you refer to because the camera is trying to remain "right side up", and it will quickly change orientation as it passes over the "north pole."
If you offset the camera's x-coordinate like so,
camera.position.x = 200;
the camera behavior will appear more natural to you.
Three.js tries to keep the camera facing up. When you pass 0 along the z-axis, it'll "fix" the camera's rotation. You can just check and reset the camera's angle manually.
camera.lookAt( scene.position ); // the origin
if (camera.position.z < 0) {
camera.rotation.z = 0;
}
I'm sure this is not the best solution, but if anyone else runs across this question while playing with three.js (like I just did), it'll give one step further.
This works for me, I hope it helps.
Rotating around X-Axis:
var x_axis = new THREE.Vector3( 1, 0, 0 );
var quaternion = new THREE.Quaternion;
camera.position.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
camera.up.applyQuaternion(quaternion.setFromAxisAngle(x_axis, rotation_speed));
Rotating around Y-Axis:
var y_axis = new THREE.Vector3( 0, 1, 0 );
camera.position.applyQuaternion(quaternion.setFromAxisAngle(y_axis, angle));
Rotating around Z-Axis:
var z_axis = new THREE.Vector3( 0, 0, 1 );
camera.up.applyQuaternion(quaternion.setFromAxisAngle(z_axis, angle));
I wanted to move my camera to a new location while having the camera look at a particular object, and this is what I came up with [make sure to load tween.js]:
/**
* Helper to move camera
* #param loc Vec3 - where to move the camera; has x, y, z attrs
* #param lookAt Vec3 - where the camera should look; has x, y, z attrs
* #param duration int - duration of transition in ms
**/
function flyTo(loc, lookAt, duration) {
// Use initial camera quaternion as the slerp starting point
var startQuaternion = camera.quaternion.clone();
// Use dummy camera focused on target as the slerp ending point
var dummyCamera = camera.clone();
dummyCamera.position.set(loc.x, loc.y, loc.z);
// set the dummy camera quaternion
var rotObjectMatrix = new THREE.Matrix4();
rotObjectMatrix.makeRotationFromQuaternion(startQuaternion);
dummyCamera.quaternion.setFromRotationMatrix(rotObjectMatrix);
dummyCamera.up.set(camera)
console.log(camera.quaternion, dummyCamera.quaternion);
// create dummy controls to avoid mutating main controls
var dummyControls = new THREE.TrackballControls(dummyCamera);
dummyControls.target.set(loc.x, loc.y, loc.z);
dummyControls.update();
// Animate between the start and end quaternions
new TWEEN.Tween(camera.position)
.to(loc, duration)
.onUpdate(function(timestamp) {
// Slerp the camera quaternion for smooth transition.
// `timestamp` is the eased time value from the tween.
THREE.Quaternion.slerp(startQuaternion, dummyCamera.quaternion, camera.quaternion, timestamp);
camera.lookAt(lookAt);
})
.onComplete(function() {
controls.target = new THREE.Vector3(scene.children[1].position-0.001);
camera.lookAt(lookAt);
}).start();
}
Example usage:
var pos = {
x: -4.3,
y: 1.7,
z: 7.3,
};
var lookAt = scene.children[1].position;
flyTo(pos, lookAt, 60000);
Then in your update()/render() function, call TWEEN.update();
Full example

Physical simulation of realistic two-legged skeleton

I wish to utilize bullet-physics or similar physical-engine to create a realistic skeleton simulation of human-like body with two legs. That is, create a simulation of "a body" made of round mass on top of two "legs", where each leg is made of 3 solid pieces connected through 3 joints and each joint have some degrees of freedom and a limited movement range in each direction, similar to human hip, knee and ankle.
I aim for a realistic model, and hence it will 'stand' only if all joints are balanced correctly and it will fall otherwise.
Any directions, suggestion or pointers to existing tutorials or resources is appreciated! This looks like an awful lot of work doing from scratch...
Check out the OpenSim project (opensim.stanford.edu), which is heavily used by the biomechanics community to study human movement for, e.g., clinical applications. In OpenSim, the human models are often actuated by muscles, not simply by torques at the joints.
OpenSim is built on top of the Simbody multibody dynamics library. See this example from Simbody to hit the ground running with a model of a humanoid: https://github.com/simbody/simbody/blob/master/Simbody/examples/JaredsDude.cpp.
I'm working on similar code at the moment. My approach is use the Bullet Physics Rag Doll Demo as a starting point. It has a rag doll with body parts connected by joints.
I'm then using the Bullet Physics Dynamic Control Demo to learn to bend the joints. The challenging part at the moment is setting all the parameters.
I suggest you learn how to create two rigid bodies connected by a constraint and then to activate the constraint motor to bend the joint.
The following is some code that I'm working with to learn how rigid bodies and constraints work in Bullet Physics. The code creates two blocks connected by a hinge constraint. The update function bends the hinge constraint slowly over time.
Now that I've got this I'll be going back to the Rag Doll and adjusting the joints.
class Simple
{
private:
btScalar targetAngle;
btCollisionShape* alphaCollisionShape;
btCollisionShape* bravoCollisionShape;
btRigidBody* alphaRigidBody;
btRigidBody* bravoRigidBody;
btHingeConstraint* hingeConstraint;
btDynamicsWorld* dynamicsWorld;
public:
~Simple( void )
{
}
btRigidBody* createRigidBody( btCollisionShape* collisionShape,
btScalar mass,
const btTransform& transform ) const
{
// calculate inertia
btVector3 localInertia( 0.0f, 0.0f, 0.0f );
collisionShape->calculateLocalInertia( mass, localInertia );
// create motion state
btDefaultMotionState* defaultMotionState
= new btDefaultMotionState( transform );
// create rigid body
btRigidBody::btRigidBodyConstructionInfo rigidBodyConstructionInfo(
mass, defaultMotionState, collisionShape, localInertia );
btRigidBody* rigidBody = new btRigidBody( rigidBodyConstructionInfo );
return rigidBody;
}
void Init( btDynamicsWorld* dynamicsWorld )
{
this->targetAngle = 0.0f;
this->dynamicsWorld = dynamicsWorld;
// create collision shapes
const btVector3 alphaBoxHalfExtents( 0.5f, 0.5f, 0.5f );
alphaCollisionShape = new btBoxShape( alphaBoxHalfExtents );
//
const btVector3 bravoBoxHalfExtents( 0.5f, 0.5f, 0.5f );
bravoCollisionShape = new btBoxShape( bravoBoxHalfExtents );
// create alpha rigid body
const btScalar alphaMass = 10.0f;
btTransform alphaTransform;
alphaTransform.setIdentity();
const btVector3 alphaOrigin( 54.0f, 0.5f, 50.0f );
alphaTransform.setOrigin( alphaOrigin );
alphaRigidBody = createRigidBody( alphaCollisionShape, alphaMass, alphaTransform );
dynamicsWorld->addRigidBody( alphaRigidBody );
// create bravo rigid body
const btScalar bravoMass = 1.0f;
btTransform bravoTransform;
bravoTransform.setIdentity();
const btVector3 bravoOrigin( 56.0f, 0.5f, 50.0f );
bravoTransform.setOrigin( bravoOrigin );
bravoRigidBody = createRigidBody( bravoCollisionShape, bravoMass, bravoTransform );
dynamicsWorld->addRigidBody( bravoRigidBody );
// create a constraint
const btVector3 pivotInA( 1.0f, 0.0f, 0.0f );
const btVector3 pivotInB( -1.0f, 0.0f, 0.0f );
btVector3 axisInA( 0.0f, 1.0f, 0.0f );
btVector3 axisInB( 0.0f, 1.0f, 0.0f );
bool useReferenceFrameA = false;
hingeConstraint = new btHingeConstraint(
*alphaRigidBody,
*bravoRigidBody,
pivotInA,
pivotInB,
axisInA,
axisInB,
useReferenceFrameA );
// set constraint limit
const btScalar low = -M_PI;
const btScalar high = M_PI;
hingeConstraint->setLimit( low, high );
// add constraint to the world
const bool isDisableCollisionsBetweenLinkedBodies = false;
dynamicsWorld->addConstraint( hingeConstraint,
isDisableCollisionsBetweenLinkedBodies );
}
void Update( float deltaTime )
{
alphaRigidBody->activate();
bravoRigidBody->activate();
bool isEnableMotor = true;
btScalar maxMotorImpulse = 1.0f; // 1.0f / 8.0f is about the minimum
hingeConstraint->enableMotor( isEnableMotor );
hingeConstraint->setMaxMotorImpulse( maxMotorImpulse );
targetAngle += 0.1f * deltaTime;
hingeConstraint->setMotorTarget( targetAngle, deltaTime );
}
};
Just found "Computer Simulation Study of Human Locomotion with a Three-Dimensional Entire-Body Neuro-Musculo-Skeletal Model" by Hase & Yamazaki (2002), which provide
A model having a three-dimensional entire-body structure and consisting of both the neuronal system and the musculo-skeletal system was proposed to precisely simulate human walking motion. The dynamics of the human body was represented by a 14-rigid-link system and 60 muscular models
Doing from scratch will be hard, no doubt about it. I don't know what your goal is. But you don't have to redesign the wheel. Have you taken a look at the Unreal Engine? You might find something to reuse there. Many games are built on the top of this engine.