diff --git a/builtins/rendercore/CMakeLists.txt b/builtins/rendercore/CMakeLists.txt index 30efcd02e24ae..c4f6e49585924 100644 --- a/builtins/rendercore/CMakeLists.txt +++ b/builtins/rendercore/CMakeLists.txt @@ -1,7 +1,7 @@ ExternalProject_Add( RENDERCORE - URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-2.0.tar.gz - URL_HASH SHA256=6bdcf70fbdec1f950057ab1df722775c468ad6894f8a364f15f589d58c326667 + URL ${CMAKE_SOURCE_DIR}/builtins/rendercore/RenderCore-2.1.tar.gz + URL_HASH SHA256=fee8250baf8e5e1946170dd91e312d2f4a86f8dedd7f8c4e744c6671587114ab CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/builtins/rendercore/RenderCore-2.0.tar.gz b/builtins/rendercore/RenderCore-2.0.tar.gz deleted file mode 100644 index 784462453568f..0000000000000 Binary files a/builtins/rendercore/RenderCore-2.0.tar.gz and /dev/null differ diff --git a/builtins/rendercore/RenderCore-2.1.tar.gz b/builtins/rendercore/RenderCore-2.1.tar.gz new file mode 100644 index 0000000000000..7053893dd5964 Binary files /dev/null and b/builtins/rendercore/RenderCore-2.1.tar.gz differ diff --git a/graf3d/eve7/CMakeLists.txt b/graf3d/eve7/CMakeLists.txt index f6152ee616c14..71179175651b7 100644 --- a/graf3d/eve7/CMakeLists.txt +++ b/graf3d/eve7/CMakeLists.txt @@ -63,6 +63,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTEve ROOT/REveUtil.hxx ROOT/REveVector.hxx ROOT/REveViewer.hxx + ROOT/REveCamera.hxx ROOT/REveViewContext.hxx ROOT/REveVSD.hxx ROOT/REveVSDStructs.hxx @@ -126,6 +127,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTEve src/REveUtil.cxx src/REveVector.cxx src/REveViewer.cxx + src/REveCamera.cxx src/REveVSD.cxx src/REveVSDStructs.cxx DEPENDENCIES diff --git a/graf3d/eve7/inc/LinkDef.h b/graf3d/eve7/inc/LinkDef.h index b8e4754f53e5e..d35f4d9c21b2e 100644 --- a/graf3d/eve7/inc/LinkDef.h +++ b/graf3d/eve7/inc/LinkDef.h @@ -250,4 +250,8 @@ // Tables #pragma link C++ class ROOT::Experimental::REveTableViewInfo; +// Camera +#pragma link C++ class ROOT::Experimental::REveCamera+; +#pragma link C++ enum ROOT::Experimental::REveCamera::ECameraType; + #endif diff --git a/graf3d/eve7/inc/ROOT/REveCamera.hxx b/graf3d/eve7/inc/ROOT/REveCamera.hxx new file mode 100644 index 0000000000000..c21174f8523e5 --- /dev/null +++ b/graf3d/eve7/inc/ROOT/REveCamera.hxx @@ -0,0 +1,95 @@ +// @(#)root/eve7:$Id$ +// Authors: Yuxiao Wang, 2025 + +/************************************************************************* + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT7_REveCamera +#define ROOT7_REveCamera + +#include +#include +#include + +#include + +namespace ROOT { +namespace Experimental { + +class REveCamera : public REveElement +{ +public: + enum ECameraType { + // Perspective + kCameraPerspXOZ, // XOZ floor + kCameraPerspYOZ, // YOZ floor + kCameraPerspXOY, // XOY floor + // Orthographic + kCameraOrthoXOY, // Looking down Z axis, X horz, Y vert + kCameraOrthoXOZ, // Looking along Y axis, X horz, Z vert + kCameraOrthoZOY, // Looking along X axis, Z horz, Y vert + kCameraOrthoZOX, // Looking along Y axis, Z horz, X vert + // Orthographic negative + kCameraOrthoXnOY, // Looking along Z axis, -X horz, Y vert + kCameraOrthoXnOZ, // Looking down Y axis, -X horz, Z vert + kCameraOrthoZnOY, // Looking down X axis, -Z horz, Y vert + kCameraOrthoZnOX // Looking down Y axis, -Z horz, X vert + }; + +private: + ECameraType fType; + std::string fName; + + // Camera transformation matrices + REveTrans fCamBase; // Base camera matrix (main positioning) + REveTrans fCamTrans; + Bool_t fInitialized{kFALSE}; + float fOrthoZoom{1.f}; + +public: + REveCamera(); + REveCamera(const std::string &name); + virtual ~REveCamera() {} + + void Setup(ECameraType type, const std::string &name, const REveVector &v1, const REveVector &v2); + + ECameraType GetType() const { return fType; } + const std::string &GetCameraName() const { return fName; } + + // Camera matrix accessors + REveTrans &RefCamBase() { return fCamBase; } + const REveTrans &GetCamBase() const { return fCamBase; } + + REveTrans &RefCamTrans() { return fCamTrans; } + const REveTrans &GetCamTrans() const { return fCamTrans; } + + void SetCamBase(const REveTrans &base) { fCamBase = base; StampObjProps(); } + + // receive mtx from client + void SetCamBaseMtx(const std::vector &arr); + void SetCamBaseMtx(const std::string &json_str); + + void SetCamTransMtx(const std::vector &arr); + void SetCamTransMtxStr(const char* json_str); + + void SetOrthoZoom(float); + + Bool_t IsInitialized() const { return fInitialized; } + void SetInitialized(Bool_t val) { fInitialized = val; } + + void BuildRenderData() override{}; + + Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override; + + ClassDef(REveCamera, 0); +}; + +} // namespace Experimental +} // namespace ROOT + +#endif diff --git a/graf3d/eve7/inc/ROOT/REveManager.hxx b/graf3d/eve7/inc/ROOT/REveManager.hxx index ca0fa9b8a054a..591198c55ecb6 100644 --- a/graf3d/eve7/inc/ROOT/REveManager.hxx +++ b/graf3d/eve7/inc/ROOT/REveManager.hxx @@ -15,7 +15,6 @@ #include #include #include - #include #include "TSysEvtHandler.h" @@ -127,6 +126,7 @@ protected: REveViewerList *fViewers{nullptr}; REveSceneList *fScenes{nullptr}; + REveElement *fCameras{nullptr}; REveScene *fGlobalScene{nullptr}; REveScene *fEventScene{nullptr}; @@ -182,6 +182,7 @@ public: REveSceneList *GetScenes() const { return fScenes; } REveViewerList *GetViewers() const { return fViewers; } + REveElement *GetCameras() const { return fCameras; } REveScene *GetGlobalScene() const { return fGlobalScene; } REveScene *GetEventScene() const { return fEventScene; } diff --git a/graf3d/eve7/inc/ROOT/REveViewer.hxx b/graf3d/eve7/inc/ROOT/REveViewer.hxx index d26a3836dd359..58af4d8048548 100644 --- a/graf3d/eve7/inc/ROOT/REveViewer.hxx +++ b/graf3d/eve7/inc/ROOT/REveViewer.hxx @@ -13,6 +13,7 @@ #define ROOT7_REveViewer #include +#include namespace ROOT { namespace Experimental { @@ -27,23 +28,21 @@ class REveScene; class REveViewer : public REveElement { public: - enum ECameraType - { - // Perspective - kCameraPerspXOZ, // XOZ floor - kCameraPerspYOZ, // YOZ floor - kCameraPerspXOY, // XOY floor - // Orthographic - kCameraOrthoXOY, // Looking down Z axis, X horz, Y vert - kCameraOrthoXOZ, // Looking along Y axis, X horz, Z vert - kCameraOrthoZOY, // Looking along X axis, Z horz, Y vert - kCameraOrthoZOX, // Looking along Y axis, Z horz, X vert - // nOrthographic - kCameraOrthoXnOY, // Looking along Z axis, -X horz, Y vert - kCameraOrthoXnOZ, // Looking down Y axis, -X horz, Z vert - kCameraOrthoZnOY, // Looking down X axis, -Z horz, Y vert - kCameraOrthoZnOX // Looking down Y axis, -Z horz, X vert - }; + // set alias instead + using ECameraType = REveCamera::ECameraType; + + // backward compatibility + static constexpr ECameraType kCameraPerspXOZ = REveCamera::kCameraPerspXOZ; + static constexpr ECameraType kCameraPerspYOZ = REveCamera::kCameraPerspYOZ; + static constexpr ECameraType kCameraPerspXOY = REveCamera::kCameraPerspXOY; + static constexpr ECameraType kCameraOrthoXOY = REveCamera::kCameraOrthoXOY; + static constexpr ECameraType kCameraOrthoXOZ = REveCamera::kCameraOrthoXOZ; + static constexpr ECameraType kCameraOrthoZOY = REveCamera::kCameraOrthoZOY; + static constexpr ECameraType kCameraOrthoZOX = REveCamera::kCameraOrthoZOX; + static constexpr ECameraType kCameraOrthoXnOY = REveCamera::kCameraOrthoXnOY; + static constexpr ECameraType kCameraOrthoXnOZ = REveCamera::kCameraOrthoXnOZ; + static constexpr ECameraType kCameraOrthoZnOY = REveCamera::kCameraOrthoZnOY; + static constexpr ECameraType kCameraOrthoZnOX = REveCamera::kCameraOrthoZnOX; enum EAxesType { kAxesNone, @@ -51,36 +50,24 @@ public: kAxesEdge }; - // For the moment REveCamera is internal class - class REveCamera - { - ECameraType fType; - std::string fName; - REveVector fV2; - REveVector fV1; - - public: - REveCamera() { Setup(kCameraPerspXOZ, "PerspXOZ", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0));} - ~REveCamera() {} - - void Setup(ECameraType type, const std::string& name, REveVector v1, REveVector v2); - - ECameraType GetType() const { return fType; } - - int WriteCoreJson(nlohmann::json &j, Int_t /*rnr_offset*/); - }; - private: REveViewer(const REveViewer&) = delete; REveViewer& operator=(const REveViewer&) = delete; - REveCamera fCamera; + REveCamera* fCamera{0}; + EAxesType fAxesType{kAxesNone}; bool fBlackBackground{false}; bool fMandatory{true}; std::string fPostStreamFlag; + std::vector fCameraList; + + ROOT::Experimental::REveCamera* CreateCamera(ECameraType type); + + bool fSyncCamera{true}; + public: REveViewer(const std::string &n="REveViewer", const std::string &t=""); ~REveViewer() override; @@ -90,8 +77,14 @@ public: virtual void AddScene(REveScene* scene); // XXX Missing RemoveScene() ???? - void SetCameraType(ECameraType t); - ECameraType GetCameraType() const { return fCamera.GetType(); } + // Camera setters + void SetCamera(ROOT::Experimental::REveCamera *cam); + REveCamera* GetCamera() const { return fCamera;} + void SetCameraByElementId(ElementId_t cameraId); // set camera via ElementID + void SetCameraType(REveCamera::ECameraType type); + + void SyncCamera(bool s) {fSyncCamera = s;} + bool GetSyncCamera() const {return fSyncCamera;} void SetAxesType(int); void SetBlackBackground(bool); diff --git a/graf3d/eve7/src/REveCamera.cxx b/graf3d/eve7/src/REveCamera.cxx new file mode 100644 index 0000000000000..7aea0cfcd15fb --- /dev/null +++ b/graf3d/eve7/src/REveCamera.cxx @@ -0,0 +1,135 @@ +// @(#)root/eve7:$Id$ +// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007, 2018 + +/************************************************************************* + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#include +#include + +#include +#include + +using namespace ROOT::Experimental; + +//////////////////////////////////////////////////////////////////////////////// +/// Default constructor + +REveCamera::REveCamera() : REveElement("REveCamera") +{ + Setup(kCameraPerspXOZ, "PerspXOZ", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)); + fCamBase.UnitTrans(); + fCamTrans.UnitTrans(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Constructor with name + +REveCamera::REveCamera(const std::string &name) : REveElement(name) +{ + Setup(kCameraPerspXOZ, name, REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)); + fCamBase.UnitTrans(); + fCamTrans.UnitTrans(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Setup camera with type, name, direction and up vectors + +void REveCamera::Setup(ECameraType type, const std::string &name, const REveVector &hAxis, const REveVector &vAxis) +{ + fType = type; + fName = name; + + // Set up base camera matrix from direction and up vectors + fCamBase.UnitTrans(); + fCamTrans.UnitTrans(); + + fCamBase.SetBaseVec(1, hAxis.fX, hAxis.fY, hAxis.fZ); + fCamBase.SetBaseVec(3, vAxis.fX, vAxis.fY, vAxis.fZ); + + REveVector y = vAxis.Cross(hAxis); + fCamBase.SetBaseVec(2, y.fX, y.fY, y.fZ); + + StampObjProps(); +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set camera base matrix from array (called from client via MIR) + +void REveCamera::SetCamBaseMtx(const std::vector &arr) +{ + if (arr.size() == 16) { + fCamBase.SetFromArray(arr.data()); + StampObjProps(); + } +} + +void REveCamera::SetCamBaseMtx(const std::string &json_str) +{ + auto j = nlohmann::json::parse(json_str); + std::vector arr = j.get>(); + SetCamBaseMtx(arr); +} + +void REveCamera::SetCamTransMtx(const std::vector &arr) +{ + if (arr.size() == 16) { + fCamTrans.SetFromArray(arr.data()); + fInitialized = kTRUE; + } +} + +// Set translation matrix with an array of 17 floats +// The first 16 floats are 4x4 matrix element +// The 17th value is setting the zoom value in orthographic type +void REveCamera::SetCamTransMtxStr(const char *ins) +{ + std::stringstream ss(ins); + std::vector arr; + std::string item; + while (std::getline(ss, item, ',')) { + arr.push_back(std::stod(item)); + } + + fOrthoZoom = arr.back(); + arr.pop_back(); + fCamTrans.SetFromArray(arr.data()); + + fInitialized = true; + + StampObjProps(); + SetCamTransMtx(arr); +} + +void REveCamera::SetOrthoZoom(float zoom) +{ + fOrthoZoom = zoom; +} + +//////////////////////////////////////////////////////////////////////////////// +/// Write core JSON for camera + +Int_t REveCamera::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) +{ + Int_t ret = REveElement::WriteCoreJson(j, rnr_offset); + + j["fType"] = fType; + j["fName"] = fName; + j["fInitialized"] = fInitialized; // Stream to client + + // Stream both matrices + // Client will read these as fMatrix arrays (16 elements each) + const Double_t *camBaseArr = fCamBase.Array(); + j["camBase"] = std::vector(camBaseArr, camBaseArr + 16); + + const Double_t *camTransArr = fCamTrans.Array(); + j["camTrans"] = std::vector(camTransArr, camTransArr + 16); + j["fZoom"] = fOrthoZoom; + + return ret; +} diff --git a/graf3d/eve7/src/REveManager.cxx b/graf3d/eve7/src/REveManager.cxx index e57faf0904099..d48302b51c1a0 100644 --- a/graf3d/eve7/src/REveManager.cxx +++ b/graf3d/eve7/src/REveManager.cxx @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -142,6 +143,13 @@ REveManager::REveManager() fScenes->IncDenyDestroy(); fWorld->AddElement(fScenes); + // -------------------------------- + // Create camera list + // -------------------------------- + fCameras = new REveElement("Cameras", "Camera list"); + fCameras->IncDenyDestroy(); + fWorld->AddElement(fCameras); + fGlobalScene = new REveScene("Geometry scene"); fGlobalScene->IncDenyDestroy(); fScenes->AddElement(fGlobalScene); diff --git a/graf3d/eve7/src/REveViewer.cxx b/graf3d/eve7/src/REveViewer.cxx index 334d9806bc046..e6f49c00272a0 100644 --- a/graf3d/eve7/src/REveViewer.cxx +++ b/graf3d/eve7/src/REveViewer.cxx @@ -10,7 +10,7 @@ *************************************************************************/ #include - +#include #include #include #include @@ -34,9 +34,10 @@ Eve representation of a GL view. In a gist, it's a camera + a list of scenes. /// Constructor. REveViewer::REveViewer(const std::string& n, const std::string& t) : - REveElement(n, t) + REveElement(n, t), + fCamera(nullptr) { - // SetChildClass(TClass::GetClass()); + SetCameraType(REveCamera::kCameraPerspXOZ); } //////////////////////////////////////////////////////////////////////////////// @@ -129,11 +130,13 @@ void REveViewer::SetBlackBackground(bool x) /// Virtual from REveElement. int REveViewer::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) { - fCamera.WriteCoreJson(j, rnr_offset); + // fCamera.WriteCoreJson(j, rnr_offset); j["Mandatory"] = fMandatory; j["AxesType"] = fAxesType; j["BlackBg"] = fBlackBackground; + j["fCameraId"] = fCamera ? fCamera->GetElementId() : 0; + j["fSyncCam"] = fSyncCamera; j["UT_PostStream"] = "UT_EveViewerUpdate"; @@ -168,77 +171,12 @@ void REveViewer::SetMandatory(bool x) } //////////////////////////////////////////////////////////////////////////////// -/// -// Set base vectors of camera base matrix -// -void REveViewer::SetCameraType(ECameraType cameraType) -{ - switch(cameraType) { - case kCameraPerspXOZ: - fCamera.Setup(kCameraPerspXOZ, "PerspXOZ", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)); // XOZ floor - break; - case kCameraPerspYOZ: - fCamera.Setup(kCameraPerspYOZ, "PerspYOZ", REveVector(0.0, -1.0, 0.0), REveVector(1.0, 0.0, 0.0));// YOZ floor - break; - case kCameraPerspXOY: - fCamera.Setup(kCameraPerspXOY, "PerspXOY", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 0.0, 1.0));// XOY floor - break; - case kCameraOrthoXOY: - fCamera.Setup(kCameraOrthoXOY, "OrthoXOY", REveVector(0.0, 0.0, 1.0), REveVector(0.0, 1.0, 0.0));// Looking down Z axis, X horz, Y vert - break; - case kCameraOrthoXOZ: - fCamera.Setup(kCameraOrthoXOZ, "OrthoXOZ", REveVector(0.0, -1.0, 0.0), REveVector(0.0, 0.0, 1.0));// Looking along Y axis, X horz, Z vert - break; - case kCameraOrthoZOY: - fCamera.Setup(kCameraOrthoZOY, "OrthoZOY", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0));// Looking along X axis, Z horz, Y vert - break; - case kCameraOrthoZOX: - fCamera.Setup(kCameraOrthoZOX, "OrthoZOX", REveVector(0.0,-1.0, 0.0), REveVector(1.0, 0.0, 0.0)); // Looking along Y axis, Z horz, X vert - break; - case kCameraOrthoXnOY: - fCamera.Setup(kCameraOrthoXnOY, "OrthoXnOY", REveVector(0.0, 0.0, -1.0), REveVector(0.0, 1.0, 0.0));// Looking along Z axis, -X horz, Y vert - break; - case kCameraOrthoXnOZ: - fCamera.Setup(kCameraOrthoXnOZ, "OrthoXnOZ", REveVector(0.0, 1.0, 0.0), REveVector(0.0, 0.0, 1.0));// Looking down Y axis, -X horz, Z vert - break; - case kCameraOrthoZnOY: - fCamera.Setup(kCameraOrthoZnOY, "OrthoZnOY", REveVector(1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)); // Looking down X axis, -Z horz, Y vert - break; - case kCameraOrthoZnOX: - fCamera.Setup(kCameraOrthoZnOX, "OrthoZnOX", REveVector(0.0, 1.0, 0.0), REveVector(1.0, 0.0, 0.0)); // Looking down Y axis, -Z horz, X vert - break; - default: - Error("REveViewer::SetCurrentCamera", "invalid camera type"); - return; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -// Set camera base matrix -// -void REveViewer::REveCamera::Setup( ECameraType type, const std::string& name, REveVector v1, REveVector v2) -{ - fType = type; - fName = name; - fV1 = v1; - fV2 = v2; -} +/// Set camera reference -//////////////////////////////////////////////////////////////////////////////// -/// -// Stream camera info -// -int REveViewer::REveCamera::WriteCoreJson(nlohmann::json &j, Int_t /*rnr_offset*/) +void REveViewer::SetCamera(::ROOT::Experimental::REveCamera *cam) { - nlohmann::json out; - out["type"] = fName; - out["V1"] = {fV1.fX, fV1.fY, fV1.fZ}; - out["V2"] = {fV2.fX, fV2.fY, fV2.fZ}; - - j["camera"] = out; - - return 0; + fCamera = cam; + StampObjProps(); } //////////////////////////////////////////////////////////////////////////////// @@ -435,3 +373,71 @@ void REveViewerList::SwitchColorSet() // } // EndChanges on EveWorld; } + +void REveViewer::SetCameraByElementId(ElementId_t cameraId) +{ + auto element = gEve->FindElementById(cameraId); + auto cam = dynamic_cast(element); + + if (cam) { + fCamera = cam; + StampObjProps(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +/// Set camera by type (backward compatibility with old API) + +void REveViewer::SetCameraType(REveCamera::ECameraType type) +{ + for (auto &cam : fCameraList) { + if (cam->GetType() == type) { + fCamera = cam; + } + } + + fCamera = CreateCamera(type); + fCameraList.push_back(fCamera); + StampObjProps(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Create Camera Based on Type Enum (Lines 161-190) +REveCamera *REveViewer::CreateCamera(ECameraType type) +{ + REveCamera *cam = nullptr; + + struct CameraDef { + REveCamera::ECameraType type; + const char *name; + REveVector v1; + REveVector v2; + }; + + static const CameraDef predefinedCameras[] = { + // Perspective cameras + {REveCamera::kCameraPerspXOZ, "PerspXOZ", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)}, + {REveCamera::kCameraPerspYOZ, "PerspYOZ", REveVector(0.0, -1.0, 0.0), REveVector(1.0, 0.0, 0.0)}, + {REveCamera::kCameraPerspXOY, "PerspXOY", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 0.0, 1.0)}, + // Orthographic cameras + {REveCamera::kCameraOrthoXOY, "OrthoXOY", REveVector(0.0, 0.0, 1.0), REveVector(0.0, 1.0, 0.0)}, + {REveCamera::kCameraOrthoXOZ, "OrthoXOZ", REveVector(0.0, -1.0, 0.0), REveVector(0.0, 0.0, 1.0)}, + {REveCamera::kCameraOrthoZOY, "OrthoZOY", REveVector(-1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)}, + {REveCamera::kCameraOrthoZOX, "OrthoZOX", REveVector(0.0, -1.0, 0.0), REveVector(1.0, 0.0, 0.0)}, + // Orthographic negative camera + {REveCamera::kCameraOrthoXnOY, "OrthoXnOY", REveVector(0.0, 0.0, -1.0), REveVector(0.0, 1.0, 0.0)}, + {REveCamera::kCameraOrthoXnOZ, "OrthoXnOZ", REveVector(0.0, 1.0, 0.0), REveVector(0.0, 0.0, 1.0)}, + {REveCamera::kCameraOrthoZnOY, "OrthoZnOY", REveVector(1.0, 0.0, 0.0), REveVector(0.0, 1.0, 0.0)}, + {REveCamera::kCameraOrthoZnOX, "OrthoZnOX", REveVector(0.0, 1.0, 0.0), REveVector(1.0, 0.0, 0.0)}}; + + // Create and add all predefined cameras + for (const auto &camDef : predefinedCameras) { + if (type == camDef.type) { + cam = new REveCamera(camDef.name); + gEve->GetCameras()->AddElement(cam); + cam->Setup(camDef.type, camDef.name, camDef.v1, camDef.v2); + } + } + + return cam; +} diff --git a/ui5/eve7/controller/GL.controller.js b/ui5/eve7/controller/GL.controller.js index a96086405f497..767821159c156 100644 --- a/ui5/eve7/controller/GL.controller.js +++ b/ui5/eve7/controller/GL.controller.js @@ -251,8 +251,16 @@ sap.ui.define([ }, isEveCameraPerspective: function() { + // get camera type from standalone REveCamera element let vo = this.mgr.GetElement(this.eveViewerId); - return vo.camera.type.startsWith("Persp"); + let camera = this.mgr.GetElement(vo.fCameraId); + if (camera && camera.fType !== undefined) { + // REveCamera::ECameraType: 0-2 are Perspective, 3-8 are Orthographic + return camera.fType < 3; + } + + console.warn("GL.controller.isEveCameraPerspective: no camera info found, defaulting to perspective"); + return true; }, switchSingle: function() diff --git a/ui5/eve7/controller/Ged.controller.js b/ui5/eve7/controller/Ged.controller.js index 51071b701468c..f07693a603d93 100644 --- a/ui5/eve7/controller/Ged.controller.js +++ b/ui5/eve7/controller/Ged.controller.js @@ -325,6 +325,9 @@ sap.ui.define([ { this.makeBoolSetter(Boolean(el.AxesType), "ShowAxes", "SetAxesType"); this.makeBoolSetter(el.BlackBg, "BlackBackground"); + + // camera type selector + this.makeCameraTypeSelector(el); }, buildREveDataCollectionSetter : function(el) @@ -748,8 +751,7 @@ sap.ui.define([ let selected = this.secSelectList.getSelectedItems(); for (let s = 0; s < selected.length; s++) this.secSelectList.setSelectedItem(selected[s], false); - - + for (let i =0; i < sec_idcs.length; ++i) { let sid = "item_"+sec_idcs[i]; this.secSelectList.setSelectedItemById(sid, true); @@ -758,9 +760,97 @@ sap.ui.define([ else this.secSelectList.removeSelections(); } - } - + }, + + makeCameraTypeSelector: function(viewer) { + let gedFrame = this.getView().byId("GED"); + let gcm = this; + + let cameraTypes = [ + { key: 0, text: "Perspective XOZ" }, + { key: 1, text: "Perspective YOZ" }, + { key: 2, text: "Perspective XOY" }, + { key: 3, text: "Orthographic XOY" }, + { key: 4, text: "Orthographic XOZ" }, + { key: 5, text: "Orthographic ZOY" }, + { key: 6, text: "Orthographic ZOX" }, + { key: 7, text: "Orthographic XnOY" }, + { key: 8, text: "Orthographic XnOZ" }, + { key: 9, text: "Orthographic ZnOY" }, + { key: 10, text: "Orthographic ZnOX" } + ]; + + let currentCamera = null; + let currentType = 0; + + if (viewer.fCameraId) { + currentCamera = this.mgr.GetElement(viewer.fCameraId); + if (currentCamera && currentCamera.fType !== undefined) { + currentType = currentCamera.fType; + } + } + + let cameraModel = new sap.ui.model.json.JSONModel({ + types: cameraTypes + }); + + let comboBox = new sap.m.ComboBox({ + width: "100%", + selectedKey: currentType.toString(), + items: { + path: "/types", + template: new sap.ui.core.ListItem({ + key: "{key}", + text: "{text}" + }) + }, + selectionChange: function(oEvent) { + let selectedItem = oEvent.getParameter("selectedItem"); + if (selectedItem) { + let selectedType = parseInt(selectedItem.getKey()); + gcm.onCameraTypeChange(viewer, selectedType); + } + } + }); + + comboBox.setModel(cameraModel); + + let labelWidget = new mText({ text: "Camera Type" }); + labelWidget.addStyleClass("sapUiTinyMargin"); + + let frame = new HorizontalLayout({ + content: [labelWidget, comboBox] + }); + + gedFrame.addContent(frame); + }, + + onCameraTypeChange: function(viewer, newCameraType) { + let mir = "SetCameraType(" + newCameraType + ")"; + this.mgr.SendMIR(mir, viewer.fElementId, viewer._typename); + }, + + getCameraList: function() { + let cameras = []; + + if (this.mgr && this.mgr.childs && this.mgr.childs.length > 0) { + let world = this.mgr.childs[0]; + + if (world.childs) { + for (let child of world.childs) { + if (child.fName === "Cameras" && child.childs) { + cameras = child.childs; + break; + } + } + } + } + + return cameras; + } + }); + GedController.canEditClass = function(typename) { return true; }; @@ -776,7 +866,6 @@ sap.ui.define([ return "SetRnrSelf"; } - return GedController; }); diff --git a/ui5/eve7/controller/Summary.controller.js b/ui5/eve7/controller/Summary.controller.js index 033401510fd93..49832fe9e01fb 100644 --- a/ui5/eve7/controller/Summary.controller.js +++ b/ui5/eve7/controller/Summary.controller.js @@ -300,6 +300,11 @@ sap.ui.define([ for (let n=0;n 2) { console.log("GlViewerRCore RQ_Mode:", this.RQ_Mode, "RQ_SSAA:", this.RQ_SSAA, @@ -119,6 +119,10 @@ sap.ui.define([ this.updateViewerAttributes(); this.controller.glViewerInitDone(); + + let eveView = this.controller.mgr.GetElement(this.controller.eveViewerId); + if (eveView.fSyncCam) + this.syncCamTransTimer(); } cleanup() { @@ -212,6 +216,37 @@ sap.ui.define([ this.lights.name = "Light container"; this.scene.add(this.lights); + this.createCameraAndLights(); + + this.rqt = new RC.RendeQuTor(this.renderer, this.scene, this.camera, this.overlay_scene); + if (this.RQ_Mode == "Direct") + { + this.rqt.initDirectToScreen(); + } + else if (this.RQ_Mode == "Simple") + { + this.rqt.initSimple(this.RQ_SSAA); + } + else + { + this.rqt.initFull(this.RQ_SSAA); + } + this.rqt.updateViewport(w, h); + + + // AMT secondary selection bug workaround for RenderCore PR #21 + this.rqt.pick_instance = function(state) + { + return this.pick_instance_low_level(this.pqueue, state); + } + this.rqt.pick_instance_overlay = function(state) + { + return this.pick_instance_low_level(this.ovlpqueue, state); + } + } + + createCameraAndLights() + { let a_light = new RC.AmbientLight(new RC.Color(0xffffff), 0.05); this.lights.add(a_light); @@ -225,6 +260,9 @@ sap.ui.define([ // this.overlay_scene.add(this.axis); // looks worse for now put to scene this.scene.add(this.axis); + let w = this.canvas.width; + let h = this.canvas.height; + if (this.controller.isEveCameraPerspective()) { this.camera = new RC.PerspectiveCamera(75, w / h, 20, 4000); @@ -238,7 +276,7 @@ sap.ui.define([ this.lights.add(light_3d_ctor(0xaaaa66, l_int, 0, 1, l_args)); // Y this.lights.add(light_3d_ctor(0x666666, l_int, 0, 1, l_args)); // gray, bottom - // Lights are positioned in resetRenderer. + // Lights are positioned in positionCameraAndLights. // Markers on light positions (screws up bounding box / camera reset calculations) // for (let i = 1; i <= 4; ++i) @@ -256,7 +294,7 @@ sap.ui.define([ this.lights.add(light_2d_ctor(0xffffff, l_int)); // white front // this.lights.add(light_2d_ctor(0xffffff, l_int)); // white back - // Lights are positioned in resetRenderer. + // Lights are positioned in positionCameraAndLights. } // AMT, disable auto update in camera in order prevent reading quaternions in update of @@ -281,32 +319,6 @@ sap.ui.define([ } this.rot_center = new RC.Vector3(0,0,0); - - this.rqt = new RC.RendeQuTor(this.renderer, this.scene, this.camera, this.overlay_scene); - if (this.RQ_Mode == "Direct") - { - this.rqt.initDirectToScreen(); - } - else if (this.RQ_Mode == "Simple") - { - this.rqt.initSimple(this.RQ_SSAA); - } - else - { - this.rqt.initFull(this.RQ_SSAA); - } - this.rqt.updateViewport(w, h); - - - // AMT secondary selection bug workaround for RenderCore PR #21 - this.rqt.pick_instance = function(state) - { - return this.pick_instance_low_level(this.pqueue, state); - } - this.rqt.pick_instance_overlay = function(state) - { - return this.pick_instance_low_level(this.ovlpqueue, state); - } } setupEventHandlers() @@ -373,7 +385,7 @@ sap.ui.define([ dome.addEventListener('dblclick', function() { //if (glc.controller.dblclick_action == "Reset") - glc.resetRenderer(); + glc.positionCameraAndLights(); }); dome.addEventListener("mouseup", function() { @@ -448,9 +460,15 @@ sap.ui.define([ } }); + // implement the camera control to client side (and look into how to locate the camera) this.controls = new RC.REveCameraControls(this.camera, this.canvas.canvasDOM); this.controls.addEventListener('change', this.render.bind(this)); + // sync camera trans to server after camera change have ended + this.controls.addEventListener('end', function() { + glc.controlsChanged = true; + }); + // camera center marker let col = new RC.Color(0.5, 0, 0); const msize = this.RQ_SSAA * 8; // marker size @@ -468,7 +486,48 @@ sap.ui.define([ this.centerMarker = s; // This will also call render(). - this.resetRenderer(); + this.positionCameraAndLights(); + } + + syncCamTransTimer() { + let glc = this; + if (glc?.controlsChanged === true) { + let equal = true; + let a = glc.controls.getCamTrans().elements; + let eveView = glc.controller.mgr.GetElement(this.controller.eveViewerId); + let eveCamera = glc.controller.mgr.GetElement(eveView.fCameraId); + let b = eveCamera.camTrans; + + // compare trans matrices + for (let i = 0; i < 16; i++) { + if (Math.abs(a[i] - b[i]) > 0.0000005) { + equal = false; + } + } + + // compare zoom if camera is orthographic + if (glc.camera.isOrthographicCamera) { + if (Math.abs(glc.camera.zoom - eveCamera.fZoom) > 0.0000005) { + eveCamera.fZoom = glc.camera.zoom; + equal = false; + } + } + + if (equal !== true) { + // save trans matrix from orbit control to eve camera object + for (let i = 0; i < 16; i++) { + b[i] = a[i]; + } + + // set trans matrix and zoom as array of 17 floats + let sz = glc.camera.isOrthographicCamera === true ? glc.camera.zoom : 1; + let fcall = "SetCamTransMtxStr(\""; + fcall += b.join(",") + "," + sz + "\")"; + glc.controller.mgr.SendMIR(fcall, eveView.fCameraId,"ROOT::Experimental::REveCamera"); + glc.controlsChanged = false; + } + } + setTimeout(this.syncCamTransTimer.bind(this), 5000); } recalcSceneBBox() @@ -476,14 +535,14 @@ sap.ui.define([ this.scene_bbox.setFromObject( this.scene ); if (this.scene_bbox.isEmpty()) { - console.error("GlViewerRenderCore.resetRenderer scene bbox empty", this.scene_bbox); + console.error("GlViewerRenderCore.positionCameraAndLights scene bbox empty", this.scene_bbox); const ext = 100; this.scene_bbox.expandByPoint(new RC.Vector3(-ext,-ext,-ext)); this.scene_bbox.expandByPoint(new RC.Vector3( ext, ext, ext)); } } - resetRenderer() + positionCameraAndLights() { this.recalcSceneBBox(); @@ -495,17 +554,34 @@ sap.ui.define([ let extR = extV.length(); if (this._logLevel >= 2) - console.log("GlViewerRenderCore.resetRenderer", sbbox, posV, negV, extV, extR); + console.log("GlViewerRenderCore.positionCameraAndLights", sbbox, posV, negV, extV, extR); let eveView = this.controller.mgr.GetElement(this.controller.eveViewerId); - let v1 = eveView.camera.V1; - let v2 = eveView.camera.V2; + // Try to use standalone REveCamera if available + let cameraId = eveView.fCameraId; + + let camera = this.controller.mgr.GetElement(cameraId); + if (this._logLevel >= 2) { + console.log("GlViewerRCore.positionCameraAndLights: Using standalone camera ID", cameraId); + if (camera) { + console.log(" Camera name:", camera.fName); + console.log(" Camera camBase:", camera.camBase); + } + } + + let v1 = [camera.camBase[0], camera.camBase[1], camera.camBase[2]]; // forward/direction + let v2 = [camera.camBase[8], camera.camBase[9], camera.camBase[10]]; // up + + if (this._logLevel >= 2) { + console.log("GlViewerRCore.positionCameraAndLights: Using standalone REveCamera"); + } if (this.camera.isPerspectiveCamera) { this.controls.setCamBaseMtx(new RC.Vector3(v1[0], v1[1], v1[2]), new RC.Vector3(v2[0], v2[1], v2[2])); this.controls.screenSpacePanning = true; + this.controls.enableRotate = true; let lc = this.lights.children; // lights are const now -- no need to set decay and distance @@ -514,8 +590,6 @@ sap.ui.define([ lc[3].position.set( extR, extR, extR); lc[4].position.set(-extR, extR, -extR); lc[5].position.set(0, -extR, 0); - - // console.log("resetRenderer 3D scene bbox ", sbbox, ", look_at ", this.rot_center); } else { @@ -536,42 +610,34 @@ sap.ui.define([ let lc = this.lights.children; lc[1].position.set( 0, 0, extR); - // lc[2].position.set( 0, 0, -extR); - - // console.log("resetRenderer 2D scene bbox ex ey", sbbox, ex, ey, ", camera_pos ", posC, ", look_at ", this.rot_center); } - this.centerMarker.visible = false; - this.controls.setFromBBox(sbbox); - this.controls.update(); - } - - setupCamera() - { - // To be used with JS debugger to edit the values as needed. + // Apply saved camTrans (if initialized) + if (camera.fInitialized) { + // Apply camTrans after bbox setup + this.controls.setCamTrans(camera.camTrans.slice()); + } - let pos = new RC.Vector3; - let lookat = new RC.Vector3; - let fov = 30; // in degrees + if (this.camera.isOrthographicCamera && camera.fZoom !== 1) { + this.camera.zoom = camera.fZoom; + this.controls.zoomChanged = true; + this.camera.updateProjectionMatrix(); + } - console.log("A good place to set the breakpoint and edit the values"); + this.controls.update(); - // Call the controller stuff, hope it's not all local, otherwise we need to edit it there. - // Sigh, should really have it (and RedeQuTor) in ROOT. + this.centerMarker.visible = false; } - updateViewerAttributes() - { + updateViewerAttributes() { let eveView = this.controller.mgr.GetElement(this.controller.eveViewerId); - if (eveView.BlackBg) - { + if (eveView.BlackBg) { this.fgCol = this.creator.ColorWhite; this.bgCol = this.creator.ColorBlack; } - else - { + else { this.bgCol = this.creator.ColorWhite; this.fgCol = this.creator.ColorBlack; } @@ -580,6 +646,39 @@ sap.ui.define([ if (eveView.AxesType > 0) this.makeAxis(); + + // compare cam base matrices + let a = this.controls.getCamBase().elements; + let eveCamera = this.controller.mgr.GetElement(eveView.fCameraId); + + // compare the base matrices + let b = eveCamera.camBase; + let equal = true; + for (let i = 0; i < 16; i++) { + if (Math.abs(a[i] - b[i]) > 0.0000005) { + equal = false; + } + } + + // compare exisiting controller type and viewer's REveCamera type + if (eveCamera.fType < 3) { + if (this.controls?.isOrthographicCamera) { + equal = false; + } + + } + else { + if (this.controls?.isPerspectiveCamera) { + equal = false; + } + } + + if (equal !== true) { + this.lights.clear(); + delete this.camera; + this.createCameraAndLights(); + this.positionCameraAndLights(); + } this.request_render(); } @@ -1057,7 +1156,7 @@ sap.ui.define([ menu.add("Set Camera Center", data, this.setCameraCenter.bind(data)); } - menu.add("Reset camera", this.resetRenderer); + menu.add("Reset camera", this.resetCamera); if (RC.REveDevelMode) { menu.add("separator"); @@ -1068,6 +1167,15 @@ sap.ui.define([ menu.show(event); } + // callback from popup "Re" menu + resetCamera() + { + let eveView = this.controller.mgr.GetElement(this.controller.eveViewerId); + let eve_camera = this.controller.mgr.GetElement(eveView.fCameraId); + eve_camera.fInitialized = false; + this.positionCameraAndLights(); + } + setCameraCenter(data) { let pthis = data.v;