diff options
author | Zong Wei <wei.zong@intel.com> | 2018-11-23 10:54:02 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-11-23 10:54:02 +0800 |
commit | bd416ed4c25d02803eed1ad71ffbaf6915fe92fe (patch) | |
tree | a210b12bba2c58ae8edb1ec6741270baedc91853 | |
parent | 5982c14b8dd63e16cbf41c48ee18845fabc76e07 (diff) | |
parent | f4413ad0cb070d94b4b168bc8d3011b879464b6d (diff) | |
download | libxcam-upstream-master-backup.tar.gz |
Merge pull request #593 from zongwave/osg_renderupstream-master-backup
render: add OSG based render to show texture on window
* build & install OSG library:
$ git clone https://github.com/openscenegraph/OpenSceneGraph.git
$ cd OpenSceneGraph/
$ mkdir build && cd build
$ cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DOPENGL_PROFILE=GLES2 \
-DOPENGL_gl_LIBRARY=${LIB_MESA_EGL_DIR}/libGLESv2.so \
-DOSG_WINDOWING_SYSTEM=X11 \
-D_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS_EXITCODE=1 \
-DLIB_POSTFIX="" \
-DOSG_CPP_EXCEPTIONS_AVAILABLE=ON \
-DCMAKE_DISABLE_FIND_PACKAGE_CURL=1 \
-DCMAKE_DISABLE_FIND_PACKAGE_FFmpeg=1 \
-DOSG_NOTIFY_DISABLED=ON \
-DOSG_GL_FIXED_FUNCTION_AVAILABLE=OFF \
-DOSG_USE_QT=OFF \
../
# NOTE: Fill in the ${LIB_MESA_EGL_DIR} - e.g.)/usr/lib/x86_64-linux-gnu/mesa-egl
$ make -j8
$ sudo make install
* test command line:
$ ./test-render-surround-view --module soft --input0 video0.yuv --input1 video1.yuv --input2 video2.yuv --input3 video3.yuv --output output.mp4 --in-w 1280 --in-h 800 --out-w 1920 --out-h 640 --loop 1
Signed-off-by: zongwave <wei.zong@intel.com>
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | modules/Makefile.am | 7 | ||||
-rw-r--r-- | modules/render/Makefile.am | 56 | ||||
-rw-r--r-- | modules/render/render_osg_camera_manipulator.cpp | 172 | ||||
-rw-r--r-- | modules/render/render_osg_camera_manipulator.h | 123 | ||||
-rw-r--r-- | modules/render/render_osg_model.cpp | 337 | ||||
-rw-r--r-- | modules/render/render_osg_model.h | 123 | ||||
-rw-r--r-- | modules/render/render_osg_shader.h | 93 | ||||
-rw-r--r-- | modules/render/render_osg_viewer.cpp | 121 | ||||
-rw-r--r-- | modules/render/render_osg_viewer.h | 66 | ||||
-rw-r--r-- | tests/Makefile.am | 32 | ||||
-rw-r--r-- | tests/test-render-surround-view.cpp | 595 |
12 files changed, 1739 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac index e17c36b..83b35b3 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,10 @@ AC_ARG_ENABLE(capi, [enable libxcam-capi library, @<:@default=yes@:>@]), [], [enable_capi="yes"]) +AC_ARG_ENABLE(osg, + AS_HELP_STRING([--enable-osg], + [enable open scene graph library, @<:@default=no@:>@]), + [], [enable_osg="no"]) # documentation AC_ARG_ENABLE(docs, [AC_HELP_STRING([--enable-docs], @@ -144,6 +148,12 @@ if test "$enable_vulkan" = "yes"; then PKG_CHECK_MODULES(LIBVULKAN, [vulkan], [HAVE_VULKAN=1], [HAVE_VULKAN=0]) fi +# check open sence graph +HAVE_OSG=0 +if test "$enable_osg" = "yes"; then + PKG_CHECK_MODULES(LIBOSG, [openscenegraph-osg], [HAVE_OSG=1], [HAVE_OSG=0]) +fi + if test "$enable_libcl" = "yes" && test "$HAVE_LIBCL" -eq 0; then PKG_CHECK_MODULES(LIBCL, [OpenCL], [HAVE_LIBCL=1], [HAVE_LIBCL=0]) fi @@ -371,6 +381,9 @@ AC_DEFINE_UNQUOTED([HAVE_VULKAN], $HAVE_VULKAN, [have vulkan]) AM_CONDITIONAL([HAVE_VULKAN], [test "$HAVE_VULKAN" -eq 1]) +AC_DEFINE_UNQUOTED([HAVE_OSG], $HAVE_OSG, + [have open scene graph]) +AM_CONDITIONAL([HAVE_OSG], [test "$HAVE_OSG" -eq 1]) AC_DEFINE_UNQUOTED([HAVE_OPENCV], $HAVE_OPENCV, [have opencv]) @@ -408,6 +421,7 @@ AC_CONFIG_FILES([Makefile modules/ocl/Makefile modules/gles/Makefile modules/vulkan/Makefile + modules/render/Makefile wrapper/Makefile wrapper/gstreamer/Makefile wrapper/gstreamer/interface/Makefile @@ -434,6 +448,7 @@ if test "$HAVE_LIBCL" -eq 1; then have_libcl="yes"; else have_libcl="no"; fi if test "$HAVE_GLES" -eq 1; then have_gles="yes"; else have_gles="no"; fi if test "$HAVE_VULKAN" -eq 1; then have_vulkan="yes"; else have_vulkan="no"; fi if test "$HAVE_OPENCV" -eq 1; then have_opencv="yes"; else have_opencv="no"; fi +if test "$HAVE_OSG" -eq 1; then have_osg="yes"; else have_osg="no"; fi if test "$ENABLE_DVS" -eq 1; then enable_dvs="yes"; else enable_dvs="no"; fi echo " @@ -450,6 +465,7 @@ echo " have Vulkan lib : $have_vulkan have OpenCL lib : $have_libcl have OpenCV lib : $have_opencv + have Open Scene Graph lib : $have_osg enable 3a lib : $enable_3alib enable smart analysis lib : $enable_smartlib enable dvs : $enable_dvs diff --git a/modules/Makefile.am b/modules/Makefile.am index 4bfa99a..04986d5 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -22,5 +22,10 @@ else VULKAN_DIR = endif +if HAVE_OSG +RENDER_DIR = render +else +RENDER_DIR = +endif -SUBDIRS = soft $(ISP_DIR) $(OCL_DIR) $(GLES_DIR) $(VULKAN_DIR) +SUBDIRS = soft $(ISP_DIR) $(OCL_DIR) $(GLES_DIR) $(VULKAN_DIR) $(RENDER_DIR) diff --git a/modules/render/Makefile.am b/modules/render/Makefile.am new file mode 100644 index 0000000..e102192 --- /dev/null +++ b/modules/render/Makefile.am @@ -0,0 +1,56 @@ +lib_LTLIBRARIES = libxcam_render.la + +XCAM_RENDER_CXXFLAGS = \ + $(LIBOSG_CFLAGS) \ + -I$(top_srcdir)/xcore \ + -I$(top_srcdir)/modules \ + $(NULL) + +XCAM_RENDER_LIBS = \ + $(losgGA) \ + -losgDB \ + -losgUtil \ + -losgFX \ + -losgText \ + -losgViewer \ + -losg \ + $(NULL) + +xcam_render_sources = \ + render_osg_camera_manipulator.cpp \ + render_osg_model.cpp \ + render_osg_viewer.cpp \ + $(NULL) + +libxcam_render_la_SOURCES = \ + $(xcam_render_sources) \ + $(NULL) + +libxcam_render_la_CXXFLAGS = \ + $(XCAM_RENDER_CXXFLAGS) \ + $(XCAM_CXXFLAGS) \ + $(NULL) + +libxcam_render_la_LIBADD = \ + $(top_builddir)/xcore/libxcam_core.la \ + $(XCAM_RENDER_LIBS) \ + $(NULL) + +libxcam_render_la_LDFLAGS = \ + $(XCAM_LT_LDFLAGS) \ + $(PTHREAD_LDFLAGS) \ + $(NULL) + +libxcam_renderincludedir = $(includedir)/xcam/render + +nobase_libxcam_renderinclude_HEADERS = \ + render_osg_camera_manipulator.h \ + render_osg_model.h \ + render_osg_viewer.h \ + render_osg_shader.h \ + $(NULL) + +noinst_HEADERS = \ + $(NULL) + +libxcam_render_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/modules/render/render_osg_camera_manipulator.cpp b/modules/render/render_osg_camera_manipulator.cpp new file mode 100644 index 0000000..3dca0f1 --- /dev/null +++ b/modules/render/render_osg_camera_manipulator.cpp @@ -0,0 +1,172 @@ +/* + * render_osg_camera_manipulator.cpp - supports 3D interactive manipulators + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_camera_manipulator.h" + +namespace XCam { + +RenderOsgCameraManipulator::RenderOsgCameraManipulator () + : osgGA::StandardManipulator::StandardManipulator () + , mAngle (osg::PI) + , mLookAtOffset (0.0f) + , mMaxLookAtOffset (osg::PI_4) + , mLength (4.0f) + , mWidth (3.0f) + , mHeight (1.6f) + , mMaxHeight (4.0f) + , mMinHeight (0.6) + , mEyePosScale (1.0f) + , mUp (osg::Vec3d(0.0f, 0.0f, 1.0f)) +{ + setAllowThrow (false); + setAutoComputeHomePosition (false); +} + +RenderOsgCameraManipulator::~RenderOsgCameraManipulator () +{ +} + +osg::Matrixd +RenderOsgCameraManipulator::getInverseMatrix () const +{ + osg::Vec3d eyePos; + getEyePosition (eyePos); + osg::Vec3d lookAtPos; + getLookAtPosition (lookAtPos); + return osg::Matrixd::lookAt (eyePos, lookAtPos, mUp); +} + +osg::Matrixd +RenderOsgCameraManipulator::getMatrix () const +{ + osg::Matrixd matrix = getInverseMatrix (); + return osg::Matrixd::inverse (matrix); +} + +void +RenderOsgCameraManipulator::home (double /*currentTime*/) +{ + mAngle = osg::PI; + mLookAtOffset = 0.0f; + mEyePosScale = 1.0f; +} + +void +RenderOsgCameraManipulator::rotate (float deltaAngle) +{ + if (deltaAngle > 0.) { + if (mLookAtOffset < mMaxLookAtOffset) { + mLookAtOffset = std::min (mLookAtOffset + deltaAngle, mMaxLookAtOffset); + } else { + mAngle += deltaAngle; + } + } else { + if (mLookAtOffset > -mMaxLookAtOffset) { + mLookAtOffset = std::max (mLookAtOffset + deltaAngle, -mMaxLookAtOffset); + } else { + mAngle += deltaAngle; + } + } + if (mAngle > 2 * osg::PI) { + mAngle -= 2 * osg::PI; + } else if (mAngle < 0.0f) { + mAngle += 2 * osg::PI; + } +} + +void +RenderOsgCameraManipulator::modifyHeight (float delta) +{ + if (delta > 0.0) { + mHeight = std::min (mHeight + delta, mMaxHeight); + } else { + mHeight = std::max (mHeight + delta, mMinHeight); + } +} + +void +RenderOsgCameraManipulator::getEyePosition (osg::Vec3d &eyePos) const +{ + float indentFactor = 1.0f - (0.1f * ((mHeight - mMinHeight) / (mMaxHeight - mMinHeight))); + eyePos[0] = cos (mAngle) * mLength * indentFactor; + eyePos[1] = sin (mAngle) * mWidth * indentFactor; + eyePos[2] = mHeight; + eyePos *= mEyePosScale; +} + +void +RenderOsgCameraManipulator::getLookAtPosition (osg::Vec3d &lookAtPos) const +{ + float lookAtAngle = mAngle + mLookAtOffset; + lookAtPos[0] = cos (lookAtAngle) * mLength * 0.5f; + lookAtPos[1] = sin (lookAtAngle) * mWidth * 0.5f; + lookAtPos[2] = mHeight * 0.25f; +} + +bool +RenderOsgCameraManipulator::handleKeyDown (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) +{ + (void)us; + bool eventHandled = false; + int key = ea.getKey (); + if (key == osgGA::GUIEventAdapter::KEY_Space) { + home (ea.getTime ()); + + eventHandled = true; + } else if (key == osgGA::GUIEventAdapter::KEY_Left) { + rotate (-0.1); + eventHandled = true; + } else if (key == osgGA::GUIEventAdapter::KEY_Right) { + rotate (0.1); + eventHandled = true; + } + + return eventHandled; +} + +bool +RenderOsgCameraManipulator::handleMouseWheel (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) +{ + (void)us; + bool eventHandled = false; + osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion(); + + if (sm == osgGA::GUIEventAdapter::SCROLL_DOWN || sm == osgGA::GUIEventAdapter::SCROLL_RIGHT) { + rotate (0.1); + eventHandled = true; + } else if (osgGA::GUIEventAdapter::SCROLL_UP || sm == osgGA::GUIEventAdapter::SCROLL_LEFT) { + rotate (-0.1); + eventHandled = true; + } + + return eventHandled; +} + +bool +RenderOsgCameraManipulator::performMovementLeftMouseButton (const double eventTimeDelta, const double dx, const double dy) +{ + (void)eventTimeDelta; + + rotate (-2.0 * dx); + modifyHeight (-dy); + return true; +} + +} // namespace XCam diff --git a/modules/render/render_osg_camera_manipulator.h b/modules/render/render_osg_camera_manipulator.h new file mode 100644 index 0000000..0653039 --- /dev/null +++ b/modules/render/render_osg_camera_manipulator.h @@ -0,0 +1,123 @@ +/* + * render_osg_camera_manipulator.h - supports 3D interactive manipulators + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_CAMERA_MANIPULATOR_H +#define XCAM_OSG_CAMERA_MANIPULATOR_H + +#include <osgGA/StandardManipulator> + +namespace XCam { + +class RenderOsgCameraManipulator + : public osgGA::StandardManipulator +{ +public: + + explicit RenderOsgCameraManipulator (); + + virtual ~RenderOsgCameraManipulator (); + + virtual void setByMatrix (const osg::Matrixd &matrix) + { + (void)matrix; + } + + virtual void setByInverseMatrix (const osg::Matrixd &matrix) + { + (void)matrix; + } + + virtual osg::Matrixd getMatrix () const; + + virtual osg::Matrixd getInverseMatrix () const; + + virtual void home (double currentTime); + + virtual void setTransformation (const osg::Vec3d &eye, const osg::Quat &rotation) + { + (void)eye; + (void)rotation; + } + + virtual void setTransformation (const osg::Vec3d &eye, const osg::Vec3d ¢er, const osg::Vec3d &up) + { + (void)eye; + (void)center; + (void)up; + } + + virtual void getTransformation (osg::Vec3d &eye, osg::Quat &rotation) const + { + (void)eye; + (void)rotation; + } + + virtual void getTransformation (osg::Vec3d &eye, osg::Vec3d ¢er, osg::Vec3d &up) const + { + (void)eye; + (void)center; + (void)up; + } + + void setInitialValues (float angle, float length, float width, float height) + { + mAngle = angle; + mLength = length; + mWidth = width; + mHeight = height; + mMinHeight = height / 2.0f; + + mUp = osg::Vec3d(0.0f, 0.0f, 1.0f); + } + +private: + RenderOsgCameraManipulator (RenderOsgCameraManipulator const &other); + + RenderOsgCameraManipulator &operator= (RenderOsgCameraManipulator const &other); + + virtual bool handleKeyDown (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us); + + virtual bool handleMouseWheel (const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us); + + virtual bool performMovementLeftMouseButton (const double eventTimeDelta, const double dx, const double dy); + + void rotate (float deltaAngle); + + void modifyHeight (float delta); + + void getEyePosition (osg::Vec3d &eye) const; + + void getLookAtPosition (osg::Vec3d ¢er) const; + + float mAngle; + float mLookAtOffset; + float mMaxLookAtOffset; + float mLength; + float mWidth; + float mHeight; + float mMaxHeight; + float mMinHeight; + float mEyePosScale; + osg::Vec3d mUp; +}; + +} // namespace XCam + +#endif // XCAM_OSG_CAMERA_MANIPULATOR_H diff --git a/modules/render/render_osg_model.cpp b/modules/render/render_osg_model.cpp new file mode 100644 index 0000000..2e3e7f3 --- /dev/null +++ b/modules/render/render_osg_model.cpp @@ -0,0 +1,337 @@ +/* + * render_osg_model.cpp - represents renderable things by model + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_model.h" + +#include <iostream> +#include <string> + +#include <osg/MatrixTransform> +#include <osg/Texture2D> +#include <osgDB/ReadFile> + +namespace XCam { + +RenderOsgModel::RenderOsgModel (const char *name, uint32_t width, uint32_t height) + : _name (NULL) + , _model (NULL) + , _geode (NULL) + , _program (NULL) + , _texture (NULL) +{ + XCAM_LOG_DEBUG ("RenderOsgModel width(%d), height(%d) ", width, height); + XCAM_ASSERT (name); + if (name) + _name = strndup (name, XCAM_MAX_STR_SIZE); + + _model = new osg::Group (); + _geode = new osg::Geode (); + + _texture = create_texture (width, height); + if (_texture.get ()) { + add_texture (_texture); + } +} + +RenderOsgModel::RenderOsgModel (const char *name, bool from_file) + : _name (NULL) + , _model (NULL) + , _geode (NULL) + , _program (NULL) + , _texture (NULL) +{ + XCAM_LOG_DEBUG ("RenderOsgModel model name (%s) ", name); + XCAM_ASSERT (name); + if (name) + _name = strndup (name, XCAM_MAX_STR_SIZE); + + _model = new osg::Group (); + _geode = new osg::Geode (); + + if (from_file) { + osg::ref_ptr<osg::Node> node = create_model_from_file (name); + _geode->addChild (node); + } +} + +RenderOsgModel::~RenderOsgModel () +{ + if (_name) + xcam_free (_name); +} + +osg::Node* +RenderOsgModel::create_model_from_file (const char *name) +{ + XCAM_LOG_DEBUG ("Invailide node name %s", name); + if (name == NULL) { + return NULL; + } + + osg::ref_ptr<osg::Node> node = osgDB::readNodeFile (name); + if (NULL == node.get ()) { + XCAM_LOG_ERROR ("Read node file FAILD!!! node name %s", name); + } + + return node.release(); +} + +void +RenderOsgModel::append_model (SmartPtr<RenderOsgModel> &child_model) +{ + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == child_model.ptr ()) { + XCAM_LOG_ERROR ("Append child model ERROR!! NULL model !!"); + } + + model->addChild (child_model->get_model ()); +} + +void +RenderOsgModel::append_geode (SmartPtr<RenderOsgModel> &child_model) +{ + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == child_model.ptr ()) { + XCAM_LOG_ERROR ("Append child geode ERROR!! NULL model !!"); + } + + model->addChild (child_model->get_geode ()); +} + +XCamReturn +RenderOsgModel::setup_shader_program ( + const char *name, + osg::Shader::Type type, + const char *source_text) +{ + XCAM_LOG_DEBUG ("setup shader program name(%s), type(%d)", name, type); + XCamReturn result = XCAM_RETURN_NO_ERROR; + + if (NULL == _program.get ()) { + _program = new osg::Program (); + _program->setName (name); + } + + _program->addShader (new osg::Shader (type, source_text)); + + _model->getOrCreateStateSet ()->setAttributeAndModes (_program, osg::StateAttribute::ON); + _model->getOrCreateStateSet ()->setMode (GL_DEPTH_TEST, osg::StateAttribute::ON); + + return result; +} + +XCamReturn +RenderOsgModel::setup_vertex_model ( + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float a, + float b, + float c) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + osg::ref_ptr<osg::Geode> geode = get_geode (); + osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry (); + + geode->addDrawable (geometry); + geometry->setUseVertexBufferObjects (true); + + osg::ref_ptr<osg::Vec3Array> vertex_array = new osg::Vec3Array (); + osg::ref_ptr<osg::Vec2Array> tex_coord_array = new osg::Vec2Array (); + osg::ref_ptr<osg::DrawElementsUInt> index_array = new osg::DrawElementsUInt (GL_TRIANGLE_STRIP, 0); + + osg::ref_ptr<osg::Vec3Array> normal_array = new osg::Vec3Array (); + osg::ref_ptr<osg::Vec4Array> color_array = new osg::Vec4Array (); + + normal_array->push_back (osg::Vec3 (0, -1, 0)); + geometry->setNormalArray (normal_array); + geometry->setNormalBinding (osg::Geometry::BIND_OVERALL); + + color_array->push_back (osg::Vec4 (1.0, 0.0, 0.0, 1.0)); + geometry->setColorArray (color_array); + geometry->setColorBinding (osg::Geometry::BIND_OVERALL); + + for (uint32_t idx = 0; idx < vertices.size (); idx++) { + vertex_array->push_back ( + osg::Vec3f (vertices[idx].x * a, + vertices[idx].y * b, + vertices[idx].z * c)); + } + + for (uint32_t idx = 0; idx < points.size (); idx++) { + tex_coord_array->push_back (osg::Vec2f (points[idx].x, points[idx].y)); + } + + for (uint32_t idx = 0; idx < indices.size (); idx++) { + index_array->push_back (indices[idx]); + } + + geometry->setVertexArray (vertex_array.get ()); + + if (points.size () > 0) { + geometry->setTexCoordArray (0, tex_coord_array.get ()); + } + + if (indices.size () > 0) { + geometry->addPrimitiveSet (index_array.get ()); + } else { + geometry->addPrimitiveSet (new osg::DrawArrays (GL_TRIANGLE_FAN, 0, 4)); + } + + model->addChild (geode); + + return result; +} + +XCamReturn +RenderOsgModel::setup_model_matrix ( + float translation_x, + float translation_y, + float translation_z, + float rotation_x, + float rotation_y, + float rotation_z, + float rotation_degrees) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + osg::ref_ptr<osg::Geode> geode = get_geode (); + + const osg::Vec3f axis(rotation_x, rotation_y, rotation_z); + osg::ref_ptr<osg::MatrixTransform> mat = new osg::MatrixTransform (); + mat->setMatrix (osg::Matrix::scale (osg::Vec3 (1.0, 1.0, 1.0)) * + osg::Matrix::rotate ((rotation_degrees / 180.f) * osg::PI_2, axis) * + osg::Matrix::translate (osg::Vec3 (translation_x, translation_y, translation_z))); + + mat->addChild (geode); + model->addChild (mat); + + return result; +} + +XCamReturn +RenderOsgModel::update_texture (SmartPtr<VideoBuffer> &buffer) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + XCAM_LOG_DEBUG ("RenderOsgModel::update_texture "); + + if (NULL == _texture.get ()) { + return XCAM_RETURN_ERROR_PARAM; + } + + { + SmartLock locker (_mutex); + + VideoBufferInfo info = buffer->get_video_info (); + uint32_t image_width = info.width; + uint32_t image_height = info.height; + + osg::ref_ptr<osg::Image> image_y = new osg::Image (); + osg::ref_ptr<osg::Image> image_uv = new osg::Image (); + + uint8_t* image_buffer = buffer->map (); + + uint8_t* src_y = image_buffer; + uint8_t* src_uv = image_buffer + image_width * image_height; + + image_y->setImage (image_width, image_height, 1, + GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, + src_y, osg::Image::NO_DELETE); + + image_uv->setImage (image_width / 2, image_height / 2, 1, + GL_LUMINANCE, GL_RG, GL_UNSIGNED_BYTE, + src_uv, osg::Image::NO_DELETE); + + _texture->_texture_y->setImage (image_y); + _texture->_texture_uv->setImage (image_uv); + + buffer->unmap (); + } + + return result; +} + +NV12Texture* +RenderOsgModel::create_texture (uint32_t width, uint32_t height) +{ + osg::ref_ptr<NV12Texture> nv12 = new NV12Texture (width, height); + + nv12->_texture_y = new osg::Texture2D (); + nv12->_texture_y->setImage (new osg::Image ()); + + nv12->_texture_y->setInternalFormat (GL_LUMINANCE); + nv12->_texture_y->setResizeNonPowerOfTwoHint (false); + nv12->_texture_y->setNumMipmapLevels (0); + nv12->_texture_y->setFilter (osg::Texture::MIN_FILTER, osg::Texture::NEAREST); + nv12->_texture_y->setFilter (osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + nv12->_texture_y->setWrap (osg::Texture::WRAP_S, osg::Texture::CLAMP); + nv12->_texture_y->setWrap (osg::Texture::WRAP_T, osg::Texture::CLAMP); + + nv12->_texture_y->setTextureWidth (width); + nv12->_texture_y->setTextureHeight (height); + + nv12->_texture_uv = new osg::Texture2D (); + nv12->_texture_uv->setImage (new osg::Image ()); + + nv12->_texture_uv->setInternalFormat (GL_RG); + nv12->_texture_uv->setResizeNonPowerOfTwoHint (false); + nv12->_texture_uv->setNumMipmapLevels (0); + nv12->_texture_uv->setFilter (osg::Texture::MIN_FILTER, osg::Texture::NEAREST); + nv12->_texture_uv->setFilter (osg::Texture::MAG_FILTER, osg::Texture::NEAREST); + nv12->_texture_uv->setWrap (osg::Texture::WRAP_S, osg::Texture::CLAMP); + nv12->_texture_uv->setWrap (osg::Texture::WRAP_T, osg::Texture::CLAMP); + + nv12->_texture_uv->setTextureWidth (width / 2); + nv12->_texture_uv->setTextureHeight (height / 2); + + return nv12.release (); +} + +XCamReturn +RenderOsgModel::add_texture (osg::ref_ptr<NV12Texture> &texture) +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::ref_ptr<osg::Group> model = get_model (); + + if (NULL == model.get () || NULL == _texture.get ()) { + return XCAM_RETURN_ERROR_PARAM; + } + + model->getOrCreateStateSet()->setTextureAttribute(0, texture->_texture_y.get ()); + texture->_uniform_y = new osg::Uniform (osg::Uniform::SAMPLER_2D, "textureY"); + texture->_uniform_y->set (0); + model->getOrCreateStateSet ()->addUniform (texture->_uniform_y.get ()); + + model->getOrCreateStateSet ()->setTextureAttribute (1, texture->_texture_uv.get ()); + texture->_uniform_uv = new osg::Uniform (osg::Uniform::SAMPLER_2D, "textureUV"); + texture->_uniform_uv->set (1); + model->getOrCreateStateSet ()->addUniform (texture->_uniform_uv.get ()); + + return result; +} + +} // namespace XCam diff --git a/modules/render/render_osg_model.h b/modules/render/render_osg_model.h new file mode 100644 index 0000000..09cba8c --- /dev/null +++ b/modules/render/render_osg_model.h @@ -0,0 +1,123 @@ +/* + * render_osg_model.h - represents renderable things by object + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_RENDER_MODEL_H +#define XCAM_OSG_RENDER_MODEL_H + +#include <osg/Texture2D> +#include <osg/Group> + +#include <interface/data_types.h> +#include <interface/stitcher.h> +#include <xcam_mutex.h> + +namespace XCam { + +class NV12Texture : public osg::Referenced +{ +public: + explicit NV12Texture (uint32_t width, uint32_t height) + { + _image_width = width; + _image_height = height; + } + +public: + uint32_t _image_width; + uint32_t _image_height; + + osg::ref_ptr<osg::Texture2D> _texture_y; + osg::ref_ptr<osg::Texture2D> _texture_uv; + + osg::ref_ptr<osg::Uniform> _uniform_y; + osg::ref_ptr<osg::Uniform> _uniform_uv; +}; + +class RenderOsgModel { +public: + + explicit RenderOsgModel (const char *name, uint32_t width, uint32_t height); + explicit RenderOsgModel (const char *name, bool from_file = true); + + virtual ~RenderOsgModel (); + + const char *get_name () const { + return _name; + } + + osg::Node* create_model_from_file (const char *name); + + osg::Group* get_model () const { + return _model; + } + + void append_model (SmartPtr<RenderOsgModel> &model); + + void append_geode (SmartPtr<RenderOsgModel> &model); + + + osg::Geode* get_geode () const { + return _geode; + } + + XCamReturn setup_shader_program ( + const char *name, + osg::Shader::Type type, + const char *source_text); + + XCamReturn setup_vertex_model ( + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float a = 1.0f, + float b = 1.0f, + float c = 1.0f); + + XCamReturn setup_model_matrix ( + float translation_x, + float translation_y, + float translation_z, + float rotation_x, + float rotation_y, + float rotation_z, + float rotation_degrees); + + XCamReturn update_texture (SmartPtr<VideoBuffer> &buffer); + +private: + + NV12Texture* create_texture (uint32_t width, uint32_t height); + XCamReturn add_texture (osg::ref_ptr<NV12Texture> &texture); + +private: + + char *_name; + + osg::ref_ptr<osg::Group> _model; + osg::ref_ptr<osg::Geode> _geode; + osg::ref_ptr<osg::Program> _program; + osg::ref_ptr<NV12Texture> _texture; + + Mutex _mutex; +}; + +} // namespace XCam + +#endif // XCAM_OSG_RENDER_MODEL_H diff --git a/modules/render/render_osg_shader.h b/modules/render/render_osg_shader.h new file mode 100644 index 0000000..b2dd52e --- /dev/null +++ b/modules/render/render_osg_shader.h @@ -0,0 +1,93 @@ +/* + * render_osg_shader.h - common gl shaders + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_SHADER_H +#define XCAM_OSG_SHADER_H + +namespace XCam { + +static const char VtxShaderProjectNV12Texture[] = "" + "precision highp float; \n" + "attribute vec4 osg_Vertex; \n" + "attribute vec2 osg_MultiTexCoord0; \n" + "attribute vec4 osg_Color; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "uniform mat4 osg_ModelViewMatrix; \n" + "uniform mat4 osg_ViewMatrixInverse; \n" + "varying vec2 texcoord; \n" + "varying vec4 color; \n" + "void main(void) \n" + "{ \n" + " texcoord = osg_MultiTexCoord0; \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + " color = osg_Color; \n" + "} \n"; + +static const char FrgShaderProjectNV12Texture[] = "" + "precision highp float; \n" + "uniform sampler2D textureY; \n" + "uniform sampler2D textureUV; \n" + "varying vec2 texcoord; \n" + "varying vec4 color; \n" + "vec4 getRGBColorNV12(sampler2D u_textureY, sampler2D u_textureUV, vec2 tex) \n" + "{ \n" + " vec4 resultcolor = vec4 (0.0, 0.0, 0.0, 1.0); \n" + " float y, u, v; \n" + " y = texture2D(u_textureY, vec2(tex.s, tex.t)).r; \n" + " vec2 colorUV = texture2D(u_textureUV, vec2(tex.s, tex.t)).rg; \n" + " u = colorUV.x-0.5; \n" + " v = colorUV.y-0.5; \n" + " y = 1.1643*(y-0.0625); \n" + " resultcolor.r = (y+1.5958*(v)); \n" + " resultcolor.g = (y-0.39173*(u)-0.81290*(v)); \n" + " resultcolor.b = (y+2.017*(u)); \n" + " resultcolor.a = 1.0; \n" + " return resultcolor; \n" + "} \n" + "void main() \n" + "{ \n" + " vec4 textureColor = getRGBColorNV12(textureY, textureUV, texcoord); \n" + " gl_FragColor = textureColor; \n" + "} \n"; + +const char VtxShaderSimpleTexture[] = "" + "precision highp float; \n" + "attribute vec4 osg_Vertex; \n" + "attribute vec4 osg_Color; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "varying vec4 color; \n" + "void main(void) \n" + "{ \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + " color = osg_Color; \n" + "} \n"; + +const char FrgShaderSimpleTexture[] = "" + "precision highp float; \n" + "varying vec4 color; \n" + "void main() \n" + "{ \n" + " gl_FragColor = color; \n" + "} \n"; + + +} // namespace XCam + +#endif // XCAM_OSG_SHADER_H diff --git a/modules/render/render_osg_viewer.cpp b/modules/render/render_osg_viewer.cpp new file mode 100644 index 0000000..42f625d --- /dev/null +++ b/modules/render/render_osg_viewer.cpp @@ -0,0 +1,121 @@ +/* + * render_osg_viewer.cpp - renders a single view on to a single scene + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#include "render_osg_viewer.h" +#include "render_osg_model.h" +#include "render_osg_camera_manipulator.h" + +#include <string> + +namespace XCam { + +RenderOsgViewer::RenderOsgViewer () + : _viewer (NULL) + , _model_groups (NULL) + , _initialized (false) +{ + _viewer = new osgViewer::Viewer (); + + if (!_initialized) { + initialize (); + } +} + +RenderOsgViewer::~RenderOsgViewer () +{ + _viewer->setDone (true); +} + +XCamReturn +RenderOsgViewer::initialize () +{ + XCamReturn result = XCAM_RETURN_NO_ERROR; + + osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); + uint32_t win_width = 1920; + uint32_t win_height = 1080; + if (wsi) { + wsi->getScreenResolution (osg::GraphicsContext::ScreenIdentifier (0), win_width, win_height); + } + + _viewer->setThreadingModel (osgViewer::Viewer::SingleThreaded); + + _viewer->setLightingMode (osg::View::SKY_LIGHT); + _viewer->getLight()->setAmbient (osg::Vec4f(0.f, 0.f, 0.f, 1.f)); + _viewer->getLight()->setDiffuse (osg::Vec4d(0.4f, 0.4f, 0.4f, 1.f)); + _viewer->getLight()->setSpecular (osg::Vec4d(0.5f, 0.5f, 0.5f, 1.f)); + + osg::ref_ptr<osgViewer::StatsHandler> stats_handler = new osgViewer::StatsHandler (); + _viewer->addEventHandler (stats_handler); + + _viewer->setUpViewInWindow (0, 0, win_width, win_height); + + osg::ref_ptr<RenderOsgCameraManipulator> vp_manipulator = new RenderOsgCameraManipulator (); + vp_manipulator->setInitialValues (osg::PI, 6.0f, 4.0f, 2.6f); + _viewer->setCameraManipulator (vp_manipulator); + _viewer->getCamera ()->setClearMask (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + _viewer->getCamera ()->setComputeNearFarMode (osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); + _viewer->getCamera ()->setClearColor (osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); + _viewer->getCamera ()->setViewport (0, 0, win_width, win_height); + + _initialized = true; + + return result; +} + +void +RenderOsgViewer::set_camera_manipulator (osg::ref_ptr<osgGA::StandardManipulator> &manipulator) +{ + _viewer->setCameraManipulator (manipulator); +} + +void +RenderOsgViewer::add_model (SmartPtr<RenderOsgModel> &model) +{ + if (!model.ptr ()) { + return; + } + + if (!_model_groups.ptr ()) { + _model_groups = model; + } else { + _model_groups->append_model (model); + } +} + +void +RenderOsgViewer::validate_model_groups () +{ + if (!_model_groups.ptr ()) { + return; + } + _viewer->setSceneData (_model_groups->get_model ()); +} + +void +RenderOsgViewer::start_render () +{ + if (!_viewer->done ()) + { + _viewer->frame (); + } +} + +} // namespace XCam diff --git a/modules/render/render_osg_viewer.h b/modules/render/render_osg_viewer.h new file mode 100644 index 0000000..bf2d1da --- /dev/null +++ b/modules/render/render_osg_viewer.h @@ -0,0 +1,66 @@ +/* + * render_osg_viewer.h - renders a single view on to a single scene + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#ifndef XCAM_OSG_RENDER_VIEWER_H +#define XCAM_OSG_RENDER_VIEWER_H + +#include <osgViewer/Viewer> +#include <osgViewer/ViewerEventHandlers> +#include <osgGA/StandardManipulator> + +#include <interface/data_types.h> +#include <interface/stitcher.h> +#include <xcam_mutex.h> + +namespace XCam { + +class RenderOsgModel; + +class RenderOsgViewer { +public: + + explicit RenderOsgViewer (); + + virtual ~RenderOsgViewer (); + + osgViewer::Viewer *get_viewer () { + return _viewer; + } + + void set_camera_manipulator (osg::ref_ptr<osgGA::StandardManipulator> &manipulator); + + void add_model (SmartPtr<RenderOsgModel> &model); + + void validate_model_groups (); + + void start_render (); + +private: + XCamReturn initialize (); + +private: + osg::ref_ptr<osgViewer::Viewer> _viewer; + SmartPtr<RenderOsgModel> _model_groups; + bool _initialized; +}; + +} // namespace XCam + +#endif // XCAM_OSG_RENDER_VIEWER_H diff --git a/tests/Makefile.am b/tests/Makefile.am index 35f4579..3f538ff 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -24,6 +24,12 @@ noinst_PROGRAMS = \ test-surround-view \ $(NULL) +if HAVE_OSG +noinst_PROGRAMS += \ + test-render-surround-view \ + $(NULL) +endif + if ENABLE_IA_AIQ noinst_PROGRAMS += \ test-poll-thread \ @@ -166,7 +172,31 @@ test_surround_view_LDADD = \ $(top_builddir)/modules/soft/libxcam_soft.la \ $(TEST_BASE_LA) \ $(NULL) + if HAVE_GLES test_surround_view_LDADD += \ + $(top_builddir)/modules/gles/libxcam_gles.la \ + $(NULL) +endif + +if HAVE_OSG +test_render_surround_view_SOURCES = test-render-surround-view.cpp +test_render_surround_view_CXXFLAGS = $(TEST_BASE_CXXFLAGS) +test_render_surround_view_LDADD = \ + $(top_builddir)/modules/soft/libxcam_soft.la \ + $(top_builddir)/modules/render/libxcam_render.la \ + $(TEST_BASE_LA) \ + -losgGA \ + -losgDB \ + -losgUtil \ + -losgFX \ + -losgText \ + -losgViewer \ + -losg \ + $(NULL) +if HAVE_GLES +test_render_surround_view_LDADD += \ $(top_builddir)/modules/gles/libxcam_gles.la -endif
\ No newline at end of file +endif + +endif diff --git a/tests/test-render-surround-view.cpp b/tests/test-render-surround-view.cpp new file mode 100644 index 0000000..335e289 --- /dev/null +++ b/tests/test-render-surround-view.cpp @@ -0,0 +1,595 @@ +/* + * test-render-surround-view.cpp - test render surround view + * + * Copyright (c) 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Author: Zong Wei <wei.zong@intel.com> + */ + +#include "test_common.h" +#include "test_stream.h" +#include <interface/geo_mapper.h> +#include <interface/stitcher.h> +#include <calibration_parser.h> +#include <soft/soft_video_buf_allocator.h> +#if HAVE_GLES +#include <gles/gl_video_buffer.h> +#include <gles/egl/egl_base.h> +#endif + +#include <render/render_osg_viewer.h> +#include <render/render_osg_model.h> +#include <render/render_osg_shader.h> + +using namespace XCam; + +enum SVModule { + SVModuleNone = 0, + SVModuleSoft, + SVModuleGLES +}; + +#define MODEL_NAME "SmallSuv.osgb" + +static const char VtxShaderCar[] = "" + "precision highp float; \n" + "uniform mat4 osg_ModelViewProjectionMatrix; \n" + "uniform mat4 osg_ModelViewMatrix; \n" + "uniform mat3 osg_NormalMatrix; \n" + "attribute vec3 osg_Normal; \n" + "attribute vec4 osg_Color; \n" + "attribute vec4 osg_Vertex; \n" + "varying vec4 v_color; \n" + "varying float diffuseLight; \n" + "varying float specLight; \n" + "attribute vec2 osg_MultiTexCoord0; \n" + "varying vec2 texCoord0; \n" + "void main() \n" + "{ \n" + " vec4 light = vec4(0.0,100.0, 100.0, 1.0); \n" + " vec4 lightColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorDiffuse = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorAmbient = vec4(0.3, 0.3, .3, 1.0); \n" + " vec4 carColorAmbient = vec4(0.0, 0.0, 1.0, 1.0); \n" + " vec4 carColorDiffuse = vec4(0.0, 0.0, 1.0, 1.0); \n" + " vec4 carColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec3 tnorm = normalize(osg_NormalMatrix * osg_Normal); \n" + " vec4 eye = osg_ModelViewMatrix * osg_Vertex; \n" + " vec3 s = normalize(vec3(light - eye)); \n" + " vec3 v = normalize(-eye.xyz); \n" + " vec3 r = reflect(-s, tnorm); \n" + " diffuseLight = max(0.0, dot( s, tnorm)); \n" + " specLight = 0.0; \n" + " if(diffuseLight > 0.0) \n" + " { \n" + " specLight = pow(max(0.0, dot(r,v)), 10.0); \n" + " } \n" + " texCoord0 = osg_MultiTexCoord0; \n" + " v_color = (specLight * lightColorSpec * carColorSpec) + (carColorDiffuse * lightColorDiffuse * diffuseLight) + lightColorAmbient * carColorAmbient; \n" + " gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; \n" + "} \n"; + +static const char FrgShaderCar[] = "" + "precision highp float; \n" + "varying vec4 v_color; \n" + "varying float diffuseLight; \n" + "varying float specLight; \n" + "uniform sampler2D textureWheel; \n" + "varying vec2 texCoord0; \n" + "void main() \n" + "{ \n" + " vec4 lightColorSpec = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorDiffuse = vec4(1.0, 1.0, 1.0, 1.0); \n" + " vec4 lightColorAmbient = vec4(0.3, 0.3, .3, 1.0); \n" + " vec4 base = texture2D(textureWheel, texCoord0.st); \n" + " gl_FragColor = (specLight * lightColorSpec * base) + (base * lightColorDiffuse * diffuseLight) + lightColorAmbient * base ; \n" + "} \n"; + +class SVStream + : public Stream +{ +public: + explicit SVStream (const char *file_name = NULL, uint32_t width = 0, uint32_t height = 0); + virtual ~SVStream () {} + + void set_module (SVModule module) { + XCAM_ASSERT (module != SVModuleNone); + _module = module; + } + + virtual XCamReturn create_buf_pool (const VideoBufferInfo &info, uint32_t count); + +private: + XCAM_DEAD_COPY (SVStream); + +private: + SVModule _module; + SmartPtr<GeoMapper> _mapper; +}; +typedef std::vector<SmartPtr<SVStream>> SVStreams; + +SVStream::SVStream (const char *file_name, uint32_t width, uint32_t height) + : Stream (file_name, width, height) + , _module (SVModuleNone) +{ +} + +XCamReturn +SVStream::create_buf_pool (const VideoBufferInfo &info, uint32_t count) +{ + XCAM_FAIL_RETURN ( + ERROR, _module != SVModuleNone, XCAM_RETURN_ERROR_PARAM, + "invalid module, please set module first"); + + SmartPtr<BufferPool> pool; + if (_module == SVModuleSoft) { + pool = new SoftVideoBufAllocator (info); + } else if (_module == SVModuleGLES) { +#if HAVE_GLES + pool = new GLVideoBufferPool (info); +#endif + } + XCAM_ASSERT (pool.ptr ()); + + if (!pool->reserve (count)) { + XCAM_LOG_ERROR ("create buffer pool failed"); + return XCAM_RETURN_ERROR_MEM; + } + + set_buf_pool (pool); + return XCAM_RETURN_NO_ERROR; +} + +static SmartPtr<Stitcher> +create_stitcher (SVModule module) +{ + SmartPtr<Stitcher> stitcher; + + if (module == SVModuleSoft) { + stitcher = Stitcher::create_soft_stitcher (); + } else if (module == SVModuleGLES) { +#if HAVE_GLES + stitcher = Stitcher::create_gl_stitcher (); +#endif + } + XCAM_ASSERT (stitcher.ptr ()); + + return stitcher; +} + +static int +parse_camera_info (const char *path, uint32_t idx, CameraInfo &info, uint32_t camera_count) +{ + static const char *instrinsic_names[] = { + "intrinsic_camera_front.txt", "intrinsic_camera_right.txt", + "intrinsic_camera_rear.txt", "intrinsic_camera_left.txt" + }; + static const char *exstrinsic_names[] = { + "extrinsic_camera_front.txt", "extrinsic_camera_right.txt", + "extrinsic_camera_rear.txt", "extrinsic_camera_left.txt" + }; + static const float viewpoints_range[] = {64.0f, 160.0f, 64.0f, 160.0f}; + + char intrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + char extrinsic_path[XCAM_TEST_MAX_STR_SIZE] = {'\0'}; + snprintf (intrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, instrinsic_names[idx]); + snprintf (extrinsic_path, XCAM_TEST_MAX_STR_SIZE, "%s/%s", path, exstrinsic_names[idx]); + + CalibrationParser parser; + CHECK ( + parser.parse_intrinsic_file (intrinsic_path, info.calibration.intrinsic), + "parse intrinsic params (%s)failed.", intrinsic_path); + + CHECK ( + parser.parse_extrinsic_file (extrinsic_path, info.calibration.extrinsic), + "parse extrinsic params (%s)failed.", extrinsic_path); + info.calibration.extrinsic.trans_x += TEST_CAMERA_POSITION_OFFSET_X; + + info.angle_range = viewpoints_range[idx]; + info.round_angle_start = (idx * 360.0f / camera_count) - info.angle_range / 2.0f; + return 0; +} + +void +get_bowl_model ( + const SmartPtr<Stitcher> &stitcher, + BowlModel::VertexMap &vertices, + BowlModel::PointMap &points, + BowlModel::IndexVector &indices, + float &a, + float &b, + float &c, + float resRatio, + uint32_t image_width, + uint32_t image_height) +{ + uint32_t res_width = image_width * resRatio; + uint32_t res_height = image_height * resRatio; + + BowlDataConfig bowl = stitcher->get_bowl_config(); + bowl.angle_start = 0.0f; + bowl.angle_end = 360.0f; + + a = bowl.a; + b = bowl.b; + c = bowl.c; + + BowlModel bowl_model(bowl, image_width, image_height); + + bowl_model.get_bowlview_vertex_model( + vertices, + points, + indices, + res_width, + res_height); +} + +static SmartPtr<RenderOsgModel> +create_surround_view_model ( + const SmartPtr<Stitcher> &stitcher, + uint32_t texture_width, + uint32_t texture_height) +{ + SmartPtr<RenderOsgModel> svm_model = new RenderOsgModel ("svm model", texture_width, texture_height); + + svm_model->setup_shader_program ("SVM", osg::Shader::VERTEX, VtxShaderProjectNV12Texture); + svm_model->setup_shader_program ("SVM", osg::Shader::FRAGMENT, FrgShaderProjectNV12Texture); + + BowlModel::VertexMap vertices; + BowlModel::PointMap points; + BowlModel::IndexVector indices; + + float a = 0; + float b = 0; + float c = 0; + float res_ratio = 0.3; + float scaling = 1000.0f; + + get_bowl_model (stitcher, vertices, points, indices, + a, b, c, res_ratio, texture_width, texture_height ); + + svm_model->setup_vertex_model (vertices, points, indices, a / scaling, b / scaling, c / scaling); + + return svm_model; +} + +static SmartPtr<RenderOsgModel> +create_car_model () +{ + std::string car_model_path = FISHEYE_CONFIG_PATH + std::string(MODEL_NAME); + + const char *env_path = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env_path) { + car_model_path.clear (); + car_model_path = std::string (env_path) + std::string (MODEL_NAME); + } + + SmartPtr<RenderOsgModel> car_model = new RenderOsgModel (car_model_path.c_str(), true); + + car_model->setup_shader_program ("Car", osg::Shader::VERTEX, VtxShaderCar); + car_model->setup_shader_program ("Car", osg::Shader::FRAGMENT, FrgShaderCar); + + float translation_x = -0.3f; + float translation_y = 0.0f; + float translation_z = 0.0f; + float rotation_x = 0.0f; + float rotation_y = 0.0f; + float rotation_z = 1.0f; + float rotation_degrees = -180.0; + + car_model->setup_model_matrix ( + translation_x, + translation_y, + translation_z, + rotation_x, + rotation_y, + rotation_z, + rotation_degrees); + + return car_model; +} + +static int +run_stitcher ( + const SmartPtr<Stitcher> &stitcher, + const SmartPtr<RenderOsgViewer> &render, const SmartPtr<RenderOsgModel> &model, + const SVStreams &ins, const SVStreams &outs, bool save_output) +{ + XCamReturn ret = XCAM_RETURN_NO_ERROR; + + Mutex mutex; + + VideoBufferList in_buffers; + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK (ins[i]->rewind (), "rewind buffer from file(%s) failed", ins[i]->get_file_name ()); + } + + do { + in_buffers.clear (); + + for (uint32_t i = 0; i < ins.size (); ++i) { + ret = ins[i]->read_buf(); + if (ret == XCAM_RETURN_BYPASS) + break; + CHECK (ret, "read buffer from file(%s) failed.", ins[i]->get_file_name ()); + in_buffers.push_back (ins[i]->get_buf ()); + } + if (ret == XCAM_RETURN_BYPASS) { + XCAM_LOG_DEBUG ("XCAM_RETURN_BYPASS \n"); + break; + } + + { + SmartLock locker (mutex); + CHECK ( + stitcher->stitch_buffers (in_buffers, outs[0]->get_buf ()), + "stitch buffer failed."); + + if (save_output) { + outs[0]->write_buf (); + } + } + + model->update_texture (outs[0]->get_buf ()); + render->start_render (); + + FPS_CALCULATION (surround - view, XCAM_OBJ_DUR_FRAME_NUM); + } while (true); + + return 0; +} + +static void usage(const char* arg0) +{ + printf ("Usage:\n" + "%s --module MODULE --input0 input.nv12 --input1 input1.nv12 --input2 input2.nv12 ...\n" + "\t--module processing module, selected from: soft, gles\n" + "\t-- read calibration files from exported path $FISHEYE_CONFIG_PATH\n" + "\t--input0 input image(NV12)\n" + "\t--input1 input image(NV12)\n" + "\t--input2 input image(NV12)\n" + "\t--input3 input image(NV12)\n" + "\t--output output image(NV12/MP4)\n" + "\t--in-w optional, input width, default: 1280\n" + "\t--in-h optional, input height, default: 800\n" + "\t--out-w optional, output width, default: 1920\n" + "\t--out-h optional, output height, default: 640\n" + "\t--scale-mode optional, scaling mode for geometric mapping,\n" + "\t select from [singleconst/dualconst/dualcurve], default: singleconst\n" + "\t--save optional, save file or not, select from [true/false], default: true\n" + "\t--loop optional, how many loops need to run, default: 1\n" + "\t--help usage\n", + arg0); +} + +int main (int argc, char *argv[]) +{ + uint32_t input_width = 1280; + uint32_t input_height = 800; + uint32_t output_width = 1920; + uint32_t output_height = 640; + + SVStreams ins; + SVStreams outs; + + bool save_output = true; + + SVModule module = SVModuleSoft; + GeoMapScaleMode scale_mode = ScaleSingleConst; + + int loop = 1; + + const struct option long_opts[] = { + {"module", required_argument, NULL, 'm'}, + {"input0", required_argument, NULL, 'i'}, + {"input1", required_argument, NULL, 'j'}, + {"input2", required_argument, NULL, 'k'}, + {"input3", required_argument, NULL, 'l'}, + {"output", required_argument, NULL, 'o'}, + {"in-w", required_argument, NULL, 'w'}, + {"in-h", required_argument, NULL, 'h'}, + {"out-w", required_argument, NULL, 'W'}, + {"out-h", required_argument, NULL, 'H'}, + {"scale-mode", required_argument, NULL, 'S'}, + {"save", required_argument, NULL, 's'}, + {"loop", required_argument, NULL, 'L'}, + {"help", no_argument, NULL, 'e'}, + {NULL, 0, NULL, 0}, + }; + + int opt = -1; + while ((opt = getopt_long(argc, argv, "", long_opts, NULL)) != -1) { + switch (opt) { + case 'm': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "soft")) { + module = SVModuleSoft; + } + break; + case 'i': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'j': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'k': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'l': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, ins, optarg); + break; + case 'o': + XCAM_ASSERT (optarg); + PUSH_STREAM (SVStream, outs, optarg); + break; + case 'w': + input_width = atoi(optarg); + break; + case 'h': + input_height = atoi(optarg); + break; + case 'W': + output_width = atoi(optarg); + break; + case 'H': + output_height = atoi(optarg); + break; + case 'S': + XCAM_ASSERT (optarg); + if (!strcasecmp (optarg, "singleconst")) + scale_mode = ScaleSingleConst; + else if (!strcasecmp (optarg, "dualconst")) + scale_mode = ScaleDualConst; + else if (!strcasecmp (optarg, "dualcurve")) + scale_mode = ScaleDualCurve; + else { + XCAM_LOG_ERROR ("GeoMapScaleMode unknown mode: %s", optarg); + usage (argv[0]); + return -1; + } + break; + case 's': + save_output = (strcasecmp (optarg, "false") == 0 ? false : true); + break; + case 'L': + loop = atoi(optarg); + break; + default: + XCAM_LOG_ERROR ("getopt_long return unknown value: %c", opt); + usage (argv[0]); + return -1; + } + } + + if (optind < argc || argc < 2) { + XCAM_LOG_ERROR ("unknown option %s", argv[optind]); + usage (argv[0]); + return -1; + } + + CHECK_EXP (ins.size () == 4, "surrond view needs 4 input streams"); + for (uint32_t i = 0; i < ins.size (); ++i) { + CHECK_EXP (ins[i].ptr (), "input stream is NULL, index:%d", i); + CHECK_EXP (strlen (ins[i]->get_file_name ()), "input file name was not set, index:%d", i); + } + + CHECK_EXP (outs.size () == 1 && outs[0].ptr (), "surrond view needs 1 output stream"); + CHECK_EXP (strlen (outs[0]->get_file_name ()), "output file name was not set"); + + for (uint32_t i = 0; i < ins.size (); ++i) { + printf ("input%d file:\t\t%s\n", i, ins[i]->get_file_name ()); + } + printf ("output file:\t\t%s\n", outs[0]->get_file_name ()); + printf ("input width:\t\t%d\n", input_width); + printf ("input height:\t\t%d\n", input_height); + printf ("output width:\t\t%d\n", output_width); + printf ("output height:\t\t%d\n", output_height); + printf ("scaling mode:\t\t%s\n", (scale_mode == ScaleSingleConst) ? "singleconst" : + ((scale_mode == ScaleDualConst) ? "dualconst" : "dualcurve")); + printf ("save output:\t\t%s\n", save_output ? "true" : "false"); + printf ("loop count:\t\t%d\n", loop); + + if (module == SVModuleGLES) { +#if !HAVE_GLES + XCAM_LOG_ERROR ("GLES module unsupported"); + return -1; +#endif + } + +#if HAVE_GLES + SmartPtr<EGLBase> egl; + if (module == SVModuleGLES) { + egl = new EGLBase (); + XCAM_ASSERT (egl.ptr ()); + XCAM_FAIL_RETURN (ERROR, egl->init (), -1, "init EGL failed"); + } +#endif + + VideoBufferInfo in_info; + in_info.init (V4L2_PIX_FMT_NV12, input_width, input_height); + for (uint32_t i = 0; i < ins.size (); ++i) { + ins[i]->set_module (module); + ins[i]->set_buf_size (input_width, input_height); + CHECK (ins[i]->create_buf_pool (in_info, 6), "create buffer pool failed"); + CHECK (ins[i]->open_reader ("rb"), "open input file(%s) failed", ins[i]->get_file_name ()); + } + + outs[0]->set_buf_size (output_width, output_height); + if (save_output) { + CHECK (outs[0]->estimate_file_format (), + "%s: estimate file format failed", outs[0]->get_file_name ()); + CHECK (outs[0]->open_writer ("wb"), "open output file(%s) failed", outs[0]->get_file_name ()); + } + + SmartPtr<Stitcher> stitcher = create_stitcher (module); + XCAM_ASSERT (stitcher.ptr ()); + + CameraInfo cam_info[4]; + std::string fisheye_config_path = FISHEYE_CONFIG_PATH; + const char *env = std::getenv (FISHEYE_CONFIG_ENV_VAR); + if (env) + fisheye_config_path.assign (env, strlen (env)); + XCAM_LOG_INFO ("calibration config path:%s", fisheye_config_path.c_str ()); + + uint32_t camera_count = ins.size (); + for (uint32_t i = 0; i < camera_count; ++i) { + if (parse_camera_info (fisheye_config_path.c_str (), i, cam_info[i], camera_count) != 0) { + XCAM_LOG_ERROR ("parse fisheye dewarp info(idx:%d) failed.", i); + return -1; + } + } + + PointFloat3 bowl_coord_offset; + centralize_bowl_coord_from_cameras ( + cam_info[0].calibration.extrinsic, cam_info[1].calibration.extrinsic, + cam_info[2].calibration.extrinsic, cam_info[3].calibration.extrinsic, + bowl_coord_offset); + + stitcher->set_camera_num (camera_count); + for (uint32_t i = 0; i < camera_count; ++i) { + stitcher->set_camera_info (i, cam_info[i]); + } + + BowlDataConfig bowl; + bowl.wall_height = 3000.0f; + bowl.ground_length = 2000.0f; + bowl.angle_start = 0.0f; + bowl.angle_end = 360.0f; + stitcher->set_bowl_config (bowl); + stitcher->set_output_size (output_width, output_height); + stitcher->set_scale_mode (scale_mode); + + SmartPtr<RenderOsgViewer> render = new RenderOsgViewer (); + + SmartPtr<RenderOsgModel> svm_model = create_surround_view_model (stitcher, output_width, output_height); + render->add_model (svm_model); + + SmartPtr<RenderOsgModel> car_model = create_car_model (); + render->add_model (car_model); + + render->validate_model_groups (); + + while (loop--) { + CHECK_EXP ( + run_stitcher (stitcher, render, svm_model, ins, outs, save_output) == 0, + "run stitcher failed"); + } + + return 0; +} |