#include "SampleInterfaces.h" #include "DetourDebugDraw.h" #include "PerfTimer.h" #include "Recast.h" #include "RecastDebugDraw.h" #include "SDL.h" #include "SDL_opengl.h" #include #include #include #ifdef WIN32 # define snprintf _snprintf #endif //////////////////////////////////////////////////////////////////////////////////////////////////// BuildContext::BuildContext() { memset(m_messages, 0, sizeof(char*) * MAX_MESSAGES); resetTimers(); } void BuildContext::doResetLog() { m_messageCount = 0; m_textPoolSize = 0; } void BuildContext::doLog(const rcLogCategory category, const char* msg, const int len) { if (!len) { return; } if (m_messageCount >= MAX_MESSAGES) { return; } char* dst = &m_textPool[m_textPoolSize]; int n = TEXT_POOL_SIZE - m_textPoolSize; if (n < 2) { return; } char* cat = dst; char* text = dst + 1; const int maxtext = n - 1; // Store category *cat = (char)category; // Store message const int count = rcMin(len + 1, maxtext); memcpy(text, msg, count); text[count - 1] = '\0'; m_textPoolSize += 1 + count; m_messages[m_messageCount++] = dst; } void BuildContext::doResetTimers() { for (int i = 0; i < RC_MAX_TIMERS; ++i) { m_accTime[i] = -1; } } void BuildContext::doStartTimer(const rcTimerLabel label) { m_startTime[label] = getPerfTime(); } void BuildContext::doStopTimer(const rcTimerLabel label) { const TimeVal endTime = getPerfTime(); const TimeVal deltaTime = endTime - m_startTime[label]; if (m_accTime[label] == -1) { m_accTime[label] = deltaTime; } else { m_accTime[label] += deltaTime; } } int BuildContext::doGetAccumulatedTime(const rcTimerLabel label) const { return getPerfTimeUsec(m_accTime[label]); } void BuildContext::dumpLog(const char* format, ...) { // Print header. va_list ap; va_start(ap, format); vprintf(format, ap); va_end(ap); printf("\n"); // Print messages const int TAB_STOPS[4] = {28, 36, 44, 52}; for (int i = 0; i < m_messageCount; ++i) { const char* msg = m_messages[i] + 1; int n = 0; while (*msg) { if (*msg == '\t') { int count = 1; for (int j = 0; j < 4; ++j) { if (n < TAB_STOPS[j]) { count = TAB_STOPS[j] - n; break; } } while (--count) { putchar(' '); n++; } } else { putchar(*msg); n++; } msg++; } putchar('\n'); } } int BuildContext::getLogCount() const { return m_messageCount; } const char* BuildContext::getLogText(const int i) const { return m_messages[i] + 1; } //////////////////////////////////////////////////////////////////////////////////////////////////// class GLCheckerTexture { unsigned int m_texId = 0; public: ~GLCheckerTexture() { if (m_texId != 0) { glDeleteTextures(1, &m_texId); } } void bind() { if (m_texId != 0) { glBindTexture(GL_TEXTURE_2D, m_texId); } else { // Create checker pattern. const unsigned int col0 = duRGBA(215, 215, 215, 255); const unsigned int col1 = duRGBA(255, 255, 255, 255); static const int TSIZE = 64; unsigned int data[TSIZE * TSIZE]; glGenTextures(1, &m_texId); glBindTexture(GL_TEXTURE_2D, m_texId); int level = 0; int size = TSIZE; while (size > 0) { for (int y = 0; y < size; ++y) { for (int x = 0; x < size; ++x) { data[x + y * size] = (x == 0 || y == 0) ? col0 : col1; } } glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); size /= 2; level++; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } } }; static GLCheckerTexture g_tex; void DebugDrawGL::depthMask(bool state) { glDepthMask(state ? GL_TRUE : GL_FALSE); } void DebugDrawGL::texture(bool state) { if (state) { glEnable(GL_TEXTURE_2D); g_tex.bind(); } else { glDisable(GL_TEXTURE_2D); } } void DebugDrawGL::begin(duDebugDrawPrimitives prim, float size) { switch (prim) { case DU_DRAW_POINTS: glPointSize(size); glBegin(GL_POINTS); break; case DU_DRAW_LINES: glLineWidth(size); glBegin(GL_LINES); break; case DU_DRAW_TRIS: glBegin(GL_TRIANGLES); break; case DU_DRAW_QUADS: glBegin(GL_QUADS); break; }; } void DebugDrawGL::vertex(const float* pos, unsigned int color) { glColor4ubv((GLubyte*)&color); glVertex3fv(pos); } void DebugDrawGL::vertex(const float x, const float y, const float z, unsigned int color) { glColor4ubv((GLubyte*)&color); glVertex3f(x, y, z); } void DebugDrawGL::vertex(const float* pos, unsigned int color, const float* uv) { glColor4ubv((GLubyte*)&color); glTexCoord2fv(uv); glVertex3fv(pos); } void DebugDrawGL::vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v) { glColor4ubv((GLubyte*)&color); glTexCoord2f(u, v); glVertex3f(x, y, z); } void DebugDrawGL::end() { glEnd(); glLineWidth(1.0f); glPointSize(1.0f); } //////////////////////////////////////////////////////////////////////////////////////////////////// FileIO::~FileIO() { if (m_fp) { fclose(m_fp); } } bool FileIO::openForWrite(const char* path) { if (m_fp) { return false; } m_fp = fopen(path, "wb"); if (!m_fp) { return false; } m_mode = 1; return true; } bool FileIO::openForRead(const char* path) { if (m_fp) { return false; } m_fp = fopen(path, "rb"); if (!m_fp) { return false; } m_mode = 2; return true; } bool FileIO::isWriting() const { return m_mode == 1; } bool FileIO::isReading() const { return m_mode == 2; } bool FileIO::write(const void* ptr, const size_t size) { if (!m_fp || m_mode != 1) { return false; } fwrite(ptr, size, 1, m_fp); return true; } bool FileIO::read(void* ptr, const size_t size) { if (!m_fp || m_mode != 2) { return false; } size_t readLen = fread(ptr, size, 1, m_fp); return readLen == 1; }