├── .gitignore ├── .gitmodules ├── bin ├── glew32.dll ├── rdb.exe └── test.exe ├── build.bat ├── premake5.exe ├── premake5.lua ├── rdb.hpp ├── readme.md ├── test.cpp └── viewer.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /build/* 2 | /thirdparty/glfw-3.3.bin.WIN64/ 3 | /thirdparty/glew-2.1.0/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/imgui"] 2 | path = thirdparty/imgui 3 | url = https://github.com/ocornut/imgui.git 4 | [submodule "thirdparty/glm"] 5 | path = thirdparty/glm 6 | url = https://github.com/g-truc/glm.git 7 | -------------------------------------------------------------------------------- /bin/glew32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykozw/rdb/1c27de7316fdb0348ada3f3bb26eb3cefd09645f/bin/glew32.dll -------------------------------------------------------------------------------- /bin/rdb.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykozw/rdb/1c27de7316fdb0348ada3f3bb26eb3cefd09645f/bin/rdb.exe -------------------------------------------------------------------------------- /bin/test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykozw/rdb/1c27de7316fdb0348ada3f3bb26eb3cefd09645f/bin/test.exe -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | premake5 vs2019 2 | pause 3 | -------------------------------------------------------------------------------- /premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykozw/rdb/1c27de7316fdb0348ada3f3bb26eb3cefd09645f/premake5.exe -------------------------------------------------------------------------------- /premake5.lua: -------------------------------------------------------------------------------- 1 | require("premake", ">=5.0.0-alpha14") 2 | 3 | solution "rdb" 4 | location "build" 5 | configurations { "Debug", "Release" } 6 | platforms {"x64"} 7 | 8 | project "rdb" 9 | kind "ConsoleApp" 10 | language "C++" 11 | characterset "MBCS" 12 | files { 13 | "viewer.cpp", 14 | "thirdparty/imgui/examples/imgui_impl_glfw.cpp", 15 | "thirdparty/imgui/examples/imgui_impl_opengl2.cpp", 16 | "thirdparty/imgui/imgui.cpp", 17 | "thirdparty/imgui/imgui_draw.cpp", 18 | "thirdparty/imgui/imgui_widgets.cpp", 19 | "thirdparty/imgui/imgui_demo.cpp" 20 | } 21 | sysincludedirs{ 22 | "thirdparty/glfw-3.3.bin.WIN64/include", 23 | "thirdparty/imgui/", 24 | "thirdparty/imgui/examples", 25 | "thirdparty/glm/", 26 | "thirdparty/glew-2.1.0/include", 27 | } 28 | libdirs { 29 | "thirdparty/glfw-3.3.bin.WIN64/lib-vc2019", 30 | "thirdparty/glew-2.1.0/lib/Release/x64", 31 | } 32 | links { 33 | "glew32.lib", 34 | "glu32.lib", 35 | "glfw3.lib", 36 | } 37 | filter "configurations:Release" 38 | optimize "Speed" 39 | 40 | project "test" 41 | dependson "rdb" 42 | kind "ConsoleApp" 43 | language "C++" 44 | characterset "MBCS" 45 | files { 46 | "test.cpp", 47 | } 48 | libdirs { "./build/bin/x64/Debug" } 49 | 50 | filter "configurations:Release" 51 | optimize "Speed" 52 | -------------------------------------------------------------------------------- /rdb.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _RDB_H_ 2 | #define _RDB_H_ 3 | 4 | #include 5 | // 6 | void rdbPoint( 7 | float x, float y, float z, 8 | float r = 1.0f, float g = 1.0f, float b = 1.0f, 9 | int32_t group = 0); 10 | void rdbLine( 11 | float x0, float y0, float z0, 12 | float x1, float y1, float z1, 13 | float r0 = 1.0f, float g0 = 1.0f, float b0 = 1.0f, 14 | float r1 = 1.0f, float g1 = 1.0f, float b1 = 1.0f, 15 | int32_t group = 0); 16 | void rdbTriangle( 17 | float x0, float y0, float z0, 18 | float x1, float y1, float z1, 19 | float x2, float y2, float z2, 20 | float r = 1.0f, float g = 1.0f, float b = 1.0f, 21 | int32_t group = 0); 22 | 23 | #if defined(RDB_IMPLIMATATION) 24 | // 25 | #include 26 | #include 27 | #pragma comment(lib, "Ws2_32.lib") 28 | // 29 | #include 30 | #include 31 | #include 32 | #include 33 | // 34 | enum class RdbTaskType : int32_t 35 | { 36 | POINT, 37 | LINE, 38 | TRIANGLE, 39 | }; 40 | // 41 | struct RdbTask 42 | { 43 | RdbTaskType type; 44 | union 45 | { 46 | struct 47 | { 48 | float x; 49 | float y; 50 | float z; 51 | float r; 52 | float g; 53 | float b; 54 | int32_t group; 55 | }rdbPoint; 56 | struct 57 | { 58 | float x0; 59 | float y0; 60 | float z0; 61 | float x1; 62 | float y1; 63 | float z1; 64 | float r0; 65 | float g0; 66 | float b0; 67 | float r1; 68 | float g1; 69 | float b1; 70 | int32_t group; 71 | }rdbLine; 72 | struct 73 | { 74 | float x0; 75 | float y0; 76 | float z0; 77 | float x1; 78 | float y1; 79 | float z1; 80 | float x2; 81 | float y2; 82 | float z2; 83 | float r; 84 | float g; 85 | float b; 86 | int32_t group; 87 | }rdbTriangle; 88 | }; 89 | }; 90 | Concurrency::concurrent_queue rdbTasks; 91 | 92 | constexpr int32_t RDB_BUFFER_SIZE = 1024 * 4; 93 | 94 | struct RdbContext 95 | { 96 | public: 97 | std::once_flag initialized; 98 | size_t bytesToSend = 0; 99 | SOCKET fd; 100 | 101 | }rdbContext; 102 | 103 | std::thread rdbMainThread; 104 | std::atomic rdbFinishFlag = false; 105 | 106 | // 107 | void rdbInitCheck(); 108 | void rdbPrintf(const char* fmt, ...); 109 | void rdbMain(); 110 | 111 | // 112 | void rdbPrintf(const char* fmt, ...) 113 | { 114 | // 115 | rdbInitCheck(); 116 | // 117 | char buffer[RDB_BUFFER_SIZE]; 118 | va_list argp; 119 | va_start(argp, fmt); 120 | const int32_t bytesToSend = vsnprintf(buffer, RDB_BUFFER_SIZE, fmt, argp); 121 | va_end(argp); 122 | // 123 | size_t sended = ::send(rdbContext.fd, buffer, bytesToSend, 0); 124 | // TODO: -1が帰ったらもう何も送らない状態にする 125 | //printf("%s,[%d]", buffer, sended); 126 | } 127 | 128 | // 129 | void rdbMain() 130 | { 131 | while (!rdbFinishFlag) 132 | { 133 | if (rdbTasks.empty()) 134 | { 135 | using namespace std::chrono_literals; 136 | std::this_thread::sleep_for(10ms); 137 | } 138 | // 139 | RdbTask task; 140 | while (rdbTasks.try_pop(task)) 141 | { 142 | switch (task.type) 143 | { 144 | case RdbTaskType::POINT: 145 | { 146 | const auto& t = task.rdbPoint; 147 | rdbPrintf("P %f,%f,%f,%f,%f,%f,%d\n", 148 | t.x, t.y, t.z, t.r, t.g, t.b, t.group); 149 | } 150 | break; 151 | case RdbTaskType::LINE: 152 | { 153 | const auto& t = task.rdbLine; 154 | rdbPrintf("L %f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d\n", 155 | t.x0, t.y0, t.z0, 156 | t.x1, t.y1, t.z1, 157 | t.r0, t.g0, t.b0, 158 | t.r1, t.g1, t.b1, 159 | t.group); 160 | } 161 | break; 162 | case RdbTaskType::TRIANGLE: 163 | { 164 | const auto& t = task.rdbTriangle; 165 | rdbPrintf("T %f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d\n", 166 | t.x0, t.y0, t.z0, 167 | t.x1, t.y1, t.z1, 168 | t.x2, t.y2, t.z2, 169 | t.r, t.g, t.b, 170 | t.group); 171 | } 172 | break; 173 | } 174 | } 175 | } 176 | } 177 | // 178 | void rdbInitCheck() 179 | { 180 | std::call_once(rdbContext.initialized, []() 181 | { 182 | WSADATA wsaData; 183 | WSAStartup(MAKEWORD(2, 2), &wsaData); // TODO: エラー処理 184 | rdbContext.fd = socket(AF_INET, SOCK_STREAM, 0); 185 | // 186 | struct sockaddr_in serv_name; 187 | serv_name.sin_family = AF_INET; 188 | serv_name.sin_addr.s_addr = ::htonl(0x7F000001L); 189 | serv_name.sin_port = ::htons(10000); 190 | ::connect(rdbContext.fd, (struct sockaddr*) & serv_name, sizeof(serv_name)); 191 | ::atexit([]() 192 | { 193 | rdbFinishFlag = true; 194 | rdbMainThread.join(); 195 | ::closesocket(rdbContext.fd); 196 | }); 197 | // 198 | rdbMainThread = std::thread([]() {rdbMain(); }); 199 | }); 200 | } 201 | 202 | // 203 | void rdbPoint( 204 | float x, float y, float z, 205 | float r, float g, float b, 206 | int32_t group) 207 | { 208 | rdbInitCheck(); 209 | RdbTask task; 210 | task.rdbPoint.x = x; 211 | task.rdbPoint.y = y; 212 | task.rdbPoint.z = z; 213 | task.rdbPoint.r = r; 214 | task.rdbPoint.g = g; 215 | task.rdbPoint.b = b; 216 | task.rdbPoint.group = group; 217 | task.type = RdbTaskType::POINT; 218 | rdbTasks.push(task); 219 | } 220 | // 221 | void rdbLine( 222 | float x0, float y0, float z0, 223 | float x1, float y1, float z1, 224 | float r0, float g0, float b0, 225 | float r1, float g1, float b1, 226 | int32_t group) 227 | { 228 | rdbInitCheck(); 229 | RdbTask task; 230 | auto& t = task.rdbLine; 231 | t.x0 = x0; t.y0 = y0; t.z0 = z0; 232 | t.x1 = x1; t.y1 = y1; t.z1 = z1; 233 | t.r0 = r0; t.g0 = g0; t.b0 = b0; 234 | t.r1 = r1; t.g1 = g1; t.b1 = b1; 235 | t.group = group; 236 | task.type = RdbTaskType::LINE; 237 | rdbTasks.push(task); 238 | } 239 | // 240 | void rdbTriangle( 241 | float x0, float y0, float z0, 242 | float x1, float y1, float z1, 243 | float x2, float y2, float z2, 244 | float r, float g, float b, 245 | int32_t group) 246 | { 247 | rdbInitCheck(); 248 | RdbTask task; 249 | auto& t = task.rdbTriangle; 250 | t.x0 = x0; 251 | t.y0 = y0; 252 | t.z0 = z0; 253 | t.x1 = x1; 254 | t.y1 = y1; 255 | t.z1 = z1; 256 | t.x2 = x2; 257 | t.y2 = y2; 258 | t.z2 = z2; 259 | t.r = r; 260 | t.g = g; 261 | t.b = b; 262 | t.group = group; 263 | task.type = RdbTaskType::TRIANGLE; 264 | rdbTasks.push(task); 265 | } 266 | 267 | #endif 268 | #endif 269 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # What's this? 2 | 3 | __rdb is a Ray-tracing debugger inspired by [vdb](https://github.com/zdevito/vdb).__ 4 | 5 | Feature 6 | - Ultimately simple APIs 7 | - Thread safety 8 | - Single header only 9 | 10 | # How to use 11 | 12 | 1. run "rdb.exe" 13 | 2. include "rdb.hpp" and call APIs 14 | 3. run. 15 | 16 | # API 17 | 18 | ```c 19 | void rdbPoint( 20 | float x, float y, float z, 21 | float r, float g, float b, 22 | int32_t group); 23 | ``` 24 | 25 | ```c 26 | void rdbLine( 27 | float x0, float y0, float z0, 28 | float x1, float y1, float z1, 29 | float r0, float g0, float b0, 30 | float r1, float g1, float b1, 31 | int32_t group); 32 | ``` 33 | 34 | ```c 35 | void rdbTriangle( 36 | float x0, float y0, float z0, 37 | float x1, float y1, float z1, 38 | float x2, float y2, float z2, 39 | float r, float g, float b, 40 | int32_t group) 41 | ``` 42 | 43 | That's all. -------------------------------------------------------------------------------- /test.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ykozw/rdb/1c27de7316fdb0348ada3f3bb26eb3cefd09645f/test.cpp -------------------------------------------------------------------------------- /viewer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | #define WIN32_LEAN_AND_MEAN 3 | #define NOMINMAX 4 | #include 5 | #include 6 | #include 7 | #pragma comment(lib, "glu32.lib") 8 | 9 | #include 10 | #include 11 | #include 12 | #pragma comment(lib, "glfw3.lib") 13 | #pragma comment(lib, "opengl32.lib") 14 | #include 15 | #include 16 | //#include 17 | // 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #pragma comment(lib, "Ws2_32.lib") 27 | // 28 | #define BUFFER_SIZE (64 * 1024) 29 | 30 | enum class RdbTaskType : int32_t 31 | { 32 | POINT, 33 | LINE, 34 | TRIANGLE, 35 | }; 36 | 37 | // 38 | template 39 | struct RingBuffer 40 | { 41 | public: 42 | bool valid() const 43 | { 44 | return (ringSize_ > 0); 45 | } 46 | // 47 | void setRingSize(int32_t ringSize) 48 | { 49 | ringSize_ = ringSize; 50 | buffer_.reserve(ringSize); 51 | clear(); 52 | } 53 | // 54 | void clear() 55 | { 56 | buffer_.clear(); 57 | cursor_ = 0; 58 | } 59 | void trim(int32_t mnPercent, int32_t mxPercent) 60 | { 61 | if (!valid()) 62 | { 63 | return; 64 | } 65 | tmpBuffer_.clear(); 66 | const int32_t b = size() * mnPercent / 100; 67 | const int32_t e = size() * mxPercent / 100; 68 | for (int32_t i=b;i 85 | void add(const Type& value) 86 | { 87 | if (!valid()) 88 | { 89 | return; 90 | } 91 | if (buffer_.size() < ringSize_) 92 | { 93 | buffer_.push_back(value); 94 | } 95 | else 96 | { 97 | buffer_[cursor_] = value; 98 | cursor_ = (cursor_ + 1) % ringSize_; 99 | } 100 | } 101 | // 102 | template 103 | Type& operator [](int32_t index) 104 | { 105 | if (!valid()) 106 | { 107 | return Type(); 108 | } 109 | index = (index + cursor_) % ringSize_; 110 | return buffer_[index]; 111 | } 112 | const Type& operator [](int32_t index) const 113 | { 114 | if (!valid()) 115 | { 116 | return Type(); 117 | } 118 | index = (index + cursor_) % ringSize_; 119 | return buffer_[index]; 120 | } 121 | private: 122 | int32_t ringSize_ = -1; 123 | int32_t cursor_ = 0; 124 | std::vector buffer_; 125 | std::vector tmpBuffer_; 126 | 127 | }; 128 | 129 | // 130 | class AABB 131 | { 132 | public: 133 | AABB() = default; 134 | void clear() 135 | { 136 | *this = AABB(); 137 | } 138 | void add(glm::vec3 point) 139 | { 140 | min_ = glm::min(point, min_); 141 | max_ = glm::max(point, max_); 142 | } 143 | glm::vec3 max() const 144 | { 145 | return max_; 146 | } 147 | glm::vec3 min() const 148 | { 149 | return min_; 150 | } 151 | glm::vec3 center() const 152 | { 153 | return (min_ + max_) * 0.5f; 154 | } 155 | glm::vec3 size() const 156 | { 157 | return (max_ - min_); 158 | } 159 | private: 160 | glm::vec3 min_ = glm::vec3( 161 | std::numeric_limits::max(), 162 | std::numeric_limits::max(), 163 | std::numeric_limits::max()); 164 | glm::vec3 max_ = glm::vec3( 165 | std::numeric_limits::lowest(), 166 | std::numeric_limits::lowest(), 167 | std::numeric_limits::lowest()); 168 | }; 169 | 170 | // 171 | class Camera 172 | { 173 | public: 174 | Camera() = default; 175 | // 176 | void update() 177 | { 178 | const ImGuiIO& io = ImGui::GetIO(); 179 | // 右ドラッグで回転 180 | if (io.KeyAlt && ImGui::IsMouseDragging(1)) 181 | { 182 | const ImVec2 delta = ImGui::GetMouseDragDelta(1); 183 | ImGui::ResetMouseDragDelta(1); 184 | const float dx = 0.005f; 185 | const float dy = 0.005f; 186 | rotation_ = 187 | glm::rotate(glm::identity>(), -delta.x * dx, glm::vec3(0.0f, 1.0f, 0.0f)) * 188 | glm::rotate(glm::identity>(), +delta.y * dy, glm::vec3(1.0f, 0.0f, 0.0f)) * 189 | rotation_; 190 | } 191 | // 中ドラッグで横移動 192 | if (io.KeyAlt && ImGui::IsMouseDragging(2)) 193 | { 194 | const ImVec2 delta = ImGui::GetMouseDragDelta(2); 195 | ImGui::ResetMouseDragDelta(2); 196 | const float scale = 0.00005f; 197 | const float moveScale = r_ * scale; 198 | const glm::vec3 xaxis = glm::vec3(1.0f, 0.0f, 0.0f) * rotation_; 199 | const glm::vec3 yaxis = glm::vec3(1.0f, 1.0f, 0.0f) * rotation_; 200 | target_ += moveScale * xaxis * delta.x; 201 | target_ += moveScale * yaxis * delta.y; 202 | } 203 | // 204 | if (io.MouseWheel < 0.0f) 205 | { 206 | r_ *= 1.05f; 207 | } 208 | else if (io.MouseWheel > 0.0f) 209 | { 210 | r_ *= 0.95f; 211 | } 212 | } 213 | // 214 | glm::vec3 lookat() const 215 | { 216 | return target_; 217 | } 218 | glm::vec3 up() const 219 | { 220 | return glm::vec3(0.0f, 1.0f, 0.0f) * rotation_; 221 | } 222 | glm::vec3 position() const 223 | { 224 | glm::vec3 dir = glm::vec3(0.0f, 0.0f, 1.0f) * rotation_; 225 | return target_ - dir * r_; 226 | } 227 | void setTarget(glm::vec3 target) 228 | { 229 | target_ = target; 230 | } 231 | void setDistance(float distance) 232 | { 233 | r_ = distance; 234 | } 235 | public: 236 | // 237 | float r_ = 100.0f; 238 | glm::vec3 target_ = glm::vec3(0.0f, 0.0f, 0.0f); 239 | glm::qua rotation_ = glm::identity>(); 240 | }; 241 | 242 | // 243 | struct RdbPoint 244 | { 245 | public: 246 | float x; 247 | float y; 248 | float z; 249 | float r; 250 | float g; 251 | float b; 252 | int32_t group; 253 | }; 254 | struct RdbLine 255 | { 256 | float x0; 257 | float y0; 258 | float z0; 259 | float x1; 260 | float y1; 261 | float z1; 262 | float r0; 263 | float g0; 264 | float b0; 265 | float r1; 266 | float g1; 267 | float b1; 268 | int32_t group; 269 | }; 270 | struct RdbTriangle 271 | { 272 | float x0; 273 | float y0; 274 | float z0; 275 | float x1; 276 | float y1; 277 | float z1; 278 | float x2; 279 | float y2; 280 | float z2; 281 | float r; 282 | float g; 283 | float b; 284 | int32_t group; 285 | }; 286 | 287 | // 288 | struct RdbTask 289 | { 290 | RdbTaskType type; 291 | union 292 | { 293 | RdbPoint rdbPoint; 294 | RdbLine rdbLine; 295 | RdbTriangle rdbTriangle; 296 | }; 297 | }; 298 | Concurrency::concurrent_queue g_rdbTasks; 299 | #include 300 | 301 | class Socket 302 | { 303 | public: 304 | void init() 305 | { 306 | threawd_ = std::thread([this]() {socketMain(); }); 307 | } 308 | void setOnConnect(const std::function& onConnect) 309 | { 310 | onConnect_ = onConnect; 311 | } 312 | // 313 | void socketMain() 314 | { 315 | WSADATA wsaData; 316 | if (WSAStartup(MAKEWORD(2, 2), &wsaData)) 317 | { 318 | exit(1); 319 | } 320 | SOCKET sockd = ::socket(AF_INET, SOCK_STREAM, 0); 321 | //avoid address in use error that occur if we quit with a client connected 322 | int t = 1; 323 | int status = ::setsockopt(sockd, SOL_SOCKET, SO_REUSEADDR, (const char*)& t, sizeof(int)); 324 | if (status == -1) 325 | { 326 | exit(1); 327 | } 328 | struct sockaddr_in name; 329 | name.sin_family = AF_INET; 330 | name.sin_addr.s_addr = INADDR_ANY; 331 | name.sin_port = ::htons(10000); 332 | 333 | if (sockd == -1) 334 | { 335 | exit(1); 336 | } 337 | 338 | status = bind(sockd, (struct sockaddr*) & name, sizeof(name)); 339 | if (status == -1) 340 | { 341 | exit(1); 342 | } 343 | status = ::listen(sockd, 5); 344 | if (status == -1) 345 | { 346 | exit(1); 347 | } 348 | 349 | while (true) 350 | { 351 | puts("wait for connection"); 352 | struct sockaddr_in peer_name; 353 | int32_t addrlen = sizeof(peer_name); 354 | SOCKET sock2 = ::accept(sockd, (struct sockaddr*) & peer_name, &addrlen); 355 | puts("connected"); 356 | if (onConnect_) 357 | { 358 | onConnect_(); 359 | } 360 | // 361 | size_t dataLen = 0; 362 | while (true) 363 | { 364 | using namespace std::chrono_literals; 365 | std::this_thread::sleep_for(10ms); 366 | char data[BUFFER_SIZE / 16]; 367 | int r = recv(sock2, data, sizeof(data) - 1, 0); 368 | if (r < 0) 369 | { 370 | puts("disconnect"); 371 | break; 372 | } 373 | 374 | if (r > 0) 375 | { 376 | // 377 | dataLen += r; 378 | // あふれる場合はすべてリセット 379 | if (sizeof(datum_) <= dataLen) 380 | { 381 | dataLen = 0; 382 | datum_[0] = '\0'; 383 | puts("OUT"); 384 | } 385 | else 386 | { 387 | data[dataLen] = '\0'; 388 | strcat(datum_, data); 389 | 390 | // "\n"が入っていたら分割フェイズ 391 | if (strchr(datum_, '\n') != nullptr) 392 | { 393 | // TODO: 最後のに\nが入っていることを確認しないといけない 394 | const char* token = strtok(datum_, "\n"); 395 | processToken(token); 396 | const char* lastToken = nullptr; 397 | while (token = strtok(nullptr, "\n")) 398 | { 399 | lastToken = token; 400 | processToken(token); 401 | } 402 | //// 最後の要素に\nがなければ次回に回す 403 | //if (strchr(lastToken, '\n') == nullptr) 404 | //{ 405 | // dataLen = strlen(lastToken); 406 | // memmove(datum_, lastToken, strlen(lastToken)+1); 407 | //} 408 | //else 409 | { 410 | dataLen = 0; 411 | datum_[0] = '\0'; 412 | } 413 | 414 | } 415 | } 416 | } 417 | } 418 | } 419 | } 420 | void processToken(const char* token) 421 | { 422 | RdbTask task; 423 | switch (token[0]) 424 | { 425 | case 'P': 426 | { 427 | task.type = RdbTaskType::POINT; 428 | auto& t = task.rdbPoint; 429 | if (sscanf(token, "P %f,%f,%f,%f,%f,%f,%d\n", 430 | &t.x, &t.y, &t.z, &t.r, &t.g, &t.b, &t.group) == 7) 431 | { 432 | g_rdbTasks.push(task); 433 | } 434 | } 435 | break; 436 | case 'L': 437 | { 438 | task.type = RdbTaskType::LINE; 439 | auto& t = task.rdbLine; 440 | if (sscanf(token, "L %f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d\n", 441 | &t.x0, &t.y0, &t.z0, 442 | &t.x1, &t.y1, &t.z1, 443 | &t.r0, &t.g0, &t.b0, 444 | &t.r1, &t.g1, &t.b1, 445 | &t.group) == 13) 446 | { 447 | g_rdbTasks.push(task); 448 | } 449 | 450 | } 451 | break; 452 | case 'T': 453 | { 454 | task.type = RdbTaskType::TRIANGLE; 455 | auto& t = task.rdbTriangle; 456 | int32_t group; 457 | if (sscanf(token, "T %f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%d\n", 458 | &t.x0, &t.y0, &t.z0, 459 | &t.x1, &t.y1, &t.z1, 460 | &t.x2, &t.y2, &t.z2, 461 | &t.r, &t.g, &t.b, 462 | &t.group) == 13) 463 | { 464 | g_rdbTasks.push(task); 465 | } 466 | } 467 | break; 468 | } 469 | } 470 | private: 471 | std::thread threawd_; 472 | char datum_[BUFFER_SIZE] = { '\0' }; 473 | std::function onConnect_ = nullptr; 474 | }; 475 | 476 | // 477 | class Window 478 | { 479 | public: 480 | GLFWwindow* window_; 481 | int32_t windowWidth_; 482 | int32_t windowHeight_; 483 | Camera camera_; 484 | Socket socket_; 485 | 486 | // 描画範囲の百分率 487 | std::array pointDrawRange_ = { 0, 100 }; 488 | std::array lineDrawRange_ = { 0, 100 }; 489 | std::array triDrawRange_ = { 0, 100 }; 490 | 491 | public: 492 | Window() 493 | { 494 | // 495 | socket_.init(); 496 | socket_.setOnConnect([this](){ clearGeometory(); }); 497 | // TODO: 呼び出しタイミングはこれでよいのか? 498 | glewInit(); 499 | // Setup window_ 500 | glfwSetErrorCallback(glfw_error_callback); 501 | if (!glfwInit()) 502 | return; 503 | const int32_t width = 1280; 504 | const int32_t height = 720; 505 | window_ = glfwCreateWindow(width, height, "Ray Debugger", NULL, NULL); 506 | if (window_ == NULL) 507 | { 508 | return; 509 | } 510 | glfwMakeContextCurrent(window_); 511 | glfwSwapInterval(1); // Enable vsync 512 | 513 | // 514 | onWindowResize(width, height); 515 | glfwSetWindowUserPointer(window_, this); 516 | glfwSetWindowSizeCallback(window_, resize_callback); 517 | 518 | // Setup Dear ImGui context 519 | IMGUI_CHECKVERSION(); 520 | ImGui::CreateContext(); 521 | ImGuiIO& io = ImGui::GetIO(); (void)io; 522 | io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls 523 | //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls 524 | 525 | // Setup Platform/Renderer bindings 526 | ImGui_ImplGlfw_InitForOpenGL(window_, true); 527 | ImGui_ImplOpenGL2_Init(); 528 | 529 | Style(); 530 | 531 | // 532 | const int32_t ringSizeMaxDefault = 1024*1024; 533 | points_.setRingSize(ringSizeMaxDefault); 534 | lines_.setRingSize(ringSizeMaxDefault); 535 | triangles_.setRingSize(ringSizeMaxDefault); 536 | } 537 | // https://github.com/ocornut/imgui/issues/707#issuecomment-468798935 538 | inline void Style() 539 | { 540 | ImGuiStyle& style = ImGui::GetStyle(); 541 | ImVec4* colors = style.Colors; 542 | 543 | /// 0 = FLAT APPEARENCE 544 | /// 1 = MORE "3D" LOOK 545 | int is3D = 0; 546 | 547 | colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); 548 | colors[ImGuiCol_TextDisabled] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); 549 | colors[ImGuiCol_ChildBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 550 | colors[ImGuiCol_WindowBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 551 | colors[ImGuiCol_PopupBg] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 552 | colors[ImGuiCol_Border] = ImVec4(0.12f, 0.12f, 0.12f, 0.71f); 553 | colors[ImGuiCol_BorderShadow] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); 554 | colors[ImGuiCol_FrameBg] = ImVec4(0.42f, 0.42f, 0.42f, 0.54f); 555 | colors[ImGuiCol_FrameBgHovered] = ImVec4(0.42f, 0.42f, 0.42f, 0.40f); 556 | colors[ImGuiCol_FrameBgActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.67f); 557 | colors[ImGuiCol_TitleBg] = ImVec4(0.19f, 0.19f, 0.19f, 1.00f); 558 | colors[ImGuiCol_TitleBgActive] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f); 559 | colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.17f, 0.17f, 0.17f, 0.90f); 560 | colors[ImGuiCol_MenuBarBg] = ImVec4(0.335f, 0.335f, 0.335f, 1.000f); 561 | colors[ImGuiCol_ScrollbarBg] = ImVec4(0.24f, 0.24f, 0.24f, 0.53f); 562 | colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); 563 | colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); 564 | colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); 565 | colors[ImGuiCol_CheckMark] = ImVec4(0.65f, 0.65f, 0.65f, 1.00f); 566 | colors[ImGuiCol_SliderGrab] = ImVec4(0.52f, 0.52f, 0.52f, 1.00f); 567 | colors[ImGuiCol_SliderGrabActive] = ImVec4(0.64f, 0.64f, 0.64f, 1.00f); 568 | colors[ImGuiCol_Button] = ImVec4(0.54f, 0.54f, 0.54f, 0.35f); 569 | colors[ImGuiCol_ButtonHovered] = ImVec4(0.52f, 0.52f, 0.52f, 0.59f); 570 | colors[ImGuiCol_ButtonActive] = ImVec4(0.76f, 0.76f, 0.76f, 1.00f); 571 | colors[ImGuiCol_Header] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f); 572 | colors[ImGuiCol_HeaderHovered] = ImVec4(0.47f, 0.47f, 0.47f, 1.00f); 573 | colors[ImGuiCol_HeaderActive] = ImVec4(0.76f, 0.76f, 0.76f, 0.77f); 574 | colors[ImGuiCol_Separator] = ImVec4(0.000f, 0.000f, 0.000f, 0.137f); 575 | colors[ImGuiCol_SeparatorHovered] = ImVec4(0.700f, 0.671f, 0.600f, 0.290f); 576 | colors[ImGuiCol_SeparatorActive] = ImVec4(0.702f, 0.671f, 0.600f, 0.674f); 577 | colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); 578 | colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); 579 | colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); 580 | colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); 581 | colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); 582 | colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); 583 | colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); 584 | colors[ImGuiCol_TextSelectedBg] = ImVec4(0.73f, 0.73f, 0.73f, 0.35f); 585 | colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); 586 | colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); 587 | colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); 588 | colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); 589 | colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); 590 | 591 | style.PopupRounding = 3; 592 | 593 | style.WindowPadding = ImVec2(4, 4); 594 | style.FramePadding = ImVec2(6, 4); 595 | style.ItemSpacing = ImVec2(6, 2); 596 | 597 | style.ScrollbarSize = 18; 598 | 599 | style.WindowBorderSize = 1; 600 | style.ChildBorderSize = 1; 601 | style.PopupBorderSize = 1; 602 | style.FrameBorderSize = is3D; 603 | 604 | style.WindowRounding = 3; 605 | style.ChildRounding = 3; 606 | style.FrameRounding = 3; 607 | style.ScrollbarRounding = 2; 608 | style.GrabRounding = 3; 609 | 610 | #ifdef IMGUI_HAS_DOCK 611 | style.TabBorderSize = is3D; 612 | style.TabRounding = 3; 613 | 614 | colors[ImGuiCol_DockingEmptyBg] = ImVec4(0.38f, 0.38f, 0.38f, 1.00f); 615 | colors[ImGuiCol_Tab] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 616 | colors[ImGuiCol_TabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 1.00f); 617 | colors[ImGuiCol_TabActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f); 618 | colors[ImGuiCol_TabUnfocused] = ImVec4(0.25f, 0.25f, 0.25f, 1.00f); 619 | colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.33f, 0.33f, 0.33f, 1.00f); 620 | colors[ImGuiCol_DockingPreview] = ImVec4(0.85f, 0.85f, 0.85f, 0.28f); 621 | 622 | if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) 623 | { 624 | style.WindowRounding = 0.0f; 625 | style.Colors[ImGuiCol_WindowBg].w = 1.0f; 626 | } 627 | #endif 628 | } 629 | // 630 | static void resize_callback(GLFWwindow* window, int width, int height) 631 | { 632 | Window* this_ = static_cast(glfwGetWindowUserPointer(window)); 633 | this_->onWindowResize(width, height); 634 | } 635 | // 636 | void onWindowResize(int32_t width, int32_t height) 637 | { 638 | windowWidth_ = width; 639 | windowHeight_ = height; 640 | } 641 | // カメラをシーンにフィットさせる 642 | void fitCamrera() 643 | { 644 | AABB sceneBound; 645 | // 646 | for (int32_t i = pointDrawRange_[0]; i < pointDrawRange_[1]; ++i) 647 | { 648 | auto& p = points_[i]; 649 | sceneBound.add(glm::vec3(p.x, p.y, p.z)); 650 | } 651 | // 652 | for (int32_t i = lineDrawRange_[0]; i < lineDrawRange_[1]; ++i) 653 | { 654 | auto& l = lines_[i]; 655 | sceneBound.add(glm::vec3(l.x0, l.y0, l.z0)); 656 | sceneBound.add(glm::vec3(l.x1, l.y1, l.z1)); 657 | } 658 | // 659 | for (int32_t i = triDrawRange_[0]; i < triDrawRange_[1]; ++i) 660 | { 661 | auto& t = triangles_[i]; 662 | sceneBound.add(glm::vec3(t.x0, t.y0, t.z0)); 663 | sceneBound.add(glm::vec3(t.x1, t.y1, t.z1)); 664 | sceneBound.add(glm::vec3(t.x2, t.y2, t.z2)); 665 | } 666 | // 667 | camera_.setTarget(sceneBound.center()); 668 | const glm::vec3 size = sceneBound.size(); 669 | const float scale = 25.0f; // TODO: 本当はfovを見て計算するべき 670 | const float distance = (size.x + size.y + size.z) * 0.5f * scale; 671 | camera_.setDistance(distance); 672 | } 673 | // 674 | void clearGeometory() 675 | { 676 | points_.clear(); 677 | lines_.clear(); 678 | triangles_.clear(); 679 | } 680 | // 保持するジオメトリを表示しているものだけにする 681 | void trimGeometory() 682 | { 683 | points_.trim(pointDrawRange_[0], pointDrawRange_[1]); 684 | lines_.trim(lineDrawRange_[0], lineDrawRange_[1]); 685 | triangles_.trim(triDrawRange_[0], triDrawRange_[1]); 686 | pointDrawRange_ = {0, 100}; 687 | lineDrawRange_ = { 0, 100 }; 688 | triDrawRange_ = { 0, 100 }; 689 | } 690 | // 691 | void onDisconnect() 692 | { 693 | clearGeometory(); 694 | } 695 | // 696 | void drawToolWindow() 697 | { 698 | // 699 | ImGuiWindowFlags window_flags = 0; 700 | window_flags |= ImGuiWindowFlags_NoTitleBar; 701 | window_flags |= ImGuiWindowFlags_NoMove; 702 | window_flags |= ImGuiWindowFlags_NoResize; 703 | //window_flags |= ImGuiWindowFlags_NoBackground; 704 | 705 | 706 | ImGui::SetNextWindowPos(ImVec2(windowWidth_-GUI_WIDTH, 0.0f)); 707 | ImGui::SetNextWindowSize(ImVec2( 708 | GUI_WIDTH, 709 | windowHeight_)); 710 | 711 | ImGui::Begin("MainWindow", nullptr, window_flags); 712 | { 713 | // ------------------------------------------------------- 714 | ImGui::Separator(); 715 | ImGui::Text("Stats"); 716 | ImGui::Text("FPS %.1f", ImGui::GetIO().Framerate); 717 | // ------------------------------------------------------- 718 | ImGui::Separator(); 719 | ImGui::Text("Basic"); 720 | if (ImGui::Button("Clear")) 721 | { 722 | clearGeometory(); 723 | } 724 | ImGui::SameLine(); 725 | if (ImGui::Button("Trim")) 726 | { 727 | trimGeometory(); 728 | } 729 | ImGui::SameLine(); 730 | if (ImGui::Button("Fit")) 731 | { 732 | fitCamrera(); 733 | } 734 | ImGui::SameLine(); 735 | ImGui::ColorEdit4("BG##3", (float*)&bgColor_, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel); 736 | // 737 | ImGui::AlignTextToFramePadding(); 738 | ImGui::Text("Point Size "); 739 | ImGui::SetNextItemWidth(120); 740 | ImGui::SameLine(); 741 | ImGui::SliderFloat("##POINT_SIZE", &pointSize_, 1.0f, 10.0f, "%.3f", 2.0f); 742 | // 743 | ImGui::AlignTextToFramePadding(); 744 | ImGui::Text("Line Width "); 745 | ImGui::SetNextItemWidth(120); 746 | ImGui::SameLine(); 747 | ImGui::SliderFloat("##LINE_WIDTH", &lineWidth_, 1.0f, 10.0f, "%.3f", 2.0f); 748 | 749 | // ------------------------------------------------------- 750 | ImGui::Separator(); 751 | ImGui::Text("Filter"); 752 | ImGui::Text(" Used Max Low High"); 753 | // 754 | ImGui::AlignTextToFramePadding(); 755 | ImGui::Text("Point %8d", points_.size()); 756 | ImGui::SameLine(); 757 | ImGui::SetNextItemWidth(60); 758 | int pointRingMax = points_.ringSize(); 759 | if (ImGui::DragInt("##POINT_RING_MAX", &pointRingMax, 16, 16, 1024*16)) 760 | { 761 | points_.setRingSize(pointRingMax); 762 | } 763 | ImGui::SetNextItemWidth(300); 764 | ImGui::SameLine(); 765 | ImGui::SliderInt2("##POINT_DRAW_RANGE", pointDrawRange_.data(), 0, 100); 766 | // 767 | ImGui::AlignTextToFramePadding(); 768 | ImGui::Text("Line %8d", lines_.size()); 769 | ImGui::SameLine(); 770 | ImGui::SetNextItemWidth(60); 771 | int lineRingMax = lines_.ringSize(); 772 | if (ImGui::DragInt("##LINE_RING_MAX", &lineRingMax, 1, 16, 255)) 773 | { 774 | lines_.setRingSize(lineRingMax); 775 | } 776 | ImGui::SameLine(); 777 | ImGui::SetNextItemWidth(300); 778 | ImGui::SliderInt2("##LINE_DRAW_RANGE", lineDrawRange_.data(), 0, 100); 779 | // 780 | ImGui::AlignTextToFramePadding(); 781 | ImGui::Text("Triangle %8d", triangles_.size()); 782 | ImGui::SameLine(); 783 | ImGui::SetNextItemWidth(60); 784 | int triangleRingMax = triangles_.ringSize(); 785 | if (ImGui::DragInt("##TRIANGLE_RING_MAX", &triangleRingMax, 1, 16, 255)) 786 | { 787 | triangles_.setRingSize(triangleRingMax); 788 | } 789 | ImGui::SameLine(); 790 | ImGui::SetNextItemWidth(300); 791 | ImGui::SliderInt2("##TRIANGLE_DRAW_RANGE", triDrawRange_.data(), 0, 100); 792 | // 793 | // ------------------------------------------------------- 794 | 795 | } 796 | ImGui::End(); 797 | } 798 | 799 | // 800 | void drawLine() 801 | { 802 | // 803 | glViewport(0, 0, windowWidth_ - GUI_WIDTH, windowHeight_); 804 | 805 | // Projection行列の設定 806 | glMatrixMode(GL_PROJECTION); 807 | glLoadIdentity(); 808 | const double aspect = double(windowWidth_ - GUI_WIDTH) / double(windowHeight_); 809 | const float fovyInDegree = 60.0f; 810 | const float nz = 0.01f; 811 | const float fz = 1000.0f; 812 | gluPerspective(fovyInDegree, aspect, nz, fz); 813 | 814 | // MV行列設定 815 | glMatrixMode(GL_MODELVIEW); 816 | glLoadIdentity(); 817 | const glm::vec3 target = camera_.lookat(); 818 | const glm::vec3 up = camera_.up(); 819 | const glm::vec3 pos = camera_.position(); 820 | gluLookAt( pos.x, pos.y, pos.z, target.x, target.y, target.z, up.x, up.y, up.z); 821 | // 822 | glPointSize(pointSize_); 823 | glLineWidth(lineWidth_); 824 | // points 825 | glBegin(GL_POINTS); 826 | const int32_t pointsDrawBegin = pointDrawRange_[0] * points_.size() / 100; 827 | const int32_t pointsDrawEnd = pointDrawRange_[1] * points_.size() / 100; 828 | for (int32_t i = pointsDrawBegin; i < pointsDrawEnd; ++i) 829 | { 830 | const RdbPoint& point = points_[i]; 831 | glColor4f(point.r, point.g, point.b, 1.0f); 832 | glVertex3f(point.x, point.y, point.z); 833 | } 834 | glEnd(); 835 | // lines 836 | glBegin(GL_LINES); 837 | const int32_t linesDrawBegin = lineDrawRange_[0] * lines_.size() / 100; 838 | const int32_t linesDrawEnd = lineDrawRange_[1] * lines_.size() / 100; 839 | for (int32_t i = linesDrawBegin; i < linesDrawEnd; ++i) 840 | { 841 | const RdbLine& line = lines_[i]; 842 | glColor4f(line.r0, line.g0, line.b0, 1.0f); 843 | glVertex3f(line.x0, line.y0, line.z0); 844 | glColor4f(line.r1, line.g1, line.b1, 1.0f); 845 | glVertex3f(line.x1, line.y1, line.z1); 846 | } 847 | glEnd(); 848 | // triangles 849 | glBegin(GL_LINES); 850 | const int32_t triDrawBegin = triDrawRange_[0] * triangles_.size() / 100; 851 | const int32_t triDrawEnd = triDrawRange_[1] * triangles_.size() / 100; 852 | for (int32_t i = triDrawBegin; i < triDrawEnd; ++i) 853 | { 854 | const RdbTriangle& tri = triangles_[i]; 855 | // 856 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 857 | glVertex3f(tri.x0, tri.y0, tri.z0); 858 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 859 | glVertex3f(tri.x1, tri.y1, tri.z1); 860 | // 861 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 862 | glVertex3f(tri.x1, tri.y1, tri.z1); 863 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 864 | glVertex3f(tri.x2, tri.y2, tri.z2); 865 | // 866 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 867 | glVertex3f(tri.x2, tri.y2, tri.z2); 868 | glColor4f(tri.r, tri.g, tri.b, 1.0f); 869 | glVertex3f(tri.x0, tri.y0, tri.z0); 870 | } 871 | glEnd(); 872 | // 873 | glFlush(); 874 | } 875 | // 876 | void update() 877 | { 878 | bool show_demo_window = true; 879 | bool show_another_window = false; 880 | // Main loop 881 | while (!glfwWindowShouldClose(window_)) 882 | { 883 | // 全ての積まれているタスクを描画に変換する 884 | while (!g_rdbTasks.empty()) 885 | { 886 | RdbTask task; 887 | if (g_rdbTasks.try_pop(task)) 888 | { 889 | switch (task.type) 890 | { 891 | case RdbTaskType::POINT: 892 | points_.add(task.rdbPoint); 893 | break; 894 | case RdbTaskType::LINE: 895 | lines_.add(task.rdbLine); 896 | break; 897 | case RdbTaskType::TRIANGLE: 898 | triangles_.add(task.rdbTriangle); 899 | break; 900 | } 901 | } 902 | } 903 | // 904 | glfwPollEvents(); 905 | // 906 | ImGui_ImplOpenGL2_NewFrame(); 907 | ImGui_ImplGlfw_NewFrame(); 908 | ImGui::NewFrame(); 909 | // 910 | camera_.update(); 911 | // GUI 912 | drawToolWindow(); 913 | //ImGui::ShowDemoWindow(&show_demo_window); 914 | // Rendering 915 | ImGui::Render(); 916 | int display_w, display_h; 917 | glfwGetFramebufferSize(window_, &display_w, &display_h); 918 | glViewport(0, 0, display_w, display_h); 919 | glClearColor(bgColor_.x, bgColor_.y, bgColor_.z, bgColor_.w); 920 | glClear(GL_COLOR_BUFFER_BIT); 921 | // 922 | glPushMatrix(); 923 | drawLine(); 924 | glPopMatrix(); 925 | // 926 | ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); 927 | // 928 | glfwMakeContextCurrent(window_); 929 | glfwSwapBuffers(window_); 930 | } 931 | } 932 | private: 933 | static void glfw_error_callback(int error, const char* description) 934 | { 935 | fprintf(stderr, "Glfw Error %d: %s\n", error, description); 936 | } 937 | private: 938 | RingBuffer points_; 939 | RingBuffer lines_; 940 | RingBuffer triangles_; 941 | float pointSize_ = 1.0f; 942 | float lineWidth_ = 1.0f; 943 | // 944 | const int32_t GUI_WIDTH = 500; 945 | // 946 | ImVec4 bgColor_ = ImVec4(0.1f, 0.1f, 0.1f, 1.00f); 947 | }; 948 | 949 | // 950 | int main() 951 | { 952 | Window window; 953 | window.update(); 954 | return 0; 955 | } 956 | --------------------------------------------------------------------------------