#define _USE_MATH_DEFINES #include #include #include #include "SampleInterfaces.h" #include "Recast.h" #include "RecastDebugDraw.h" #include "DetourDebugDraw.h" #include "PerfTimer.h" #include "SDL.h" #include "SDL_opengl.h" #ifdef WIN32 # define snprintf _snprintf #endif //////////////////////////////////////////////////////////////////////////////////////////////////// BuildContext::BuildContext() : m_messageCount(0), m_textPoolSize(0) { memset(m_messages, 0, sizeof(char*) * MAX_MESSAGES); resetTimers(); } // Virtual functions for custom implementations. 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; public: GLCheckerTexture() : m_texId(0) { } ~GLCheckerTexture() { if (m_texId != 0) glDeleteTextures(1, &m_texId); } void bind() { if (m_texId == 0) { // 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); } else { glBindTexture(GL_TEXTURE_2D, m_texId); } } }; 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() : m_fp(0), m_mode(-1) { } 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; }