for the past few weeks, I am trying to simulate water dropplets with help of kinnect
Kinnect would get 3d surface of an object and then I would vizualize water dropplets on that surface (so water would start at random point and flow down the object (from highest point (z) to lowest point (z)), like water on a real object (like hill) would do
so Kinnect would point to something like curved table and water dropplets would start at random point (the highest point for instance) and would flow down to the lowst point
I use kinnect for xbox 360 and I can already capture data into a point cloud (ofMesh) fine like this
#include "ofApp.h"
#include "PMSettingsManagerGeneral.h"
#include "PMSharedSettings.h"
#include "Defaults.h"
//--------------------------------------------------------------
ofMesh mesh;
void ofApp::setup(){
ofSetFrameRate(60);
ofSetVerticalSync(true);
ofBackground(ofColor::black);
ofHideCursor();
//createGui to guiApp
PMSharedSettings shared = PMSharedSettings::getInstance();
auto globalGui = shared.guiApp->globalParametersGui;
//offsetXf = 0;
//offsetYf = 0;
//globalGui->bindVariables(&offsetX_lowf, &offsetXf, &offsetY_lowf, &offsetYf);
anglef = 0;
red = 255; green = 255; blue = 255, buttonPressed = false;
globalGui->bindVariables(&anglef, &red, &green, &blue, &buttonPressed);
//setup Gui
globalGui->init(1, 0); //This setting has no effect currently, it will allow u to specify to what layer will the gui be drawn
globalGui->setBackgroundColor(ofColor::slateGrey);
globalGui->setVisible(true);
shared.guiApp->layoutGuis();
//Kinect
ofSetLogLevel(OF_LOG_VERBOSE);
// enable depth->video image calibration
kinect.setRegistration(true);
//kinect.init();
// other options we could use
//kinect.init(true); // shows infrared instead of RGB video image
kinect.init(false, false); // disable video image (faster fps)
//kinect.open(); // opens first available kinect
// other options we could use
//kinect.open(1); // open a kinect by id, starting with 0 (sorted by serial # lexicographically))
//kinect.open("A00362A08602047A"); // open a kinect using it's unique serial #
// send some setup info out to the console for debugging
// print the intrinsic IR sensor values
if (kinect.isConnected()) {
ofLogNotice() << "sensor-emitter dist: " << kinect.getSensorEmitterDistance() << "cm";
ofLogNotice() << "sensor-camera dist: " << kinect.getSensorCameraDistance() << "cm";
ofLogNotice() << "zero plane pixel size: " << kinect.getZeroPlanePixelSize() << "mm";
ofLogNotice() << "zero plane dist: " << kinect.getZeroPlaneDistance() << "mm";
}
ofSetFrameRate(60);
// zero the tilt on startup
anglef = 0;
kinect.setCameraTiltAngle(anglef);
}
//--------------------------------------------------------------
void ofApp::update(){
//Kinect
ofBackground(0,0,0);
// get fresh data from the kinect
kinect.update();
//Aquire data from Kinnect
int w = 640;
int h = 480;
mesh.setMode(OF_PRIMITIVE_POINTS);
int step = 2;
//Clear the mesh before each loop so old data doesn't bother us
mesh.clear();
// step through each row of the data from the kinect using a a loop inside a loop
// this loops through each line (the inner x loop) and after each line steps down to the next line (the outer y loop)
for (int y = 0; y < h; y += step) {
for (int x = 0; x < w; x += step) {
if (kinect.getDistanceAt(x, y) > 0) {
// we get the kinect data for each pixel and change each point in our mesh to correspond to the x,y,z and colour data
//mesh.addColor(kinect.getColorAt(x, y));
mesh.addVertex(kinect.getWorldCoordinateAt(x, y));
}
}
}
kinect.setCameraTiltAngle(anglef);
}
//--------------------------------------------------------------
void ofApp::draw(){
//ofDrawRectangle(offsetXf, offsetYf, 100, 100);
// make a new 3d mesh, called 'mesh'
//Draw that data
prepareDrawingSurface(mesh);
}
void ofApp::exit()
{
//Kinnect
// when we quit our app we remember to close the connection to the kinect sensor
kinect.setCameraTiltAngle(0); // zero the tilt on exit
kinect.close();
}
// this is our custom function that we call to make a 3D point cloud from the raw kinect data
void ofApp::prepareDrawingSurface(ofMesh& mesh) {
drawSimulation(mesh);
}
void ofApp::drawSimulation(ofMesh& mesh)
{
// Loop through all vertices in the mesh
for (int i = 0; i < mesh.getNumVertices(); i++) {
// Access the x, y, z coordinates of each vertex
float x = mesh.getVertex(i).x;
float y = mesh.getVertex(i).y;
float z = mesh.getVertex(i).z;
//cout << "Vertex " << i << ": x = " << x << ", y = " << y << ", z = " << z << endl;
ofColor color; color.set(red, green, blue);
// Size of the circle
float circleSize = 1; // Adjust the size as needed
// Calculate the position along the vertical axis based on the Z-coordinate
float yPos = ofMap(z, 0, 4000, ofGetHeight(), 0); //Map values to screen resolution
// Set the color and draw the circle at the calculated position
ofSetColor(color);
ofDrawCircle(x, yPos, circleSize);
}
}
//--------------------------------------------------------------
void ofApp::keyPressed(int key) {
// this is a case statement -
// rather than dozens of if - then statements we can say - get the keypress from the keyboard and do one from this list depending on the key value.
switch (key) {
case 'w':
kinect.enableDepthNearValueWhite(!kinect.isDepthNearValueWhite());
break;
case 'o':
kinect.setCameraTiltAngle(anglef); // go back to prev tilt
kinect.open();
break;
case 'c':
kinect.setCameraTiltAngle(0); // zero the tilt
kinect.close();
break;
case '1':
kinect.setLed(ofxKinect::LED_GREEN);
break;
case '2':
kinect.setLed(ofxKinect::LED_YELLOW);
break;
case '3':
kinect.setLed(ofxKinect::LED_RED);
break;
case '4':
kinect.setLed(ofxKinect::LED_BLINK_GREEN);
break;
case '5':
kinect.setLed(ofxKinect::LED_BLINK_YELLOW_RED);
break;
case '0':
kinect.setLed(ofxKinect::LED_OFF);
break;
case OF_KEY_UP:
anglef++;
if (anglef > 30) anglef = 30;
kinect.setCameraTiltAngle(anglef);
break;
case OF_KEY_DOWN:
anglef--;
if (anglef < -30) anglef = -30;
kinect.setCameraTiltAngle(anglef);
break;
case 'r':
kinect.setCameraTiltAngle(0); // Reset the tilt to 0
case 'f':
ofToggleFullscreen();
break;
}
}
//--------------------------------------------------------------
void ofApp::keyReleased(int key){
}
//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){
}
//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
}
//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){
}
//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){
}
//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
}
//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
}
//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
}
now the equiring data is allright, the simulation is the problem (in function drawSimulation) curently what I was able to do looks like this: https://youtu.be/iP7ZRVU7lzM 4
but this doesn’t look anything like water flowing down, it just looks like static dots that don’t even seam to fill the whole screen (my screen is 1920x1080 but this can change, while kinnect is capturing data at 640x480)
So to make things easier lets just focus on one water dropplet (I can always make an array out of them and they can overlap)
class droplet
{
float[] position; -> position[0] = x, position[1] = y
float[] valocity;
}
now I believe you calculate position from gradient (don’t know how, I just know u should do that (2 arrays: gradient_x and gradient_y) and you calculate velocity from position and gradient somehow
what I don’t know is how do I calculate gradients (position of my droplet) from the point of cloud kinnect gives me
and how do I draw my dropplet (position and velocity) on the screen so my dropplet would know what to do
suppose dropplet gets generated on (x,y) (30,30) then the dropplet knows oh, thats high, and it would travel to a lower point which would be on idk like 180,180
just like a real water dropplet would on a real slope or a hill
Hopefully someone can help me a since I feal I am very close. I can capture kinnect data, its just that simulation is a bit wierd