summaryrefslogtreecommitdiffstats
path: root/dev/MinGfx/tests
diff options
context:
space:
mode:
authorMatt Strapp <matt@mattstrapp.net>2021-09-20 18:15:14 -0500
committerMatt Strapp <matt@mattstrapp.net>2021-09-20 18:15:14 -0500
commit342403a02f8063903d0f38327430721d4d0ae331 (patch)
tree29d020a27bc16939c568dd4b29166566d1c0e658 /dev/MinGfx/tests
parentFix parenthesis (diff)
downloadcsci4611-submission-p1.0.tar
csci4611-submission-p1.0.tar.gz
csci4611-submission-p1.0.tar.bz2
csci4611-submission-p1.0.tar.lz
csci4611-submission-p1.0.tar.xz
csci4611-submission-p1.0.tar.zst
csci4611-submission-p1.0.zip
Diffstat (limited to 'dev/MinGfx/tests')
-rw-r--r--dev/MinGfx/tests/blank_window/CMakeLists.txt82
-rw-r--r--dev/MinGfx/tests/blank_window/main.cc50
-rw-r--r--dev/MinGfx/tests/gui_plus_opengl/CMakeLists.txt88
-rw-r--r--dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.cc748
-rw-r--r--dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.h192
-rw-r--r--dev/MinGfx/tests/gui_plus_opengl/main.cc50
6 files changed, 605 insertions, 605 deletions
diff --git a/dev/MinGfx/tests/blank_window/CMakeLists.txt b/dev/MinGfx/tests/blank_window/CMakeLists.txt
index 2081638..b502ddb 100644
--- a/dev/MinGfx/tests/blank_window/CMakeLists.txt
+++ b/dev/MinGfx/tests/blank_window/CMakeLists.txt
@@ -1,41 +1,41 @@
-# This file is part of the MinGfx cmake build system.
-# See the main MinGfx/CMakeLists.txt file for details.
-
-project(mingfx-test-blank-window)
-
-
-# Source:
-set (SOURCEFILES
- main.cc
-)
-set (HEADERFILES
-)
-set (CONFIGFILES
-)
-
-
-# Define the target
-add_executable(${PROJECT_NAME} ${HEADERFILES} ${SOURCEFILES})
-
-
-# Add dependency on libMinGfx:
-target_include_directories(${PROJECT_NAME} PUBLIC ../../src)
-target_link_libraries(${PROJECT_NAME} PUBLIC MinGfx)
-
-# Add external dependency on NanoGUI
-include(AutoBuildNanoGUI)
-AutoBuild_use_package_NanoGUI(${PROJECT_NAME} PUBLIC)
-
-
-
-# Installation:
-install(TARGETS ${PROJECT_NAME}
- RUNTIME DESTINATION ${INSTALL_BIN_DEST}
- COMPONENT Tests)
-
-
-# For better organization when using an IDE with folder structures:
-set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Tests")
-source_group("Header Files" FILES ${HEADERFILES})
-set_source_files_properties(${CONFIGFILES} PROPERTIES HEADER_FILE_ONLY TRUE)
-source_group("Config Files" FILES ${CONFIGFILES})
+# This file is part of the MinGfx cmake build system.
+# See the main MinGfx/CMakeLists.txt file for details.
+
+project(mingfx-test-blank-window)
+
+
+# Source:
+set (SOURCEFILES
+ main.cc
+)
+set (HEADERFILES
+)
+set (CONFIGFILES
+)
+
+
+# Define the target
+add_executable(${PROJECT_NAME} ${HEADERFILES} ${SOURCEFILES})
+
+
+# Add dependency on libMinGfx:
+target_include_directories(${PROJECT_NAME} PUBLIC ../../src)
+target_link_libraries(${PROJECT_NAME} PUBLIC MinGfx)
+
+# Add external dependency on NanoGUI
+include(AutoBuildNanoGUI)
+AutoBuild_use_package_NanoGUI(${PROJECT_NAME} PUBLIC)
+
+
+
+# Installation:
+install(TARGETS ${PROJECT_NAME}
+ RUNTIME DESTINATION ${INSTALL_BIN_DEST}
+ COMPONENT Tests)
+
+
+# For better organization when using an IDE with folder structures:
+set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Tests")
+source_group("Header Files" FILES ${HEADERFILES})
+set_source_files_properties(${CONFIGFILES} PROPERTIES HEADER_FILE_ONLY TRUE)
+source_group("Config Files" FILES ${CONFIGFILES})
diff --git a/dev/MinGfx/tests/blank_window/main.cc b/dev/MinGfx/tests/blank_window/main.cc
index da81ccb..371b209 100644
--- a/dev/MinGfx/tests/blank_window/main.cc
+++ b/dev/MinGfx/tests/blank_window/main.cc
@@ -1,25 +1,25 @@
-/*
- This file is part of the MinGfx Project.
-
- Copyright (c) 2017,2018 Regents of the University of Minnesota.
- All Rights Reserved.
-
- Original Author(s) of this File:
- Dan Keefe, 2018, University of Minnesota
-
- Author(s) of Significant Updates/Modifications to the File:
- ...
- */
-
-// The GraphicsApp base class can also run as its own app, but it just displays a blank screen
-
-#include <mingfx.h>
-using namespace mingfx;
-
-int main(int argc, char **argv) {
-
- GraphicsApp *app = new GraphicsApp(1024, 768, "A Blank Window!");
- app->Run();
-
- return 0;
-}
+/*
+ This file is part of the MinGfx Project.
+
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+
+ Original Author(s) of this File:
+ Dan Keefe, 2018, University of Minnesota
+
+ Author(s) of Significant Updates/Modifications to the File:
+ ...
+ */
+
+// The GraphicsApp base class can also run as its own app, but it just displays a blank screen
+
+#include <mingfx.h>
+using namespace mingfx;
+
+int main(int argc, char **argv) {
+
+ GraphicsApp *app = new GraphicsApp(1024, 768, "A Blank Window!");
+ app->Run();
+
+ return 0;
+}
diff --git a/dev/MinGfx/tests/gui_plus_opengl/CMakeLists.txt b/dev/MinGfx/tests/gui_plus_opengl/CMakeLists.txt
index 5e49e7c..b54ddaa 100644
--- a/dev/MinGfx/tests/gui_plus_opengl/CMakeLists.txt
+++ b/dev/MinGfx/tests/gui_plus_opengl/CMakeLists.txt
@@ -1,44 +1,44 @@
-# This file is part of the MinGfx cmake build system.
-# See the main MinGfx/CMakeLists.txt file for details.
-
-project(mingfx-test-gui-plus-opengl)
-
-
-# Source:
-set (SOURCEFILES
- gui_plus_opengl.cc
- main.cc
-)
-set (HEADERFILES
- gui_plus_opengl.h
-)
-set (CONFIGFILES
-)
-
-
-# Define the target
-add_executable(${PROJECT_NAME} ${HEADERFILES} ${SOURCEFILES})
-
-
-# Add dependency on libMinGfx:
-target_include_directories(${PROJECT_NAME} PUBLIC ../../src)
-target_link_libraries(${PROJECT_NAME} PUBLIC MinGfx)
-
-# Add external dependency on NanoGUI
-include(AutoBuildNanoGUI)
-AutoBuild_use_package_NanoGUI(${PROJECT_NAME} PUBLIC)
-
-
-
-# Installation:
-install(TARGETS ${PROJECT_NAME}
- RUNTIME DESTINATION ${INSTALL_BIN_DEST}
- COMPONENT Tests)
-
-
-# For better organization when using an IDE with folder structures:
-set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Tests")
-source_group("Header Files" FILES ${HEADERFILES})
-set_source_files_properties(${CONFIGFILES} PROPERTIES HEADER_FILE_ONLY TRUE)
-source_group("Config Files" FILES ${CONFIGFILES})
-
+# This file is part of the MinGfx cmake build system.
+# See the main MinGfx/CMakeLists.txt file for details.
+
+project(mingfx-test-gui-plus-opengl)
+
+
+# Source:
+set (SOURCEFILES
+ gui_plus_opengl.cc
+ main.cc
+)
+set (HEADERFILES
+ gui_plus_opengl.h
+)
+set (CONFIGFILES
+)
+
+
+# Define the target
+add_executable(${PROJECT_NAME} ${HEADERFILES} ${SOURCEFILES})
+
+
+# Add dependency on libMinGfx:
+target_include_directories(${PROJECT_NAME} PUBLIC ../../src)
+target_link_libraries(${PROJECT_NAME} PUBLIC MinGfx)
+
+# Add external dependency on NanoGUI
+include(AutoBuildNanoGUI)
+AutoBuild_use_package_NanoGUI(${PROJECT_NAME} PUBLIC)
+
+
+
+# Installation:
+install(TARGETS ${PROJECT_NAME}
+ RUNTIME DESTINATION ${INSTALL_BIN_DEST}
+ COMPONENT Tests)
+
+
+# For better organization when using an IDE with folder structures:
+set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Tests")
+source_group("Header Files" FILES ${HEADERFILES})
+set_source_files_properties(${CONFIGFILES} PROPERTIES HEADER_FILE_ONLY TRUE)
+source_group("Config Files" FILES ${CONFIGFILES})
+
diff --git a/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.cc b/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.cc
index be83d2e..b6dedf7 100644
--- a/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.cc
+++ b/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.cc
@@ -1,374 +1,374 @@
-/*
- Copyright (c) 2017,2018 Regents of the University of Minnesota.
- All Rights Reserved.
- See corresponding header file for details.
- */
-
-
-#define _USE_MATH_DEFINES
-#include "gui_plus_opengl.h"
-#include "default_shader.h"
-#include "mesh.h"
-#include "shader_program.h"
-#include "texture2d.h"
-#include "text_shader.h"
-#include "unicam.h"
-
-
-#pragma warning (push)
-#pragma warning (disable : 6001)
-#pragma warning (disable : 6011)
-#pragma warning (disable : 6262)
-#pragma warning (disable : 6385)
-#pragma warning (disable : 6387)
-#pragma warning (disable : 26450)
-#pragma warning (disable : 26451)
-#pragma warning (disable : 26453)
-#pragma warning (disable : 26495)
-#pragma warning (disable : 26812)
-#include <stb_image.h>
-#pragma warning (pop)
-
-#include <iostream>
-
-
-QuickShapes *qs;
-Ray pickRay;
-
-
-GLuint vbo, vao, vshader, fshader, shaderProgram;
-float model[16];
-GLuint texID = 0;
-
-Mesh mesh1, mesh2;
-ShaderProgram shaderprog1;
-Texture2D tex1;
-
-DefaultShader dShader;
-DefaultShader::MaterialProperties mat1;
-
-Matrix4 P,V;
-
-UniCam uniCam;
-
-Point2 mpos;
-
-
-TextShader ts;
-
-
-
-GuiPlusOpenGL::GuiPlusOpenGL() : GraphicsApp(1024,768, "Circle Simulation") {
-
- InitGraphicsContext();
-
- simTime_ = 0.0;
- paused_ = false;
- pauseBtn_ = NULL;
-
- int i;
- i = mesh1.AddTriangle(Point3(0,0,0), Point3(1,0,0), Point3(1,1,0));
- mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
- mesh1.SetTexCoords(i, 0, Point2(0,0), Point2(1,0), Point2(1,1));
- i = mesh1.AddTriangle(Point3(0,0,0), Point3(1,1,0), Point3(0,1,0));
- mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
- mesh1.SetTexCoords(i, 0, Point2(0,0), Point2(1,1), Point2(0,1));
-
- //i = mesh1.AppendTriangle(Point3(0,0,0), Point3(0,0,1), Point3(1,1,0));
- //mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
-}
-
-
-
-
-GuiPlusOpenGL::~GuiPlusOpenGL() {
-
-}
-
-void GuiPlusOpenGL::InitNanoGUI() {
- nanogui::FormHelper *gui = new nanogui::FormHelper(screen());
- nanogui::ref<nanogui::Window> window = gui->addWindow(Eigen::Vector2i(10, 10), "Simulation Controls");
- pauseBtn_ = gui->addButton("Pause", std::bind(&GuiPlusOpenGL::OnPauseBtnPressed, this));
- gui->addButton("Restart", std::bind(&GuiPlusOpenGL::OnRestartBtnPressed, this));
-
- screen()->performLayout();
-}
-
-
-
-void GuiPlusOpenGL::UpdateSimulation(double dt) {
- if (!paused_) {
- simTime_ += dt;
- //std::cout << "Update Simulation " << simTime_ << std::endl;
- }
- uniCam.AdvanceAnimation(dt);
-}
-
-
-void GuiPlusOpenGL::OnRestartBtnPressed() {
- simTime_ = 0.0;
-}
-
-void GuiPlusOpenGL::OnPauseBtnPressed() {
- paused_ = !paused_;
- if (paused_) {
- pauseBtn_->setCaption("Play");
- }
- else {
- pauseBtn_->setCaption("Pause");
- }
-}
-
-
-
-void GuiPlusOpenGL::OnMouseMove(const Point2 &pos, const Vector2 &delta) {
- //std::cout << "Mouse moved to " << pos << " delta from last frame " << delta << std::endl;
-
- Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
- Point3 filmplanePt = GfxMath::ScreenToNearPlane(uniCam.view_matrix(), P, mouseInNDC);
-
- Matrix4 camMat = uniCam.view_matrix().Inverse();
- Point3 eye = camMat.ColumnToPoint3(3);
-
- pickRay = Ray(eye, filmplanePt - eye);
-
- mpos = pos;
-}
-
-void GuiPlusOpenGL::OnLeftMouseDown(const Point2 &pos) {
- //std::cout << "Left mouse button down at " << pos << std::endl;
-
- Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
- float mouseZ = ReadZValueAtPixel(pos);
- uniCam.OnButtonDown(mouseInNDC, mouseZ);
-
-}
-
-void GuiPlusOpenGL::OnLeftMouseDrag(const Point2 &pos, const Vector2 &delta) {
- //std::cout << "Mouse dragged (left button) to " << pos << " delta from last frame " << delta << std::endl;
-
- Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
- uniCam.OnDrag(mouseInNDC);
-}
-
-void GuiPlusOpenGL::OnLeftMouseUp(const Point2 &pos) {
- //std::cout << "Left mouse button up at " << pos << std::endl;
-
- Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
- uniCam.OnButtonUp(mouseInNDC);
-
-}
-
-
-void GuiPlusOpenGL::OnMiddleMouseDown(const Point2 &pos) {
- //std::cout << "Middle mouse button down at " << pos << std::endl;
-}
-
-void GuiPlusOpenGL::OnMiddleMouseDrag(const Point2 &pos, const Vector2 &delta) {
- //std::cout << "Mouse dragged (middle button) to " << pos << " delta from last frame " << delta << std::endl;
-}
-
-void GuiPlusOpenGL::OnMiddleMouseUp(const Point2 &pos) {
- //std::cout << "Middle mouse button up at " << pos << std::endl;
-}
-
-
-void GuiPlusOpenGL::OnRightMouseDown(const Point2 &pos) {
- //std::cout << "Right mouse button down at " << pos << std::endl;
-}
-
-void GuiPlusOpenGL::OnRightMouseDrag(const Point2 &pos, const Vector2 &delta) {
- //std::cout << "Mouse dragged (right button) to " << pos << " delta from last frame " << delta << std::endl;
- Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
- Point3 filmplanePt = GfxMath::ScreenToNearPlane(uniCam.view_matrix(), P, mouseInNDC);
-
- Matrix4 camMat = uniCam.view_matrix().Inverse();
- Point3 eye = camMat.ColumnToPoint3(3);
-
- pickRay = Ray(eye, filmplanePt - eye);
-}
-
-void GuiPlusOpenGL::OnRightMouseUp(const Point2 &pos) {
- //std::cout << "Right mouse button up at " << pos << std::endl;
-}
-
-
-
-void GuiPlusOpenGL::OnKeyDown(const char *c, int modifiers) {
- //std::cout << "Key DOWN (" << c << ") modifiers=" << modifiers << std::endl;
-}
-
-void GuiPlusOpenGL::OnKeyUp(const char *c, int modifiers) {
- //std::cout << "Key UP (" << c << ") modifiers=" << modifiers << std::endl;
-}
-
-void GuiPlusOpenGL::OnSpecialKeyDown(int key, int scancode, int modifiers) {
- //std::cout << "Special Key DOWN key=" << key << " scancode=" << scancode << " modifiers=" << modifiers << std::endl;
-}
-
-void GuiPlusOpenGL::OnSpecialKeyUp(int key, int scancode, int modifiers) {
- //std::cout << "Special Key UP key=" << key << " scancode=" << scancode << " modifiers=" << modifiers << std::endl;
-}
-
-
-void GuiPlusOpenGL::DrawUsingNanoVG(NVGcontext *ctx) {
-
- // example of drawing some circles
-
- nvgBeginPath(ctx);
- nvgCircle(ctx, 512.0f+50.0f*std::cosf((float)simTime_), 350.0f+200.0f*std::sinf((float)simTime_), 50.0f);
- nvgFillColor(ctx, nvgRGBA(100,100,255,200));
- nvgFill(ctx);
- nvgStrokeColor(ctx, nvgRGBA(0,0,0,255));
- nvgStroke(ctx);
-
- nvgBeginPath(ctx);
- nvgCircle(ctx, 512.0f+200.0f*std::cosf((float)simTime_), 350.0f+50.0f*std::sinf((float)simTime_), 50.0f);
- nvgFillColor(ctx, nvgRGBA(255,100,100,200));
- nvgFill(ctx);
- nvgStrokeColor(ctx, nvgRGBA(0,0,0,255));
- nvgStroke(ctx);
-
-}
-
-
-void GuiPlusOpenGL::InitOpenGL() {
- std::string fname = Platform::FindMinGfxDataFile("Futura_Medium_BT.ttf");
- ts.Init(fname, 42);
-
- qs = new QuickShapes();
-
- P = Matrix4::Perspective(60.0f, aspect_ratio(), 0.1f, 10.0f);
- V = Matrix4::LookAt(Point3(0,0,3), Point3(0,0,0), Vector3(0,1,0));
- uniCam.set_view_matrix(V);
-
- mesh1.UpdateGPUMemory();
-
- mesh2.LoadFromOBJ(Platform::FindMinGfxDataFile("teapot.obj"));
- std::vector<Matrix4> xforms;
- for (float x=-4.0; x <= 4.0; x += 1.0) {
- //xforms.push_back(Matrix4());
- xforms.push_back(Matrix4::Translation(Vector3(x,0,0)));
- }
- mesh2.SetInstanceTransforms(xforms);
-
-
- tex1.InitFromFile(Platform::FindMinGfxDataFile("test.png"));
- mat1.surface_texture = tex1;
-
- DefaultShader::LightProperties l;
- l.position = Point3(-10, 5, 5);
- l.diffuse_intensity = Color(1,0,0);
- dShader.AddLight(l);
-}
-
-
-void GuiPlusOpenGL::DrawUsingOpenGL() {
-
- V = uniCam.view_matrix();
- Matrix4 M = Matrix4::Translation(Vector3(-1,0,0)) * Matrix4::Scale(Vector3(0.5, 0.5, 0.5));
-
- // Draw several quick shapes
- float col[3] = {0.4f, 0.4f, 0.8f};
- Matrix4 M2 = Matrix4::Translation(Vector3(1.0f, 1.5f, 0.0f))*Matrix4::Scale(Vector3(0.2f, 0.2f, 0.2f));
- qs->DrawSphere(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawCylinder(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawCone(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawCube(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawBrush(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawSquare(M2, V, P, col);
-
- M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
- qs->DrawSquare(M2, V, P, col, tex1);
-
-
- qs->DrawArrow(Matrix4(), V, P, col, Point3(0,0,0), Vector3(-1,1.5,0), 0.01f);
-
- qs->DrawLineSegment(Matrix4(), V, P, col, Point3(0,0,0), Point3(1, 1.5, 0), 0.01f);
-
- qs->DrawAxes(Matrix4(), V, P);
-
- dShader.Draw(Matrix4(), V, P, &mesh1, mat1);
- dShader.Draw(Matrix4(), V, P, &mesh2, DefaultShader::MaterialProperties());
-
-
- float t;
- Point3 p;
- int id;
- if (pickRay.IntersectMesh(mesh1, &t, &p, &id)) {
- M2 = Matrix4::Translation(p - Point3::Origin()) * Matrix4::Scale(Vector3(0.025f, 0.025f, 0.025f));
- qs->DrawSphere(M2, V, P, Color(1,0,1));
- }
- if (pickRay.IntersectMesh(mesh2, &t, &p, &id)) {
- M2 = Matrix4::Translation(p - Point3::Origin()) * Matrix4::Scale(Vector3(0.025f, 0.025f, 0.025f));
- qs->DrawSphere(M2, V, P, Color(1,1,0));
- }
-
- uniCam.Draw(P);
-
-
- Matrix4 M3 = Matrix4::Translation(Vector3(-1,0,0));
- TextShader::TextFormat f;
-
-
- f.color = Color(1,1,0);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
- ts.Draw3D(M3, V, P, "TOPgg", f, true);
-
- f.color = Color(0,1,1);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_CENTER;
- ts.Draw3D(M3, V, P, "V_CENTERyy", f, true);
-
- f.color = Color(1,0,1);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_BOTTOM;
- ts.Draw3D(M3, V, P, "BOTTOMgg", f, true);
-
- f.color = Color(1,1,1);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_BASELINE;
- ts.Draw3D(M3, V, P, "Hello good buddy", f, true);
-
- qs->DrawLineSegment(M3, V, P, col, Point3(0,0,0), Point3(1, 0, 0), 0.01f);
-
- M3 = M3 * Matrix4::Translation(Vector3(0,0.5,0));
-
-
- f.color = Color(1,0,0);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_LEFT;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
- ts.Draw3D(M3, V, P, "LEFT", f, true);
-
- f.color = Color(0,1,0);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
- ts.Draw3D(M3, V, P, "CENTER", f, true);
-
- f.color = Color(0,0,1);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_RIGHT;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
- ts.Draw3D(M3, V, P, "RIGHT", f, true);
-
-
- M3 = Matrix4::Translation(Vector3(0,0,1));
- f.color = Color(1,1,1);
- f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
- f.v_align = TextShader::VertAlign::VERT_ALIGN_BASELINE;
- f.size = 0.25;
- ts.Draw3D(M3, V, P, "Hello good buddy", f, true);
-
-
- //std::cout << mpos << " z = " << z_value_at_pixel(mpos) << std::endl;
-}
+/*
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+ See corresponding header file for details.
+ */
+
+
+#define _USE_MATH_DEFINES
+#include "gui_plus_opengl.h"
+#include "default_shader.h"
+#include "mesh.h"
+#include "shader_program.h"
+#include "texture2d.h"
+#include "text_shader.h"
+#include "unicam.h"
+
+
+#pragma warning (push)
+#pragma warning (disable : 6001)
+#pragma warning (disable : 6011)
+#pragma warning (disable : 6262)
+#pragma warning (disable : 6385)
+#pragma warning (disable : 6387)
+#pragma warning (disable : 26450)
+#pragma warning (disable : 26451)
+#pragma warning (disable : 26453)
+#pragma warning (disable : 26495)
+#pragma warning (disable : 26812)
+#include <stb_image.h>
+#pragma warning (pop)
+
+#include <iostream>
+
+
+QuickShapes *qs;
+Ray pickRay;
+
+
+GLuint vbo, vao, vshader, fshader, shaderProgram;
+float model[16];
+GLuint texID = 0;
+
+Mesh mesh1, mesh2;
+ShaderProgram shaderprog1;
+Texture2D tex1;
+
+DefaultShader dShader;
+DefaultShader::MaterialProperties mat1;
+
+Matrix4 P,V;
+
+UniCam uniCam;
+
+Point2 mpos;
+
+
+TextShader ts;
+
+
+
+GuiPlusOpenGL::GuiPlusOpenGL() : GraphicsApp(1024,768, "Circle Simulation") {
+
+ InitGraphicsContext();
+
+ simTime_ = 0.0;
+ paused_ = false;
+ pauseBtn_ = NULL;
+
+ int i;
+ i = mesh1.AddTriangle(Point3(0,0,0), Point3(1,0,0), Point3(1,1,0));
+ mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
+ mesh1.SetTexCoords(i, 0, Point2(0,0), Point2(1,0), Point2(1,1));
+ i = mesh1.AddTriangle(Point3(0,0,0), Point3(1,1,0), Point3(0,1,0));
+ mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
+ mesh1.SetTexCoords(i, 0, Point2(0,0), Point2(1,1), Point2(0,1));
+
+ //i = mesh1.AppendTriangle(Point3(0,0,0), Point3(0,0,1), Point3(1,1,0));
+ //mesh1.SetNormals(i, Vector3(0,0,1), Vector3(0,0,1), Vector3(0,0,1));
+}
+
+
+
+
+GuiPlusOpenGL::~GuiPlusOpenGL() {
+
+}
+
+void GuiPlusOpenGL::InitNanoGUI() {
+ nanogui::FormHelper *gui = new nanogui::FormHelper(screen());
+ nanogui::ref<nanogui::Window> window = gui->addWindow(Eigen::Vector2i(10, 10), "Simulation Controls");
+ pauseBtn_ = gui->addButton("Pause", std::bind(&GuiPlusOpenGL::OnPauseBtnPressed, this));
+ gui->addButton("Restart", std::bind(&GuiPlusOpenGL::OnRestartBtnPressed, this));
+
+ screen()->performLayout();
+}
+
+
+
+void GuiPlusOpenGL::UpdateSimulation(double dt) {
+ if (!paused_) {
+ simTime_ += dt;
+ //std::cout << "Update Simulation " << simTime_ << std::endl;
+ }
+ uniCam.AdvanceAnimation(dt);
+}
+
+
+void GuiPlusOpenGL::OnRestartBtnPressed() {
+ simTime_ = 0.0;
+}
+
+void GuiPlusOpenGL::OnPauseBtnPressed() {
+ paused_ = !paused_;
+ if (paused_) {
+ pauseBtn_->setCaption("Play");
+ }
+ else {
+ pauseBtn_->setCaption("Pause");
+ }
+}
+
+
+
+void GuiPlusOpenGL::OnMouseMove(const Point2 &pos, const Vector2 &delta) {
+ //std::cout << "Mouse moved to " << pos << " delta from last frame " << delta << std::endl;
+
+ Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
+ Point3 filmplanePt = GfxMath::ScreenToNearPlane(uniCam.view_matrix(), P, mouseInNDC);
+
+ Matrix4 camMat = uniCam.view_matrix().Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+
+ pickRay = Ray(eye, filmplanePt - eye);
+
+ mpos = pos;
+}
+
+void GuiPlusOpenGL::OnLeftMouseDown(const Point2 &pos) {
+ //std::cout << "Left mouse button down at " << pos << std::endl;
+
+ Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
+ float mouseZ = ReadZValueAtPixel(pos);
+ uniCam.OnButtonDown(mouseInNDC, mouseZ);
+
+}
+
+void GuiPlusOpenGL::OnLeftMouseDrag(const Point2 &pos, const Vector2 &delta) {
+ //std::cout << "Mouse dragged (left button) to " << pos << " delta from last frame " << delta << std::endl;
+
+ Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
+ uniCam.OnDrag(mouseInNDC);
+}
+
+void GuiPlusOpenGL::OnLeftMouseUp(const Point2 &pos) {
+ //std::cout << "Left mouse button up at " << pos << std::endl;
+
+ Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
+ uniCam.OnButtonUp(mouseInNDC);
+
+}
+
+
+void GuiPlusOpenGL::OnMiddleMouseDown(const Point2 &pos) {
+ //std::cout << "Middle mouse button down at " << pos << std::endl;
+}
+
+void GuiPlusOpenGL::OnMiddleMouseDrag(const Point2 &pos, const Vector2 &delta) {
+ //std::cout << "Mouse dragged (middle button) to " << pos << " delta from last frame " << delta << std::endl;
+}
+
+void GuiPlusOpenGL::OnMiddleMouseUp(const Point2 &pos) {
+ //std::cout << "Middle mouse button up at " << pos << std::endl;
+}
+
+
+void GuiPlusOpenGL::OnRightMouseDown(const Point2 &pos) {
+ //std::cout << "Right mouse button down at " << pos << std::endl;
+}
+
+void GuiPlusOpenGL::OnRightMouseDrag(const Point2 &pos, const Vector2 &delta) {
+ //std::cout << "Mouse dragged (right button) to " << pos << " delta from last frame " << delta << std::endl;
+ Point2 mouseInNDC = PixelsToNormalizedDeviceCoords(pos);
+ Point3 filmplanePt = GfxMath::ScreenToNearPlane(uniCam.view_matrix(), P, mouseInNDC);
+
+ Matrix4 camMat = uniCam.view_matrix().Inverse();
+ Point3 eye = camMat.ColumnToPoint3(3);
+
+ pickRay = Ray(eye, filmplanePt - eye);
+}
+
+void GuiPlusOpenGL::OnRightMouseUp(const Point2 &pos) {
+ //std::cout << "Right mouse button up at " << pos << std::endl;
+}
+
+
+
+void GuiPlusOpenGL::OnKeyDown(const char *c, int modifiers) {
+ //std::cout << "Key DOWN (" << c << ") modifiers=" << modifiers << std::endl;
+}
+
+void GuiPlusOpenGL::OnKeyUp(const char *c, int modifiers) {
+ //std::cout << "Key UP (" << c << ") modifiers=" << modifiers << std::endl;
+}
+
+void GuiPlusOpenGL::OnSpecialKeyDown(int key, int scancode, int modifiers) {
+ //std::cout << "Special Key DOWN key=" << key << " scancode=" << scancode << " modifiers=" << modifiers << std::endl;
+}
+
+void GuiPlusOpenGL::OnSpecialKeyUp(int key, int scancode, int modifiers) {
+ //std::cout << "Special Key UP key=" << key << " scancode=" << scancode << " modifiers=" << modifiers << std::endl;
+}
+
+
+void GuiPlusOpenGL::DrawUsingNanoVG(NVGcontext *ctx) {
+
+ // example of drawing some circles
+
+ nvgBeginPath(ctx);
+ nvgCircle(ctx, 512.0f+50.0f*std::cosf((float)simTime_), 350.0f+200.0f*std::sinf((float)simTime_), 50.0f);
+ nvgFillColor(ctx, nvgRGBA(100,100,255,200));
+ nvgFill(ctx);
+ nvgStrokeColor(ctx, nvgRGBA(0,0,0,255));
+ nvgStroke(ctx);
+
+ nvgBeginPath(ctx);
+ nvgCircle(ctx, 512.0f+200.0f*std::cosf((float)simTime_), 350.0f+50.0f*std::sinf((float)simTime_), 50.0f);
+ nvgFillColor(ctx, nvgRGBA(255,100,100,200));
+ nvgFill(ctx);
+ nvgStrokeColor(ctx, nvgRGBA(0,0,0,255));
+ nvgStroke(ctx);
+
+}
+
+
+void GuiPlusOpenGL::InitOpenGL() {
+ std::string fname = Platform::FindMinGfxDataFile("Futura_Medium_BT.ttf");
+ ts.Init(fname, 42);
+
+ qs = new QuickShapes();
+
+ P = Matrix4::Perspective(60.0f, aspect_ratio(), 0.1f, 10.0f);
+ V = Matrix4::LookAt(Point3(0,0,3), Point3(0,0,0), Vector3(0,1,0));
+ uniCam.set_view_matrix(V);
+
+ mesh1.UpdateGPUMemory();
+
+ mesh2.LoadFromOBJ(Platform::FindMinGfxDataFile("teapot.obj"));
+ std::vector<Matrix4> xforms;
+ for (float x=-4.0; x <= 4.0; x += 1.0) {
+ //xforms.push_back(Matrix4());
+ xforms.push_back(Matrix4::Translation(Vector3(x,0,0)));
+ }
+ mesh2.SetInstanceTransforms(xforms);
+
+
+ tex1.InitFromFile(Platform::FindMinGfxDataFile("test.png"));
+ mat1.surface_texture = tex1;
+
+ DefaultShader::LightProperties l;
+ l.position = Point3(-10, 5, 5);
+ l.diffuse_intensity = Color(1,0,0);
+ dShader.AddLight(l);
+}
+
+
+void GuiPlusOpenGL::DrawUsingOpenGL() {
+
+ V = uniCam.view_matrix();
+ Matrix4 M = Matrix4::Translation(Vector3(-1,0,0)) * Matrix4::Scale(Vector3(0.5, 0.5, 0.5));
+
+ // Draw several quick shapes
+ float col[3] = {0.4f, 0.4f, 0.8f};
+ Matrix4 M2 = Matrix4::Translation(Vector3(1.0f, 1.5f, 0.0f))*Matrix4::Scale(Vector3(0.2f, 0.2f, 0.2f));
+ qs->DrawSphere(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawCylinder(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawCone(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawCube(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawBrush(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawSquare(M2, V, P, col);
+
+ M2 = Matrix4::Translation(Vector3(0,-0.5,0)) * M2;
+ qs->DrawSquare(M2, V, P, col, tex1);
+
+
+ qs->DrawArrow(Matrix4(), V, P, col, Point3(0,0,0), Vector3(-1,1.5,0), 0.01f);
+
+ qs->DrawLineSegment(Matrix4(), V, P, col, Point3(0,0,0), Point3(1, 1.5, 0), 0.01f);
+
+ qs->DrawAxes(Matrix4(), V, P);
+
+ dShader.Draw(Matrix4(), V, P, &mesh1, mat1);
+ dShader.Draw(Matrix4(), V, P, &mesh2, DefaultShader::MaterialProperties());
+
+
+ float t;
+ Point3 p;
+ int id;
+ if (pickRay.IntersectMesh(mesh1, &t, &p, &id)) {
+ M2 = Matrix4::Translation(p - Point3::Origin()) * Matrix4::Scale(Vector3(0.025f, 0.025f, 0.025f));
+ qs->DrawSphere(M2, V, P, Color(1,0,1));
+ }
+ if (pickRay.IntersectMesh(mesh2, &t, &p, &id)) {
+ M2 = Matrix4::Translation(p - Point3::Origin()) * Matrix4::Scale(Vector3(0.025f, 0.025f, 0.025f));
+ qs->DrawSphere(M2, V, P, Color(1,1,0));
+ }
+
+ uniCam.Draw(P);
+
+
+ Matrix4 M3 = Matrix4::Translation(Vector3(-1,0,0));
+ TextShader::TextFormat f;
+
+
+ f.color = Color(1,1,0);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
+ ts.Draw3D(M3, V, P, "TOPgg", f, true);
+
+ f.color = Color(0,1,1);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_CENTER;
+ ts.Draw3D(M3, V, P, "V_CENTERyy", f, true);
+
+ f.color = Color(1,0,1);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_BOTTOM;
+ ts.Draw3D(M3, V, P, "BOTTOMgg", f, true);
+
+ f.color = Color(1,1,1);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_BASELINE;
+ ts.Draw3D(M3, V, P, "Hello good buddy", f, true);
+
+ qs->DrawLineSegment(M3, V, P, col, Point3(0,0,0), Point3(1, 0, 0), 0.01f);
+
+ M3 = M3 * Matrix4::Translation(Vector3(0,0.5,0));
+
+
+ f.color = Color(1,0,0);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_LEFT;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
+ ts.Draw3D(M3, V, P, "LEFT", f, true);
+
+ f.color = Color(0,1,0);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
+ ts.Draw3D(M3, V, P, "CENTER", f, true);
+
+ f.color = Color(0,0,1);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_RIGHT;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_TOP;
+ ts.Draw3D(M3, V, P, "RIGHT", f, true);
+
+
+ M3 = Matrix4::Translation(Vector3(0,0,1));
+ f.color = Color(1,1,1);
+ f.h_align = TextShader::HorizAlign::HORIZ_ALIGN_CENTER;
+ f.v_align = TextShader::VertAlign::VERT_ALIGN_BASELINE;
+ f.size = 0.25;
+ ts.Draw3D(M3, V, P, "Hello good buddy", f, true);
+
+
+ //std::cout << mpos << " z = " << z_value_at_pixel(mpos) << std::endl;
+}
diff --git a/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.h b/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.h
index faf3580..316b747 100644
--- a/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.h
+++ b/dev/MinGfx/tests/gui_plus_opengl/gui_plus_opengl.h
@@ -1,96 +1,96 @@
-/*
- This file is part of the MinGfx Project.
-
- Copyright (c) 2017,2018 Regents of the University of Minnesota.
- All Rights Reserved.
-
- Original Author(s) of this File:
- Dan Keefe, 2018, University of Minnesota
-
- Author(s) of Significant Updates/Modifications to the File:
- ...
- */
-
-#include <mingfx.h>
-using namespace mingfx;
-
-
-/** An application that opens up a window that includes a few buttons
- for controlling the simulation and can be used to draw circles and
- other computer graphics.
-
- After constructing a new CircleViewer, call Run() to start and
- run the application. Run() will not return until the application
- window is closed. Make sure that you call cs3081::InitGraphics()
- before creating the RobotViewer app. Example:
-
- ```
- int main(int argc, char **argv) {
- cs3081::InitGraphics();
- cs3081::CircleViewer *app = new cs3081::CircleViewer();
- app->Run();
- cs3081::ShutdownGraphics();
- return 0;
- }
- ```
-
- While the window is open UpdateSimulation() will be called
- repeatedly, once per frame. Fill this in to update your simulation
- or perform any other processing that should happen over time as the
- simulation progresses.
-
- Fill in the On*() methods as desired to respond to user input events.
-
- Fill in the Draw*() methods to draw graphics to the screen using
- either the nanovg library or raw OpenGL.
-*/
-class GuiPlusOpenGL : public GraphicsApp {
-public:
- GuiPlusOpenGL();
- ~GuiPlusOpenGL();
-
- void InitNanoGUI();
-
- void UpdateSimulation(double dt);
-
-
- void OnRestartBtnPressed();
- void OnPauseBtnPressed();
-
-
- void OnMouseMove(const Point2 &pos, const Vector2 &delta);
-
- void OnLeftMouseDown(const Point2 &pos);
- void OnLeftMouseDrag(const Point2 &pos, const Vector2 &delta);
- void OnLeftMouseUp(const Point2 &pos);
-
- void OnMiddleMouseDown(const Point2 &pos);
- void OnMiddleMouseDrag(const Point2 &pos, const Vector2 &delta);
- void OnMiddleMouseUp(const Point2 &pos);
-
- void OnRightMouseDown(const Point2 &pos);
- void OnRightMouseDrag(const Point2 &pos, const Vector2 &delta);
- void OnRightMouseUp(const Point2 &pos);
-
-
-
- void OnKeyDown(const char *c, int modifiers);
-
- void OnKeyUp(const char *c, int modifiers);
-
- void OnSpecialKeyDown(int key, int scancode, int modifiers);
-
- void OnSpecialKeyUp(int key, int scancode, int modifiers);
-
-
- void DrawUsingNanoVG(NVGcontext *ctx);
-
- void InitOpenGL();
-
- void DrawUsingOpenGL();
-
-private:
- double simTime_;
- bool paused_;
- nanogui::Button *pauseBtn_;
-};
+/*
+ This file is part of the MinGfx Project.
+
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+
+ Original Author(s) of this File:
+ Dan Keefe, 2018, University of Minnesota
+
+ Author(s) of Significant Updates/Modifications to the File:
+ ...
+ */
+
+#include <mingfx.h>
+using namespace mingfx;
+
+
+/** An application that opens up a window that includes a few buttons
+ for controlling the simulation and can be used to draw circles and
+ other computer graphics.
+
+ After constructing a new CircleViewer, call Run() to start and
+ run the application. Run() will not return until the application
+ window is closed. Make sure that you call cs3081::InitGraphics()
+ before creating the RobotViewer app. Example:
+
+ ```
+ int main(int argc, char **argv) {
+ cs3081::InitGraphics();
+ cs3081::CircleViewer *app = new cs3081::CircleViewer();
+ app->Run();
+ cs3081::ShutdownGraphics();
+ return 0;
+ }
+ ```
+
+ While the window is open UpdateSimulation() will be called
+ repeatedly, once per frame. Fill this in to update your simulation
+ or perform any other processing that should happen over time as the
+ simulation progresses.
+
+ Fill in the On*() methods as desired to respond to user input events.
+
+ Fill in the Draw*() methods to draw graphics to the screen using
+ either the nanovg library or raw OpenGL.
+*/
+class GuiPlusOpenGL : public GraphicsApp {
+public:
+ GuiPlusOpenGL();
+ ~GuiPlusOpenGL();
+
+ void InitNanoGUI();
+
+ void UpdateSimulation(double dt);
+
+
+ void OnRestartBtnPressed();
+ void OnPauseBtnPressed();
+
+
+ void OnMouseMove(const Point2 &pos, const Vector2 &delta);
+
+ void OnLeftMouseDown(const Point2 &pos);
+ void OnLeftMouseDrag(const Point2 &pos, const Vector2 &delta);
+ void OnLeftMouseUp(const Point2 &pos);
+
+ void OnMiddleMouseDown(const Point2 &pos);
+ void OnMiddleMouseDrag(const Point2 &pos, const Vector2 &delta);
+ void OnMiddleMouseUp(const Point2 &pos);
+
+ void OnRightMouseDown(const Point2 &pos);
+ void OnRightMouseDrag(const Point2 &pos, const Vector2 &delta);
+ void OnRightMouseUp(const Point2 &pos);
+
+
+
+ void OnKeyDown(const char *c, int modifiers);
+
+ void OnKeyUp(const char *c, int modifiers);
+
+ void OnSpecialKeyDown(int key, int scancode, int modifiers);
+
+ void OnSpecialKeyUp(int key, int scancode, int modifiers);
+
+
+ void DrawUsingNanoVG(NVGcontext *ctx);
+
+ void InitOpenGL();
+
+ void DrawUsingOpenGL();
+
+private:
+ double simTime_;
+ bool paused_;
+ nanogui::Button *pauseBtn_;
+};
diff --git a/dev/MinGfx/tests/gui_plus_opengl/main.cc b/dev/MinGfx/tests/gui_plus_opengl/main.cc
index e520953..f3b5e09 100644
--- a/dev/MinGfx/tests/gui_plus_opengl/main.cc
+++ b/dev/MinGfx/tests/gui_plus_opengl/main.cc
@@ -1,25 +1,25 @@
-/*
- This file is part of the MinGfx Project.
-
- Copyright (c) 2017,2018 Regents of the University of Minnesota.
- All Rights Reserved.
-
- Original Author(s) of this File:
- Dan Keefe, 2018, University of Minnesota
-
- Author(s) of Significant Updates/Modifications to the File:
- ...
- */
-
-#include <mingfx.h>
-#include "gui_plus_opengl.h"
-
-
-int main(int argc, char **argv) {
-
- GuiPlusOpenGL *app = new GuiPlusOpenGL();
- app->Run();
-
- return 0;
-}
-
+/*
+ This file is part of the MinGfx Project.
+
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+
+ Original Author(s) of this File:
+ Dan Keefe, 2018, University of Minnesota
+
+ Author(s) of Significant Updates/Modifications to the File:
+ ...
+ */
+
+#include <mingfx.h>
+#include "gui_plus_opengl.h"
+
+
+int main(int argc, char **argv) {
+
+ GuiPlusOpenGL *app = new GuiPlusOpenGL();
+ app->Run();
+
+ return 0;
+}
+