END_TEST;
}
+int UtcDaliCoreSetStereoBase(void)
+{
+ TestApplication application;
+ tet_infoline("Testing Dali::GetMaximumUpdateCount");
+
+ application.GetCore().SetViewMode( STEREO_HORIZONTAL );
+ DALI_TEST_EQUALS( application.GetCore().GetViewMode(), STEREO_HORIZONTAL, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ application.GetCore().SetViewMode( STEREO_VERTICAL );
+ DALI_TEST_EQUALS( application.GetCore().GetViewMode(), STEREO_VERTICAL, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ application.GetCore().SetViewMode( MONO );
+ DALI_TEST_EQUALS( application.GetCore().GetViewMode(), MONO, TEST_LOCATION );
+
+ application.SendNotification();
+ application.Render();
+
+ END_TEST;
+}
+
#define DALI_INTEGRATION_CORE_ENUMERATIONS_H
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// EXTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/view-mode.h>
#include <dali/integration-api/context-notifier.h>
#include <dali/integration-api/resource-policies.h>
return mImpl->GetSystemOverlay();
}
+void Core::SetViewMode( ViewMode viewMode )
+{
+ mImpl->SetViewMode( viewMode );
+}
+
+ViewMode Core::GetViewMode() const
+{
+ return mImpl->GetViewMode();
+}
+
+void Core::SetStereoBase( float stereoBase )
+{
+ mImpl->SetStereoBase( stereoBase );
+}
+
+float Core::GetStereoBase() const
+{
+ return mImpl->GetStereoBase();
+}
+
void Core::RegisterProcessor( Processor& processor )
{
mImpl->RegisterProcessor( processor );
// INTERNAL INCLUDES
#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/view-mode.h>
#include <dali/integration-api/context-notifier.h>
#include <dali/integration-api/core-enumerations.h>
#include <dali/integration-api/resource-policies.h>
SystemOverlay& GetSystemOverlay();
/**
+ * Set the stereoscopic 3D view mode
+ * @param[in] viewMode The new view mode
+ */
+ void SetViewMode( ViewMode viewMode );
+
+ /**
+ * Get the current view mode
+ * @return The current view mode
+ * @see SetViewMode.
+ */
+ ViewMode GetViewMode() const;
+
+ /**
+ * Set the stereo base (eye seperation) for stereoscopic 3D
+ * @param[in] stereoBase The stereo base (eye seperation) for stereoscopic 3D (mm)
+ */
+ void SetStereoBase( float stereoBase );
+
+ /**
+ * Get the stereo base (eye seperation) for stereoscopic 3D
+ * @return The stereo base (eye seperation) for stereoscopic 3D (mm)
+ */
+ float GetStereoBase() const;
+
+ /**
* @brief Register a processor
*
* Note, Core does not take ownership of this processor.
return mStage->GetSystemOverlay();
}
+void Core::SetViewMode( ViewMode viewMode )
+{
+ mStage->SetViewMode( viewMode );
+}
+
+ViewMode Core::GetViewMode() const
+{
+ return mStage->GetViewMode();
+}
+
+void Core::SetStereoBase( float stereoBase )
+{
+ mStage->SetStereoBase( stereoBase );
+}
+
void Core::RegisterProcessor( Integration::Processor& processor )
{
mProcessors.PushBack(&processor);
}
}
+float Core::GetStereoBase() const
+{
+ return mStage->GetStereoBase();
+}
+
StagePtr Core::GetCurrentStage()
{
return mStage.Get();
#include <dali/internal/common/owner-pointer.h>
#include <dali/internal/event/animation/animation-playlist-declarations.h>
#include <dali/internal/event/common/stage-def.h>
+#include <dali/public-api/common/view-mode.h>
#include <dali/integration-api/resource-policies.h>
namespace Dali
*/
Integration::SystemOverlay& GetSystemOverlay();
+ // Stereoscopy
+
+ /**
+ * @copydoc Dali::Integration::Core::SetViewMode()
+ */
+ void SetViewMode( ViewMode viewMode );
+
+ /**
+ * @copydoc Dali::Integration::Core::GetViewMode()
+ */
+ ViewMode GetViewMode() const;
+
+ /**
+ * @copydoc Dali::Integration::Core::SetStereoBase()
+ */
+ void SetStereoBase( float stereoBase );
+
+ /**
+ * @copydoc Dali::Integration::Core::GetStereoBase()
+ */
+ float GetStereoBase() const;
+
+
/**
* @copydoc Dali::Integration::Core::RegisterProcessor
*/
const float aspectRatio = width / height;
- // sceneObject is being used in a separate thread; queue a message to set
SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
SetFieldOfView( fieldOfView );
SetNearClippingPlane( nearClippingPlane );
SetFarClippingPlane( farClippingPlane );
SetAspectRatio( aspectRatio );
+ // sceneObject is being used in a separate thread; queue a message to set
+ SetStereoBiasMessage( GetEventThreadServices(), *mSceneObject, stereoBias );
SetZ( cameraZ );
}
// Create the list of render-tasks
mRenderTaskList = RenderTaskList::New();
- // Create the default render-task (don't need the returned handle)
- mRenderTaskList->CreateTask( mRootLayer.Get(), mDefaultCamera.Get() );
+ // Create the default render-task
+ Dali::RenderTask defaultRenderTask = mRenderTaskList->CreateTask( mRootLayer.Get(), mDefaultCamera.Get() );
}
void Stage::Uninitialize()
return overlay;
}
+void Stage::SetViewMode( ViewMode viewMode )
+{
+ if( mViewMode != viewMode )
+ {
+ DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "View mode changed from %d to %d\n", mViewMode, viewMode);
+
+ if( mViewMode == MONO )
+ {
+ mDefaultCamera->SetOrientation( Dali::ANGLE_180, Vector3::YAXIS );
+ mRenderTaskList->GetTask(0).SetSourceActor( Dali::Actor() );
+
+ //Create camera and RenderTask for left eye
+ mLeftCamera = CameraActor::New( Size::ZERO );
+ mLeftCamera->SetParentOrigin( ParentOrigin::CENTER );
+ mDefaultCamera->Add( *mLeftCamera.Get() );
+ mLeftRenderTask = mRenderTaskList->CreateTask();
+ mLeftRenderTask.SetCameraActor( Dali::CameraActor( mLeftCamera.Get() ) );
+ mLeftCamera->SetType( Dali::Camera::FREE_LOOK );
+
+ //Create camera and RenderTask for right eye
+ mRightCamera = CameraActor::New( Size::ZERO );
+ mRightCamera->SetParentOrigin( ParentOrigin::CENTER );
+ mDefaultCamera->Add( *mRightCamera.Get() );
+ mRightRenderTask = mRenderTaskList->CreateTask();
+ mRightRenderTask.SetClearColor( Vector4( 1.0f,0.0f,0.0f,1.0f));
+
+ mRightRenderTask.SetCameraActor( Dali::CameraActor( mRightCamera.Get() ) );
+ mRightCamera->SetType( Dali::Camera::FREE_LOOK );
+ }
+
+ // save new mode
+ mViewMode = viewMode;
+
+ switch( viewMode )
+ {
+ case MONO:
+ {
+ // delete extra stereoscopic render tasks and cameras
+ mRenderTaskList->RemoveTask( mLeftRenderTask );
+ mDefaultCamera->Remove( *mLeftCamera.Get() );
+ mLeftRenderTask.Reset();
+ mLeftCamera.Reset();
+ mRenderTaskList->RemoveTask( mRightRenderTask );
+ mDefaultCamera->Remove( *mRightCamera.Get() );
+ mRightRenderTask.Reset();
+ mRightCamera.Reset();
+ mDefaultCamera->SetOrientation( Dali::ANGLE_0, Vector3::YAXIS );
+ mDefaultCamera->SetType( Dali::Camera::LOOK_AT_TARGET );
+ mRenderTaskList->GetTask(0).SetSourceActor( Dali::Layer(mRootLayer.Get()) );
+
+ break;
+ }
+ case STEREO_HORIZONTAL:
+ {
+ //Stereo mode with horizontal split is for landscape mode. That's the reason for the cameras being rotated
+ //Top camera renders the scene as seen from the right eye and bottom camera as seen from left.
+
+ //Calculate separation in pixels along vertical axis ( mStereoBase is defined in millimetres )
+ const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().y ) * 0.5f );
+
+ //Calculate aspect ratio
+ float aspect = mSize.width / (mSize.height * 0.5f);
+
+ mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0f,stereoBase) );
+ mLeftCamera->SetAspectRatio( aspect );
+
+ mLeftCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
+ mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+ mLeftRenderTask.SetViewport( Viewport(0, static_cast<int32_t>( mSize.height * 0.5f ), static_cast<int32_t>( mSize.width ), static_cast<int32_t>( mSize.height * 0.5f ) ) ); // truncated
+
+ mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, -stereoBase ) );
+ mRightCamera->SetAspectRatio( aspect );
+ mRightCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
+ mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+ mRightRenderTask.SetViewport( Viewport(0, 0, static_cast<int32_t>( mSize.width ), static_cast<int32_t>( mSize.height * 0.5f ) ) ); // truncated
+
+ break;
+ }
+ case STEREO_VERTICAL:
+ {
+ //Calculate separation in pixels along horizontal axis
+ const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().x ) * 0.5f );
+
+ //Recalculate fov based on viewport size
+ const float fov = 2.0f * std::atan( mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
+
+ mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
+ mLeftCamera->SetFieldOfView( fov );
+ mLeftCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
+ mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+ mLeftRenderTask.SetViewport( Viewport(0, 0, static_cast<int32_t>( mSize.width * 0.5f ), static_cast<int32_t>( mSize.height ) ) ); // truncated
+
+ mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
+ mRightCamera->SetFieldOfView( fov );
+ mRightCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
+ mRightCamera->SetPosition( Vector3( -stereoBase, 0.0f, 0.0f ) );
+ mRightRenderTask.SetViewport( Viewport( static_cast<int32_t>( mSize.width * 0.5f ), 0, static_cast<int32_t>( mSize.width * 0.5f ), static_cast<int32_t>( mSize.height ) ) ); // truncated
+
+ break;
+ }
+ case STEREO_INTERLACED:
+ {
+ break;
+ }
+ }
+ }
+}
+
+ViewMode Stage::GetViewMode() const
+{
+ return mViewMode;
+}
+
+void Stage::SetStereoBase( float stereoBase )
+{
+ if( ! Equals( mStereoBase, stereoBase ) )
+ {
+ DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "old( %.2f) new(%.2f)\n", mStereoBase, stereoBase );
+ mStereoBase = stereoBase;
+
+ switch( mViewMode )
+ {
+ case STEREO_HORIZONTAL:
+ {
+ stereoBase = mStereoBase / 25.4f * GetDpi().y * 0.5f;
+ float aspect = mSize.width / (mSize.height * 0.5f);
+
+ mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, stereoBase) );
+ mLeftCamera->SetAspectRatio( aspect );
+ mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+
+ mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, -stereoBase) );
+ mRightCamera->SetAspectRatio( aspect );
+ mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+
+ break;
+ }
+ case STEREO_VERTICAL:
+ {
+ stereoBase = mStereoBase / 25.4f * GetDpi().x * 0.5f;
+ const float fov = 2.0f * std::atan( mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
+
+ mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
+ mLeftCamera->SetFieldOfView( fov );
+ mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+
+ mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
+ mRightCamera->SetFieldOfView( fov );
+ mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+float Stage::GetStereoBase() const
+{
+ return mStereoBase;
+}
+
void Stage::SetBackgroundColor(Vector4 color)
{
// Cache for public GetBackgroundColor()
mSize( Vector2::ZERO ),
mSurfaceSize( Vector2::ZERO ),
mBackgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
+ mViewMode( MONO ),
+ mStereoBase( DEFAULT_STEREO_BASE ),
mTopMargin( 0 ),
mDpi( Vector2::ZERO ),
+ mRightRenderTask(),
+ mLeftRenderTask(),
mSystemOverlay( NULL ),
mKeyEventSignal(),
mKeyEventGeneratedSignal(),
*/
// INTERNAL INCLUDES
-#include <dali/public-api/common/stage.h>
#include <dali/public-api/object/ref-object.h>
-#include <dali/public-api/object/base-object.h>
-#include <dali/public-api/math/vector2.h>
-#include <dali/public-api/math/vector3.h>
-#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/common/stage.h>
#include <dali/devel-api/common/stage-devel.h>
+#include <dali/public-api/object/base-object.h>
#include <dali/integration-api/context-notifier.h>
#include <dali/internal/common/owner-pointer.h>
#include <dali/internal/event/actors/layer-impl.h>
#include <dali/internal/event/common/stage-def.h>
#include <dali/internal/event/render-tasks/render-task-defaults.h>
#include <dali/internal/update/manager/update-manager.h>
-#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/public-api/common/view-mode.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/render-tasks/render-task.h>
namespace Dali
{
*/
SystemOverlay* GetSystemOverlayInternal();
+ // Stereoscopy
+
+ /**
+ * @copydoc Dali::Integration::Core::SetViewMode()
+ */
+ void SetViewMode( ViewMode viewMode );
+
+ /**
+ * @copydoc Dali::Integration::Core::GetViewMode()
+ */
+ ViewMode GetViewMode() const;
+
+ /**
+ * @copydoc Dali::Integration::Core::SetStereoBase()
+ */
+ void SetStereoBase( float stereoBase );
+
+ /**
+ * @copydoc Dali::Integration::Core::GetStereoBase()
+ */
+ float GetStereoBase() const;
+
// Keyboard stuff
/**
IntrusivePtr<CameraActor> mDefaultCamera;
+ ViewMode mViewMode;
+ float mStereoBase;
+
uint32_t mTopMargin;
Vector2 mDpi;
// The list of render-tasks
IntrusivePtr<RenderTaskList> mRenderTaskList;
+ Dali::RenderTask mRightRenderTask;
+ IntrusivePtr<CameraActor> mRightCamera;
+ Dali::RenderTask mLeftRenderTask;
+ IntrusivePtr<CameraActor> mLeftCamera;
+
Integration::SystemOverlay* mSystemOverlay; ///< SystemOverlay stage access
// The key event signal
m[12] = m[13] = m[15] = 0.0f;
}
-void Perspective(Matrix& result, float fovy, float aspect, float near, float far, bool invertYAxis )
+void Perspective(Matrix& result, float fovy, float aspect, float near, float far, bool invertYAxis, const Vector2& stereoBias )
{
float frustumH = tanf( fovy * 0.5f ) * near;
float frustumW = frustumH * aspect;
+ Vector2 bias = stereoBias * 0.5f;
- Frustum(result, -frustumW, frustumW, -frustumH, frustumH, near, far, invertYAxis);
+ Frustum(result, -(frustumW + bias.x), frustumW - bias.x, -(frustumH + bias.y), frustumH - bias.y, near, far, invertYAxis);
}
void Orthographic(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis)
const float Camera::DEFAULT_BOTTOM_CLIPPING_PLANE(400.0f);
const float Camera::DEFAULT_NEAR_CLIPPING_PLANE( 800.0f ); // default height of the screen
const float Camera::DEFAULT_FAR_CLIPPING_PLANE( DEFAULT_NEAR_CLIPPING_PLANE + 2.f * DEFAULT_NEAR_CLIPPING_PLANE );
+const Vector2 Camera::DEFAULT_STEREO_BIAS( 0.0f, 0.0f );
const Vector3 Camera::DEFAULT_TARGET_POSITION( 0.0f, 0.0f, 0.0f );
mBottomClippingPlane( DEFAULT_BOTTOM_CLIPPING_PLANE ),
mNearClippingPlane( DEFAULT_NEAR_CLIPPING_PLANE ),
mFarClippingPlane( DEFAULT_FAR_CLIPPING_PLANE ),
+ mStereoBias( DEFAULT_STEREO_BIAS ),
mTargetPosition( DEFAULT_TARGET_POSITION ),
mViewMatrix(),
mProjectionMatrix(),
mUpdateProjectionFlag = UPDATE_COUNT;
}
+void Camera::SetStereoBias( const Vector2& stereoBias )
+{
+ mStereoBias = stereoBias;
+ mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
void Camera::SetLeftClippingPlane( float leftClippingPlane )
{
mLeftClippingPlane = leftClippingPlane;
mAspectRatio,
mNearClippingPlane,
mFarClippingPlane,
- mInvertYAxis );
+ mInvertYAxis,
+ mStereoBias );
break;
}
case Dali::Camera::ORTHOGRAPHIC_PROJECTION:
*/
void SetAspectRatio( float aspectRatio );
+ /**
+ * @copydoc Dali::Internal::CameraActor::SetStereoBias
+ */
+ void SetStereoBias(const Vector2& stereoBias);
+
/**
* @copydoc Dali::Internal::CameraActor::SetLeftClippingPlane
*/
float mBottomClippingPlane;
float mNearClippingPlane;
float mFarClippingPlane;
+ Vector2 mStereoBias;
Vector3 mTargetPosition;
InheritedMatrix mViewMatrix; ///< The viewMatrix; this is double buffered for input handling.
new (slot) LocalType( &camera, &Camera::SetAspectRatio, parameter );
}
+inline void SetStereoBiasMessage( EventThreadServices& eventThreadServices, const Camera& camera, const Vector2& parameter )
+{
+ typedef MessageValue1< Camera, Vector2 > LocalType;
+
+ // Reserve some memory inside the message queue
+ uint32_t* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+ // Construct message in the message queue memory; note that delete should not be called on the return value
+ new (slot) LocalType( &camera, &Camera::SetStereoBias, parameter );
+}
+
inline void SetLeftClippingPlaneMessage( EventThreadServices& eventThreadServices, const Camera& camera, float parameter )
{
typedef MessageValue1< Camera, float > LocalType;
#define __DALI_VIEW_MODE_H__
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
enum ViewMode
{
MONO, ///< Monoscopic (single camera). This is the default @SINCE_1_0.0
- STEREO_HORIZONTAL, ///< @DEPRECATED_1_3.39 Stereoscopic. Frame buffer is split horizontally with the left and right camera views in their respective sides. @SINCE_1_0.0
- STEREO_VERTICAL, ///< @DEPRECATED_1_3.39 Stereoscopic. Frame buffer is split vertically with the left camera view at the top and the right camera view at the bottom. @SINCE_1_0.0
+ STEREO_HORIZONTAL, ///< Stereoscopic. Frame buffer is split horizontally with the left and right camera views in their respective sides. @SINCE_1_0.0
+ STEREO_VERTICAL, ///< Stereoscopic. Frame buffer is split vertically with the left camera view at the top and the right camera view at the bottom. @SINCE_1_0.0
STEREO_INTERLACED ///< @DEPRECATED_1_1.19 @brief Stereoscopic. Left/Right camera views are rendered into the framebuffer on alternate frames. @SINCE_1_0.0
};
#define __DALI_CORE_H__
/*
- * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <dali/public-api/common/loading-state.h>
#include <dali/public-api/common/stage.h>
#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/view-mode.h>
#include <dali/public-api/events/gesture-detector.h>
#include <dali/public-api/events/gesture.h>