Have display / stop functionality working generally, but textures not appearing properly.

This commit is contained in:
mmcwilliams 2024-05-05 11:28:20 -04:00
parent 62c7181906
commit 566f1ecefd
5 changed files with 147 additions and 71 deletions

BIN
img/4kSnake.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -46,6 +46,7 @@ class State {
void setMode(json& msgData); void setMode(json& msgData);
void setExposure(json& msgData); void setExposure(json& msgData);
void setPosition(json& msgData); void setPosition(json& msgData);
void setActive () { active = true; }
public : public :
State(); State();
@ -57,7 +58,7 @@ class State {
vector<uint64_t> getExposure() { return exposure; } vector<uint64_t> getExposure() { return exposure; }
vector<uint64_t> getPosition() { return { x, y, w, h }; } vector<uint64_t> getPosition() { return { x, y, w, h }; }
bool isError () { return ERROR; } bool isError () { return ERROR; }
void setActive () { active = true; } void setInactive () { active = false; }
bool isActive () { return active; } bool isActive () { return active; }
}; };

View File

@ -21,9 +21,11 @@
#include <condition_variable> #include <condition_variable>
using namespace std; using namespace std;
using namespace std::chrono;
uint16_t PORT = 8081; uint16_t PORT = 8081;
const uint16_t BUFFER_SIZE = 2048; const uint16_t BUFFER_SIZE = 2048;
int clientSocket = 0;
GLuint imageTexture = 0; GLuint imageTexture = 0;
GLuint blankTexture = 0; GLuint blankTexture = 0;
@ -34,15 +36,68 @@ GLint screenHeight = 0;
Image img; Image img;
State state; State state;
void actionDisplay () { uint64_t exposureTime = 0;
steady_clock::time_point startTime;
bool displaying = false;
bool completed = true;
bool timing = false;
/**
* State Message Variables
**/
bool receivedMessage = false;
string incomingMessage;
string outgoingMessage;
mutex receivedMutex;
condition_variable receivedCondVar;
void actionDisplay () {
vector<uint64_t> exposure = state.getExposure();
if (exposure.size() == 0) {
displaying = true;
completed = true;
timing = false;
} else if (exposure.size() == 1) {
exposureTime = exposure[0];
displaying = true;
completed = false;
timing = true;
startTime = steady_clock::now();
while (!completed) {
//
}
} // multi channel case
}
void actionStop () {
displaying = false;
completed = true;
}
void postAction () {
if (state.isError()) {
outgoingMessage = state.createMessage(false);
} else {
outgoingMessage = state.createMessage(true);
}
const char* msg = outgoingMessage.c_str();
int bytesSent = send(clientSocket, msg, strlen(msg), 0);
if (bytesSent < 0) {
cerr << "Error sending ACK to client" << endl;
} else {
cout << "Sent = " << outgoingMessage << endl;
}
} }
void actionLoad () { void actionLoad () {
auto localStartTime = steady_clock::now();
string imagePath = state.getImage(); string imagePath = state.getImage();
vector<uint64_t> position = state.getPosition(); vector<uint64_t> position = state.getPosition();
Mat image = img.loadImage(imagePath, position[0], position[1], position[2], position[3]); Mat image = img.loadImage(imagePath, position[0], position[1], position[2], position[3]);
glGenTextures(2, &imageTexture); glGenTextures(1, &imageTexture);
glBindTexture(GL_TEXTURE_2D, imageTexture); glBindTexture(GL_TEXTURE_2D, imageTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@ -51,19 +106,18 @@ void actionLoad () {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, // Type of texture glTexSubImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level 0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_RGB, // Internal colour format to convert to GL_RGB, // Internal colour format to convert to
image.cols, // Image width i.e. 640 for Kinect in standard mode image.cols, // Image width
image.rows, // Image height i.e. 480 for Kinect in standard mode image.rows, // Image height
0, // Border width in pixels (can either be 1 or 0) 0, // Border width in pixels (can either be 1 or 0)
GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type GL_UNSIGNED_BYTE, // Image data type
image.ptr()); // The actual image data itself image.ptr()); // The actual image data itself
} auto localCurrentTime = steady_clock::now();
auto localElapsedTime = duration_cast<milliseconds>(localCurrentTime - localStartTime).count();
void actionStop () { cout << "actionLoad() [" << localElapsedTime << " ms]" << endl;
} }
void loadBlank () { void loadBlank () {
@ -79,22 +133,52 @@ void loadBlank () {
glTexImage2D(GL_TEXTURE_2D, // Type of texture glTexImage2D(GL_TEXTURE_2D, // Type of texture
0, // Pyramid level (for mip-mapping) - 0 is the top level 0, // Pyramid level (for mip-mapping) - 0 is the top level
GL_RGB, // Internal colour format to convert to GL_RGB, // Internal colour format to convert to
blank.cols, // Image width i.e. 640 for Kinect in standard mode blank.cols, // Image width
blank.rows, // Image height i.e. 480 for Kinect in standard mode blank.rows, // Image height
0, // Border width in pixels (can either be 1 or 0) 0, // Border width in pixels (can either be 1 or 0)
GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.) GL_RGB, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
GL_UNSIGNED_BYTE, // Image data type GL_UNSIGNED_BYTE, // Image data type
blank.ptr()); // The actual image data itself blank.ptr()); // The actual image data itself
} }
void initImageTexture() {
glGenTextures(1, &imageTexture);
}
void display () { void display () {
if (state.isActive()) {
if (state.getAction() == LOAD) {
actionLoad();
} else if (state.getAction() == DISPLAY) {
actionDisplay();
} else if (state.getAction() == STOP) {
actionStop();
}
state.setInactive();
postAction();
}
if (displaying && timing) {
auto currentTime = steady_clock::now();
auto elapsedTime = duration_cast<milliseconds>(currentTime - startTime).count();
if (elapsedTime > exposureTime) {
cout << "Exposure = " << elapsedTime << " ms" << endl;
displaying = false;
completed = true;
}
}
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glViewport(0, 0, screenWidth, screenHeight); glViewport(0, 0, screenWidth, screenHeight);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
if (displaying) {
glBindTexture(GL_TEXTURE_2D, imageTexture);
} else {
glBindTexture(GL_TEXTURE_2D, blankTexture); glBindTexture(GL_TEXTURE_2D, blankTexture);
}
glBegin(GL_QUADS); // front face glBegin(GL_QUADS); // front face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); //bottom right glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); //bottom right
@ -114,47 +198,14 @@ void timer(int value) {
glutTimerFunc(1, timer, 0); glutTimerFunc(1, timer, 0);
} }
/**
* State Message Variables
**/
bool receivedMessage = false;
bool sendMessage = false;
string incomingMessage;
string outgoingMessage;
mutex receivedMutex;
condition_variable receivedCondVar;
mutex sendMutex;
condition_variable sendCondVar;
/** /**
* *
**/ **/
void processMessage () { void processMessage () {
if (receivedMessage) { if (receivedMessage) {
cout << "RECEIVED" << endl;
state.receiveMessage(incomingMessage); state.receiveMessage(incomingMessage);
receivedMessage = false; receivedMessage = false;
while (state.isActive()) {
if (state.getAction() == LOAD) {
actionLoad();
} else if (state.getAction() == DISPLAY) {
actionDisplay();
} else if (state.getAction() == STOP) {
actionStop();
}
}
if (state.isError()) {
outgoingMessage = state.createMessage(false);
} else {
outgoingMessage = state.createMessage(true);
}
sendMessage = true;
} }
} }
@ -174,32 +225,12 @@ void handleTCPConnection(int clientSocket) {
{ {
lock_guard<mutex> lock(receivedMutex); lock_guard<mutex> lock(receivedMutex);
receivedMessage = true; receivedMessage = true;
sendMessage = false;
incomingMessage = localIncomingMessage; incomingMessage = localIncomingMessage;
receivedCondVar.notify_all(); receivedCondVar.notify_all();
} }
processMessage(); processMessage();
bool localSendMessage;
string localOutgoingMessage;
{
unique_lock<mutex> lock(sendMutex);
sendCondVar.wait(lock, [&] { return sendMessage; });
localSendMessage = sendMessage;
localOutgoingMessage = outgoingMessage;
}
if (localSendMessage) {
const char* msg = localOutgoingMessage.c_str();
int bytesSent = send(clientSocket, msg, strlen(msg), 0);
if (bytesSent < 0) {
cerr << "Error sending ACK to client" << endl;
break;
}
}
memset(buffer, 0, BUFFER_SIZE); memset(buffer, 0, BUFFER_SIZE);
} }
} }
@ -209,7 +240,7 @@ void runTCPServer (int serverSocket) {
struct sockaddr_in clientAddr; struct sockaddr_in clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr); socklen_t clientAddrLen = sizeof(clientAddr);
int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen); clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);
if (clientSocket < 0) { if (clientSocket < 0) {
cerr << "Error accepting client connection" << endl; cerr << "Error accepting client connection" << endl;
continue; continue;
@ -260,6 +291,7 @@ int main (int argc, char** argv) {
glutDisplayFunc(display); glutDisplayFunc(display);
glutTimerFunc(0, timer, 0); glutTimerFunc(0, timer, 0);
loadBlank(); loadBlank();
initImageTexture();
int serverSocket = socket(AF_INET, SOCK_STREAM, 0); int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket < 0) { if (serverSocket < 0) {

View File

@ -16,7 +16,20 @@ bool State::imageExists (string& image) {
void State::setAction (json& msgData) { void State::setAction (json& msgData) {
action = static_cast<Action>(msgData["action"]); action = static_cast<Action>(msgData["action"]);
cout << "Action = " << action << endl; switch (action) {
case NONE:
cout << "Action = NONE" << endl;
break;
case LOAD:
cout << "Action = LOAD" << endl;
break;
case DISPLAY:
cout << "Action = DISPLAY" << endl;
break;
case STOP:
cout << "Action = STOP" << endl;
break;
}
} }
void State::setImage (json& msgData) { void State::setImage (json& msgData) {
@ -45,9 +58,11 @@ void State::setPosition (json& msgData) {
void State::setExposure (json& msgData) { void State::setExposure (json& msgData) {
if (msgData["exposure"].size() == 1) { if (msgData["exposure"].size() == 1) {
exposure = { msgData["exposure"][0] }; exposure = { msgData["exposure"][0] };
} else if (msgData["exposure"].size() == 3) { cout << "Exposure = " << msgData["exposure"][0] << " ms" << endl;
} /*else if (msgData["exposure"].size() == 3) {
exposure = { msgData["exposure"][0], msgData["exposure"][1], msgData["exposure"][2] }; exposure = { msgData["exposure"][0], msgData["exposure"][1], msgData["exposure"][2] };
} else { cout << "Exposure[0] = " << msgData["exposure"][0] << " ms, [1] = " << msgData["exposure"][1] << " ms, [2] = " << msgData["exposure"][2] << " ms" << endl;
}*/ else {
error(); error();
cerr << "Exposure array is incorrect length, " << msgData["exposure"].size() << endl; cerr << "Exposure array is incorrect length, " << msgData["exposure"].size() << endl;
return; return;
@ -81,6 +96,8 @@ void State::receiveMessage (string msgString) {
if (action == DISPLAY && msgData.contains("exposure")) { if (action == DISPLAY && msgData.contains("exposure")) {
setExposure(msgData); setExposure(msgData);
} }
setActive();
} }
string State::createMessage (bool success) { string State::createMessage (bool success) {

View File

@ -1,4 +1,5 @@
const net = require('net'); const net = require('net');
const { resolve } = require('path');
const serverAddress = 'localhost'; const serverAddress = 'localhost';
const serverPort = 8081; const serverPort = 8081;
@ -16,13 +17,38 @@ async function delay (ms) {
client.connect(serverPort, serverAddress, async () => { client.connect(serverPort, serverAddress, async () => {
const data = { const data = {
action : 1, action : 1,
image: 'filename.tif', image: resolve('./img/4kSnake.png'),
position : {
x: 100,
y : 100,
w : 320,
h : 320
}
}; };
console.log('SENDING'); console.log('SENDING');
console.log(data); console.log(data);
client.write(JSON.stringify(data)); client.write(JSON.stringify(data));
await delay(2000); await delay(2000);
data.action = 2; data.action = 2;
delete data.position
console.log('SENDING');
console.log(data);
client.write(JSON.stringify(data));
await delay(2000);
data.action = 3;
console.log('SENDING');
console.log(data);
client.write(JSON.stringify(data));
await delay(2000);
data.action = 1;
data.position = { x: 50, y : 50, w : 320, h : 320 };
console.log('SENDING');
console.log(data);
client.write(JSON.stringify(data));
await delay(1000);
data.action = 2;
delete data.position;
data.exposure = [ 4000 ];
console.log('SENDING'); console.log('SENDING');
console.log(data); console.log(data);
client.write(JSON.stringify(data)); client.write(JSON.stringify(data));