diff --git a/bin/data/new_tree.bin b/bin/data/new_tree.bin index 74fceae..49844b7 100644 Binary files a/bin/data/new_tree.bin and b/bin/data/new_tree.bin differ diff --git a/bin/image-to-mesh b/bin/image-to-mesh index 1ac1f1f..23b22f7 100755 Binary files a/bin/image-to-mesh and b/bin/image-to-mesh differ diff --git a/src/Bullet.cpp b/src/Bullet.cpp index 25e793c..7bc3a00 100644 --- a/src/Bullet.cpp +++ b/src/Bullet.cpp @@ -1,6 +1,6 @@ #include "Bullet.h" -void Bullet::setup(vector& _nodes){ +void Bullet::setup(){ /* setup camera & world */ camera_start_pos = ofVec3f(0, -3.f, -40.f); camera_end_position = glm::vec3(ofRandom(-100, 100), ofRandom(-100, 100), ofRandom(0, 0)); @@ -31,6 +31,7 @@ void Bullet::setup(vector& _nodes){ } void Bullet::update(bool& is_controller_active, Node& chosen_node, vector nn) { + std::lock_guard lock(shapeMutex); nn_nodes = nn; @@ -173,7 +174,6 @@ void Bullet::update(bool& is_controller_active, Node& chosen_node, vector } void Bullet::draw(){ - std::lock_guard lock(shapeMutex); float shapes_drawn = 0; @@ -369,6 +369,13 @@ void Bullet::setNodes(vector& _nodes){ nodes = _nodes; } +void Bullet::updateTSNEPosition(vector& _nodes){ + for(size_t i = 0; i < _nodes.size(); i++){ + nodes[i].tsne_position = _nodes[i].tsne_position; + } +} + + /* check if a node is inside a given radius, deactivate & stall if not. if it drifts too far reset position*/ void Bullet::updateNodeActivation(Node& node) { glm::vec3 node_pos = node.collider->getPosition(); diff --git a/src/Bullet.h b/src/Bullet.h index 31fde14..baa749d 100644 --- a/src/Bullet.h +++ b/src/Bullet.h @@ -27,7 +27,7 @@ struct CameraPosition { class Bullet{ public: - void setup(vector& _nodes); + void setup(); void update(bool& is_camera_active, Node& chosen_node, vector nn); void draw(); void addMesh(ofMesh _mesh, ofMesh _simple_mesh, Node& _node); @@ -38,6 +38,7 @@ class Bullet{ bool checkNodeVisibility(const Node& n); glm::vec3 getCameraPosition(); void setNodes(vector& _nodes); + void updateTSNEPosition(vector& _nodes); void updateNodeActivation(Node& node); ofxBulletWorldRigid world; vector bounds; @@ -145,6 +146,7 @@ class Bullet{ private: std::vector workerThreads; std::mutex shapeMutex; + std::mutex nodesMutex; std::atomic shouldTerminate{false}; std::atomic repulsionNodeIndex{0}; @@ -165,8 +167,8 @@ class Bullet{ Node* current_target_node = nullptr; /* random walk vars */ - const float RANDOM_WALK_RADIUS = 700.0f; - const float RANDOM_WALK_SPEED = 25.0f; // Adjust for slower/faster movement + const float RANDOM_WALK_RADIUS = 450.0f; + const float RANDOM_WALK_SPEED = 40.0f; // Adjust for slower/faster movement const float TARGET_REACHED_DISTANCE = 5.0f; const float RANDOM_WALK_DELAY = 10.0f; // 5 seconds delay diff --git a/src/ofApp.cpp b/src/ofApp.cpp index 3a5dd6e..7b31d82 100644 --- a/src/ofApp.cpp +++ b/src/ofApp.cpp @@ -61,8 +61,7 @@ void ofApp::setup(){ ORTCHAR_T* modelPath_Yolo = "/home/cailean/Desktop/openframeworks/of_v0.12.0_linux64gcc6_release/apps/myApps/image-to-mesh/bin/data/models/yolov5s-face.onnx"; ORTCHAR_T* modelPath_Indoor_Dynamic = "/home/cailean/Desktop/openframeworks/of_v0.12.0_linux64gcc6_release/apps/myApps/image-to-mesh/bin/data/models/depth_anything_v2_vitl.onnx"; - /* bullet setup */ - bullet.setup(nodes); + bullet.setup(); /* pi mapper setup */ // mapper.registerFboSource(projection_src); @@ -118,6 +117,7 @@ void ofApp::setup(){ server->start(); last_updated_time = ofGetElapsedTimef(); + last_updated_time_esp = ofGetElapsedTimef(); } //-------------------------------------------------------------- @@ -137,14 +137,17 @@ void ofApp::update(){ } - if(current_time - last_updated_time >= 1){ + if(current_time - last_updated_time >= 0.1){ buildKDTree(); getNearestImages(); - depth_esp.update(); - depth_onnx_esp.SetPixels(model_esp_out_fbo); last_updated_time = current_time; } + if(current_time - last_updated_time_esp >= 4.0){ + depth_esp.update(); + depth_onnx_esp.SetPixels(model_esp_out_fbo); + last_updated_time_esp = current_time; + } if(ofGetFrameNum() < 1){ @@ -177,6 +180,16 @@ void ofApp::update(){ //mapper.update(); bullet.update(server->is_active, server->getChosenNode(), nn_nodes); + + if(tsne_update_complete) { + tsne_update_complete = false; // Reset flag + onTSNEUpdateComplete(); // Call your main thread function + } + + if(ofGetElapsedTimef() > tsne_start_time + TNSE_DURATION){ + tsne_iter_idx = (tsne_iter_idx + 1) % 9; + updateTSNEPositions(nodes); + } } //-------------------------------------------------------------- @@ -386,8 +399,6 @@ void ofApp::drawPortrait(){ } } - - void ofApp::drawPortraitZ(){ ofBackgroundGradient(ofColor::white, ofColor::orange, OF_GRADIENT_LINEAR); @@ -586,13 +597,50 @@ void ofApp::createNodes(std::string json_path){ tsne_points = tsne.run(tsne_input, dims, perplexity, theta, normalise, runManually); + // Option 1: Using nested loops + for(size_t i = 0; i < 9; i++) { + for(size_t t = 0; t <= 100; t++) { + tsne_points = tsne.iterate(); + } + point_iterations.push_back(tsne_points); + } + for(size_t i = 0; i < tsne_points.size(); i++){ - const auto& vec = tsne_points[i]; + const auto& vec = point_iterations[0][i]; auto& n = nodes[i]; n.tsne_position = (glm::vec3(((vec[0] * 2) - 1) * tsne_scale, ((vec[1] * 2) - 1) * tsne_scale, -5.0f)); } } +void ofApp::updateTSNEPositions(vector& _nodes){ + if(tsne_updating) { + ofLog() << "TSNE update already in progress"; + return; + } + tsne_updating = true; + tsne_update_complete = false; // Reset flag + tsne_thread = std::thread(&ofApp::updateTSNEPositionsThreaded, this, std::ref(_nodes)); + tsne_thread.detach(); +} + +void ofApp::updateTSNEPositionsThreaded(vector& _nodes){ + ofLog() << "Starting TSNE update in thread"; + { + std::lock_guard lock(nodes_mutex); + for(size_t i = 0; i < point_iterations[tsne_iter_idx].size(); i++) { + const auto& vec = point_iterations[tsne_iter_idx][i]; + nodes[i].tsne_position = glm::vec3( + ((vec[0] * 2) - 1) * tsne_scale, + ((vec[1] * 2) - 1) * tsne_scale, + -5.0f + ); + } + } + tsne_updating = false; + tsne_update_complete = true; // Set completion flag + ofLog() << "TSNE update complete"; +} + std::vector> ofApp::createDoubleVectorFromNodes(const std::vector& nodes) { std::vector> result; result.reserve(nodes.size()); @@ -701,10 +749,22 @@ void ofApp::keyPressed(int key) { } std::cout << portrait_camera.getPosition() << " : " < images; ofFbo map_fbo; @@ -103,6 +106,7 @@ class ofApp : public ofBaseApp{ vector esp_images; ofPixels esp_comp_pixels; float last_updated_time; + float last_updated_time_esp; /* nodes */ ofJson json; @@ -113,8 +117,9 @@ class ofApp : public ofBaseApp{ float perplexity = 20; float theta = 0.2; bool normalise = true; - bool runManually = false; + bool runManually = true; float tsne_scale = 500; + vector>> point_iterations; /* kd tree */ std::unique_ptr kd_tree; @@ -148,4 +153,23 @@ class ofApp : public ofBaseApp{ /* n-neighbour */ vector nn_nodes; + + Bullet bullet; + + /* simulation update timer */ + const float TNSE_DURATION = 360.0f; + float tsne_start_time; + int tsne_iter_idx = 0; + + + + private: + + std::thread tsne_thread; + std::atomic tsne_updating{false}; + std::mutex nodes_mutex; + bool tsne_update_complete = false; + + void updateTSNEPositions(vector& _nodes); + void updateTSNEPositionsThreaded(vector& _nodes); };