Esempio n. 1
0
/*!
Updates the axis aligned bounding box in world space. 
*/
SLAABBox& SLNode::updateAABBRec()
{
    if (_isAABBUpToDate)
        return _aabb;

    // empty the AABB (= max negative AABB)
    if (_meshes.size() > 0 || _children.size() > 0)
    {   _aabb.minWS(SLVec3f( FLT_MAX, FLT_MAX, FLT_MAX));
        _aabb.maxWS(SLVec3f(-FLT_MAX,-FLT_MAX,-FLT_MAX));  
    }

    // Build or update AABB of meshes & merge them to the nodes aabb in WS
    for (auto mesh : _meshes)
    {   SLAABBox aabbMesh;
        mesh->buildAABB(aabbMesh, updateAndGetWM());
        _aabb.mergeWS(aabbMesh);
    }
    
    // Merge children in WS
    for (auto child : _children)
        if (typeid(*child)!=typeid(SLCamera))
            _aabb.mergeWS(child->updateAABBRec());

    // We need min & max also in OS for the uniform grid intersection in OS
    _aabb.fromWStoOS(_aabb.minWS(), _aabb.maxWS(), updateAndGetWMI());

    // For visualizing the nodes orientation we finally update the axis in WS
    _aabb.updateAxisWS(updateAndGetWM());

    _isAABBUpToDate = true;
    return _aabb;
}
Esempio n. 2
0
/*!
Intersects the nodes meshes with the given ray. The intersection
test is only done if the AABB is intersected. The ray-mesh intersection is
done in the nodes object space. The rays origin and direction is therefore 
transformed into the object space.
*/
bool SLNode::hitRec(SLRay* ray)
{
    assert(ray != 0);

    // Do not test hidden nodes
    if (_drawBits.get(SL_DB_HIDDEN)) 
        return false;

    // Do not test origin node for shadow rays 
    if (this==ray->srcNode && ray->type==SHADOW) 
        return false;
   
    // Check first AABB for intersection
    if (!_aabb.isHitInWS(ray)) 
        return false;


    SLbool wasHit = false;
   
    // Transform ray to object space for non-groups
    if (_meshes.size() > 0)    
    {  
        // transform origin position to object space
        ray->originOS.set(updateAndGetWMI().multVec(ray->origin));
         
        // transform the direction only with the linear sub matrix
        ray->setDirOS(_wmI.mat3() * ray->dir);

        // test all meshes
        for (auto mesh : _meshes)
        {   if (mesh->hit(ray, this) && !wasHit) 
                wasHit = true;
            if (ray->isShaded()) 
                return true;
        }
    }

    // Test children nodes
    for (auto child : _children)
    {   if (child->hitRec(ray) && !wasHit) 
            wasHit = true;
        if (ray->isShaded()) 
            return true;
    }

    return wasHit;
}
Esempio n. 3
0
/*!
Applies the view transform to the modelview matrix depending on the eye:
eye=-1 for left, eye=1 for right
*/
void SLCamera::setView(SLSceneView* sv, const SLEye eye)
{  
    SLScene* s = SLScene::current;
   
    SLMat4f vm = updateAndGetWMI();

    if (eye == centerEye)
    {   _stateGL->modelViewMatrix.identity();
        _stateGL->viewMatrix.setMatrix(vm);
    } 
    else // stereo viewing
    {
        if (_projection == stereoSideBySideD)
        {  
            // half interpupilar disqtance
            //_eyeSeparation = s->oculus()->interpupillaryDistance(); update old rift code
            SLfloat halfIPD = (SLfloat)eye * _eyeSeparation * -0.5f;
            
            SLMat4f trackingPos;
            if (_useDeviceRot)
            {
                // get the oculus or mobile device orientation
                SLQuat4f rotation;
                if (s->oculus()->isConnected())
                {
                    rotation = s->oculus()->orientation(eye);
                    trackingPos.translate(-s->oculus()->position(eye));
                }
                else rotation = sv->deviceRotation();

                SLfloat rotX, rotY, rotZ;
                rotation.toMat4().toEulerAnglesZYX(rotZ, rotY, rotX);
                //SL_LOG("rotx : %3.1f, roty: %3.1f, rotz: %3.1f\n", rotX*SL_RAD2DEG, rotY*SL_RAD2DEG, rotZ*SL_RAD2DEG);
                SLVec3f viewAdjust = s->oculus()->viewAdjust(eye) * _unitScaling;
                SLMat4f vmEye(SLMat4f(viewAdjust.x, viewAdjust.y, viewAdjust.z) * rotation.inverted().toMat4() * trackingPos * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            } 
            else
            {      
                SLMat4f vmEye(SLMat4f(halfIPD, 0.0f, 0.f) * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            }
        }
        else
        {
            // Get central camera vectors eye, lookAt, lookUp out of the view matrix vm
            SLVec3f EYE, LA, LU, LR;
            vm.lookAt(&EYE, &LA, &LU, &LR);
   
            // Shorten LR to half of the eye dist (eye=-1 for left, eye=1 for right)
            LR *= _eyeSeparation * 0.5f * (SLfloat)eye;
      
            // Set the OpenGL view matrix for the left eye
            SLMat4f vmEye;
            vmEye.lookAt(EYE+LR, EYE + _focalDist*LA+LR, LU);
            _stateGL->modelViewMatrix = vmEye;
            _stateGL->viewMatrix = vmEye;
        }
    } 
}
Esempio n. 4
0
/*!
Sets the projection transformation matrix, the viewport transformation and the
drawing buffer. In case of a stereographic projection it additionally sets the
stereo splitting parameters such as the color masks and the color filter matrix
for stereo color anaglyphs. 
*/
void SLCamera::setProjection(SLSceneView* sv, const SLEye eye)
{  
    ////////////////////
    // Set Projection //
    ////////////////////

    const SLMat4f& vm = updateAndGetWMI();

    _stateGL->stereoEye  = eye;
    _stateGL->projection = _projection;
   
    SLVec3f pos(vm.translation());
    SLfloat top, bottom, left, right, d;   // frustum paramters
    _scrW = sv->scrW();
    _scrH = sv->scrH();
    _aspect = sv->scrWdivH();
   
    switch (_projection) 
    {  
        case monoPerspective:
            _stateGL->projectionMatrix.perspective(_fov, sv->scrWdivH(), _clipNear, _clipFar);
            break;

        case monoOrthographic:
            top    = tan(SL_DEG2RAD*_fov*0.5f) * pos.length();
            bottom = -top;
            left   = -sv->scrWdivH()*top;
            right  = -left;

            // The ortographic projection should have its near clip plane behind the camera
            // rather than slightly in front of it. Else we will see cross sections of scenes if
            // we zoom in close
            _stateGL->projectionMatrix.ortho(left,right,bottom,top, -_clipNear, _clipFar);
            break;

        case stereoSideBySideD:
            _stateGL->projectionMatrix = SLScene::current->oculus()->projection(eye);

            break;
        // all other stereo projections
        default: 
            // assymetric frustum shift d (see chapter stereo projection)
            d = (SLfloat)eye * 0.5f * _eyeSeparation * _clipNear / _focalDist;
            top    = tan(SL_DEG2RAD*_fov/2) * _clipNear;
            bottom = -top;
            left   = -sv->scrWdivH()*top - d;
            right  =  sv->scrWdivH()*top - d;
            _stateGL->projectionMatrix.frustum(left,right,bottom,top,_clipNear,_clipFar);
    }
   
    //////////////////
    // Set Viewport //
    //////////////////
   
    SLint w = sv->scrW();
    SLint h = sv->scrH();
    SLint w2 = sv->scrWdiv2();
    SLint h2 = sv->scrHdiv2();
    SLint h4 = h2 >> 1;
   
    if (_projection == stereoSideBySideD)
    {   SLint fbW2 = sv->oculusFB()->halfWidth();
        SLint fbH  = sv->oculusFB()->height();
        if (eye==leftEye) 
             _stateGL->viewport(   0, 0, fbW2, fbH);
        else _stateGL->viewport(fbW2, 0, fbW2, fbH);
    } else
    if (_projection == stereoSideBySide)
    {  
        if (eye==leftEye) 
             _stateGL->viewport( 0, 0, w2, h);
        else _stateGL->viewport(w2, 0, w2, h);
    } else
    if (_projection == stereoSideBySideP)
    {  
        if (eye==leftEye) 
             _stateGL->viewport( 0, h4, w2, h2);
        else _stateGL->viewport(w2, h4, w2, h2);
    } else  
        _stateGL->viewport(0, 0, w, h);
   

    ///////////////////
    // Clear Buffers //
    ///////////////////

    if (eye==rightEye) //&& _projection >= stereoColorRC) 
        // Do not clear color on right eye because it contains the color of the
        // left eye. The right eye must be drawn after the left into the same buffer
        _stateGL->clearDepthBuffer();
   
    //  Set Color Mask and Filter
    if (_projection >= stereoColorRC)
    {   if (eye==leftEye)
        {  switch (_projection) 
            {   case stereoColorRC: _stateGL->colorMask(1, 0, 0, 1); break;
                case stereoColorRB: _stateGL->colorMask(1, 0, 0, 1); break;
                case stereoColorRG: _stateGL->colorMask(1, 0, 0, 1); break;
                case stereoColorYB: _stateGL->colorMask(1, 1, 0, 1); break;
                default: break;
            }
        } else
        {   switch (_projection) 
            {   case stereoColorRC: _stateGL->colorMask(0, 1, 1, 1); break;
                case stereoColorRB: _stateGL->colorMask(0, 0, 1, 1); break;
                case stereoColorRG: _stateGL->colorMask(0, 1, 0, 1); break;
                case stereoColorYB: _stateGL->colorMask(0, 0, 1, 1); break;
                default: break;
            }
        }
      
        // Set color filter matrix for red-cyan and yello-blue (ColorCode3D)
        switch (_projection) 
        {   case stereoColorRC:
            _stateGL->stereoColorFilter.setMatrix(0.29f, 0.59f, 0.12f,
                                                  0.00f, 1.00f, 0.00f,
                                                  0.00f, 0.00f, 1.00f); break;
            case stereoColorYB:
            _stateGL->stereoColorFilter.setMatrix(1.00f, 0.00f, 0.00f,
                                                  0.00f, 1.00f, 0.00f,
                                                  0.15f, 0.15f, 0.70f); break;
            default: break;
        }
    }
    GET_GL_ERROR;
}
Esempio n. 5
0
/*!
Only draws the frustum lines without lighting when the camera is not the 
active one. This means that it can be seen from the active view point.
*/
void SLCamera::drawMeshes(SLSceneView* sv) 
{  
    if (sv->camera()!=this)
    {
        if (_projection == monoOrthographic)
        {
            const SLMat4f& vm = updateAndGetWMI();
            SLVec3f P[17*2];
            SLuint  i=0;
            SLVec3f pos(vm.translation());
            SLfloat t = tan(SL_DEG2RAD*_fov*0.5f) * pos.length();
            SLfloat b = -t;
            SLfloat l = -sv->scrWdivH() * t;
            SLfloat r = -l;

            // small line in view direction
            P[i++].set(0,0,0); P[i++].set(0,0,_clipNear*4);

            // frustum pyramid lines
            P[i++].set(r,t,_clipNear); P[i++].set(r,t,-_clipFar);
            P[i++].set(l,t,_clipNear); P[i++].set(l,t,-_clipFar);
            P[i++].set(l,b,_clipNear); P[i++].set(l,b,-_clipFar);
            P[i++].set(r,b,_clipNear); P[i++].set(r,b,-_clipFar);

            // around far clipping plane
            P[i++].set(r,t,-_clipFar); P[i++].set(r,b,-_clipFar);
            P[i++].set(r,b,-_clipFar); P[i++].set(l,b,-_clipFar);
            P[i++].set(l,b,-_clipFar); P[i++].set(l,t,-_clipFar);
            P[i++].set(l,t,-_clipFar); P[i++].set(r,t,-_clipFar);

            // around projection plane at focal distance
            P[i++].set(r,t,-_focalDist); P[i++].set(r,b,-_focalDist);
            P[i++].set(r,b,-_focalDist); P[i++].set(l,b,-_focalDist);
            P[i++].set(l,b,-_focalDist); P[i++].set(l,t,-_focalDist);
            P[i++].set(l,t,-_focalDist); P[i++].set(r,t,-_focalDist);

            // around near clipping plane
            P[i++].set(r,t,_clipNear); P[i++].set(r,b,_clipNear);
            P[i++].set(r,b,_clipNear); P[i++].set(l,b,_clipNear);
            P[i++].set(l,b,_clipNear); P[i++].set(l,t,_clipNear);
            P[i++].set(l,t,_clipNear); P[i++].set(r,t,_clipNear);

            _bufP.generate(P, i, 3);
        }
        else
        {
            SLVec3f P[17*2];
            SLuint  i=0;
            SLfloat aspect = sv->scrWdivH();
            SLfloat tanFov = tan(_fov*SL_DEG2RAD*0.5f);
            SLfloat tF =  tanFov * _clipFar;    //top far
            SLfloat rF =  tF * aspect;          //right far
            SLfloat lF = -rF;                   //left far
            SLfloat tP =  tanFov * _focalDist;  //top projection at focal distance
            SLfloat rP =  tP * aspect;          //right projection at focal distance
            SLfloat lP = -tP * aspect;          //left projection at focal distance
            SLfloat tN =  tanFov * _clipNear;   //top near
            SLfloat rN =  tN * aspect;          //right near
            SLfloat lN = -tN * aspect;          //left near

            // small line in view direction
            P[i++].set(0,0,0); P[i++].set(0,0,_clipNear*4);

            // frustum pyramid lines
            P[i++].set(0,0,0); P[i++].set(rF, tF,-_clipFar);
            P[i++].set(0,0,0); P[i++].set(lF, tF,-_clipFar);
            P[i++].set(0,0,0); P[i++].set(lF,-tF,-_clipFar);
            P[i++].set(0,0,0); P[i++].set(rF,-tF,-_clipFar);

            // around far clipping plane
            P[i++].set(rF, tF,-_clipFar); P[i++].set(rF,-tF,-_clipFar);
            P[i++].set(rF,-tF,-_clipFar); P[i++].set(lF,-tF,-_clipFar);
            P[i++].set(lF,-tF,-_clipFar); P[i++].set(lF, tF,-_clipFar);
            P[i++].set(lF, tF,-_clipFar); P[i++].set(rF, tF,-_clipFar);

            // around projection plane at focal distance
            P[i++].set(rP, tP,-_focalDist); P[i++].set(rP,-tP,-_focalDist);
            P[i++].set(rP,-tP,-_focalDist); P[i++].set(lP,-tP,-_focalDist);
            P[i++].set(lP,-tP,-_focalDist); P[i++].set(lP, tP,-_focalDist);
            P[i++].set(lP, tP,-_focalDist); P[i++].set(rP, tP,-_focalDist);

            // around near clipping plane
            P[i++].set(rN, tN,-_clipNear); P[i++].set(rN,-tN,-_clipNear);
            P[i++].set(rN,-tN,-_clipNear); P[i++].set(lN,-tN,-_clipNear);
            P[i++].set(lN,-tN,-_clipNear); P[i++].set(lN, tN,-_clipNear);
            P[i++].set(lN, tN,-_clipNear); P[i++].set(rN, tN,-_clipNear);

            _bufP.generate(P, i, 3);
        }
      
        _bufP.drawArrayAsConstantColorLines(SLCol3f::WHITE*0.7f);
    }
}