Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/WolfireGames/overgrowth.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Graphics/pxdebugdraw.cpp')
-rw-r--r--Source/Graphics/pxdebugdraw.cpp1143
1 files changed, 1143 insertions, 0 deletions
diff --git a/Source/Graphics/pxdebugdraw.cpp b/Source/Graphics/pxdebugdraw.cpp
new file mode 100644
index 00000000..8aadee4e
--- /dev/null
+++ b/Source/Graphics/pxdebugdraw.cpp
@@ -0,0 +1,1143 @@
+//-----------------------------------------------------------------------------
+// Name: pxdebugdraw.cpp
+// Developer: Wolfire Games LLC
+// Description:
+// License: Read below
+//-----------------------------------------------------------------------------
+//
+//
+// Copyright 2022 Wolfire Games LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-----------------------------------------------------------------------------
+#include "pxdebugdraw.h"
+
+#include <Graphics/graphics.h>
+#include <Graphics/geometry.h>
+#include <Graphics/camera.h>
+#include <Graphics/textures.h>
+#include <Graphics/shaders.h>
+#include <Graphics/model.h>
+#include <Graphics/Billboard.h>
+#include <Graphics/font_renderer.h>
+#include <Graphics/text.h>
+#include <Graphics/vboringcontainer.h>
+
+#include <Internal/timer.h>
+#include <Internal/profiler.h>
+#include <Internal/common.h>
+
+#include <Math/vec3math.h>
+#include <Math/vec4math.h>
+
+#include <Logging/logdata.h>
+
+#include <set>
+
+extern Timer game_timer;
+
+extern TextAtlas g_text_atlas[kNumTextAtlas];
+extern TextAtlasRenderer g_text_atlas_renderer;
+
+extern bool g_debug_runtime_disable_debug_draw;
+extern bool g_debug_runtime_disable_debug_ribbon_draw;
+
+DebugDraw::~DebugDraw() {
+ Dispose();
+}
+
+void DebugDraw::Dispose() {
+ DebugDrawElementMap::iterator iter = elements.begin();
+ for(;iter != elements.end(); ++iter){
+ DebugDrawElement* element = (*iter).second;
+ delete element;
+ }
+ elements.clear();
+}
+
+void DebugDraw::Draw() {
+ // Can't return early for g_debug_runtime_disable_debug_draw without memory usage ramping up every frame
+
+ bool editor_draw = true;
+ if(Graphics::Instance()->media_mode() ||
+ ActiveCameras::Instance()->Get()->GetFlags() == Camera::kPreviewCamera ||
+ elements.empty())
+ {
+ editor_draw = false;
+ }
+
+ CHECK_GL_ERROR();
+ GLState gl_state;
+ gl_state.blend = true;
+ gl_state.cull_face = false;
+ gl_state.depth_test = true;
+ gl_state.depth_write = false;
+ Graphics::Instance()->setGLState(gl_state);
+
+ if (!g_debug_runtime_disable_debug_draw) {
+ delete_on_update.Draw();
+ delete_on_draw.Draw();
+ }
+ delete_on_draw.verts.clear();
+
+ int old_key = -1;
+ DebugDrawElementMap::iterator iter = elements.begin();
+ for(;iter != elements.end();){
+ DebugDrawElement* element = (*iter).second;
+ CHECK_GL_ERROR();
+ if(!g_debug_runtime_disable_debug_draw && (element->type == kRibbon || editor_draw) && element->visible){
+ PROFILER_GPU_ZONE(g_profiler_ctx, "Draw element");
+ Graphics::Instance()->setDepthTest(true);
+ element->Draw();
+ }
+ CHECK_GL_ERROR();
+ if(element->GetLifespan() == _delete_on_draw){
+ LOGS << "Removing element" << std::endl;
+ delete element;
+ elements.erase(iter);
+ if(old_key == -1){
+ iter = elements.begin();
+ } else {
+ iter = ++elements.find(old_key);
+ }
+ } else {
+ old_key = (*iter).first;
+ ++iter;
+ }
+ }
+ CHECK_GL_ERROR();
+}
+
+void DebugDraw::Update(float timestep) {
+ delete_on_update.verts.clear();
+ int old_key = -1;
+ DebugDrawElementMap::iterator iter = elements.begin();
+ for(;iter != elements.end();){
+ DebugDrawElement* element = (*iter).second;
+ if(element->GetLifespan() == _fade){
+ element->fade_amount += timestep;
+ }
+ bool to_delete = element->GetLifespan() == _delete_on_update ||
+ element->fade_amount >= 1.0f;
+ if(to_delete){
+ delete element;
+ elements.erase(iter);
+ if(old_key == -1){
+ iter = elements.begin();
+ } else {
+ iter = ++elements.find(old_key);
+ }
+ } else {
+ old_key = (*iter).first;
+ ++iter;
+ }
+ }
+}
+
+void DebugDraw::Remove( int which )
+{
+ LOGS << "Erasing element" << std::endl;
+ DebugDrawElementMap::iterator iter;
+ iter = elements.find(which);
+ if(iter != elements.end()){
+ free_ids.push((*iter).first);
+ DebugDrawElement* element = (*iter).second;
+ delete element;
+ elements.erase(iter);
+ }
+}
+
+int DebugDraw::AddElement( DebugDrawElement* element,
+ const DDLifespan lifespan)
+{
+ LOGS << "Adding element" << std::endl;
+ int new_id;
+ if(free_ids.empty()){
+ new_id = id_index++;
+ } else {
+ new_id = free_ids.front();
+ free_ids.pop();
+ }
+ element->SetLifespan(lifespan);
+ elements.insert(std::pair<int, DebugDrawElement*> (new_id, element));
+ return new_id;
+}
+
+DebugDraw::DebugDraw():
+ id_index(0)
+{}
+
+int DebugDraw::AddLine( const vec3 &start,
+ const vec3 &end,
+ const vec4 &start_color,
+ const vec4 &end_color,
+ const DDLifespan lifespan,
+ const DDFlag& flags)
+{
+ if(lifespan == _delete_on_update && flags == _DD_NO_FLAG){
+ size_t start_count = delete_on_update.verts.size();
+ delete_on_update.verts.resize(start_count + 14);
+ memcpy(&delete_on_update.verts[start_count + 0], &start[0], sizeof(vec3));
+ memcpy(&delete_on_update.verts[start_count + 3], &start_color[0], sizeof(vec4));
+ memcpy(&delete_on_update.verts[start_count + 7], &end[0], sizeof(vec3));
+ memcpy(&delete_on_update.verts[start_count + 10], &end_color[0], sizeof(vec4));
+ return -1;
+ } else if(lifespan == _delete_on_draw && flags == _DD_NO_FLAG){
+ size_t start_count = delete_on_draw.verts.size();
+ delete_on_draw.verts.resize(start_count + 14);
+ memcpy(&delete_on_draw.verts[start_count + 0], &start[0], sizeof(vec3));
+ memcpy(&delete_on_draw.verts[start_count + 3], &start_color[0], sizeof(vec4));
+ memcpy(&delete_on_draw.verts[start_count + 7], &end[0], sizeof(vec3));
+ memcpy(&delete_on_draw.verts[start_count + 10], &end_color[0], sizeof(vec4));
+ return -1;
+ } else {
+ DebugDrawElement* element = new DebugDrawLine(start, end, start_color, end_color, flags);
+ return AddElement(element, lifespan);
+ }
+}
+
+int DebugDraw::AddLine( const vec3 &start,
+ const vec3 &end,
+ const vec4 &color,
+ const DDLifespan lifespan,
+ const DDFlag& flags)
+{
+ // sync_attach_3 vore coolt att skicka över detta
+ // om vi kommer från sync_attach_1
+ return AddLine(start,end,color,color,lifespan,flags);
+}
+
+
+int DebugDraw::AddRibbon(const vec3 &start, const vec3 &end, const vec4 &start_color, const vec4 &end_color, const float start_width, const float end_width, const DDLifespan lifespan, const DDFlag& flags /*= _DD_NO_FLAG*/) {
+ DebugDrawElement* element = new DebugDrawRibbon(start, end, start_color, end_color, start_width, end_width, flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddRibbon(const DDLifespan lifespan, const DDFlag& flags /*= _DD_NO_FLAG*/) {
+ DebugDrawElement* element = new DebugDrawRibbon(flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddPoint( const vec3 &point,
+ const vec4 &color,
+ const DDLifespan lifespan,
+ const DDFlag& flags)
+{
+ DebugDrawElement* element = new DebugDrawPoint(point, color, flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddWireSphere( const vec3 &position,
+ const float radius,
+ const vec4 &color,
+ const DDLifespan lifespan )
+{
+ if(radius == 0.0f){
+ DisplayError("Error", "Creating debug draw sphere with radius zero");
+ }
+ DebugDrawElement* element = new DebugDrawWireSphere(position, radius, vec3(1.0f), color);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddText( const vec3 &position, const std::string &content, const float& scale, const DDLifespan lifespan, const DDFlag& flags, const vec4& color )
+{
+ DebugDrawElement* element = new DebugDrawText(position, scale, content, flags, color);
+ return AddElement(element, lifespan);
+}
+
+bool DebugDraw::SetPosition( int id, const vec3 &position )
+{
+ DebugDrawElement* element = GetElement( id );
+ if( element ) {
+ return element->SetPosition(position);
+ } else {
+ LOGE << "No element with id " << id << std::endl;
+ return false;
+ }
+}
+
+bool DebugDraw::SetVisible(int id, bool visible)
+{
+ DebugDrawElement* element = GetElement( id );
+ if( element ) {
+ element->visible = visible;
+ return true;
+ } else {
+ LOGE << "No element with id " << id << std::endl;
+ return false;
+ }
+}
+
+DebugDrawElement* DebugDraw::GetElement( int id )
+{
+ DebugDrawElementMap::iterator it = elements.find(id);
+
+ if( it != elements.end() ) {
+ return it->second;
+ } else {
+ return NULL;
+ }
+}
+
+int DebugDraw::AddWireBox( const vec3 &position, const vec3 &dimensions, const vec4 &color, const DDLifespan lifespan )
+{
+ DebugDrawElement* element = new DebugDrawWireBox(position,
+ dimensions,
+ color);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddWireCylinder( const vec3 &position, const float radius, const float height, const vec4 &color, const DDLifespan lifespan )
+{
+ DebugDrawElement* element = new DebugDrawWireCylinder(position,
+ radius,
+ height,
+ color);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddWireScaledSphere( const vec3 &position, const float radius, const vec3 &scale, const vec4 &color, const DDLifespan lifespan )
+{
+ DebugDrawElement* element = new DebugDrawWireSphere(position, radius, scale, color);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddWireMesh( const std::string &path, const mat4 &transform, const vec4 &color, const DDLifespan lifespan )
+{
+ RC_VBOContainer vbo;
+ std::vector<vec3> vertices;
+
+ std::map<std::string, RC_VBOContainer>::iterator me_iter = mesh_edges_map.find(path);
+
+ if(me_iter == mesh_edges_map.end())
+ {
+ Model model;
+ model.LoadObj(path, _MDL_SIMPLE);
+ model.RemoveDuplicatedVerts();
+
+
+ for(unsigned i=0; i < (model.faces.size()/3)*3; i +=3)
+ {
+ for( unsigned j=0; j < 3; j++ )
+ {
+ int f = model.faces[i+j];
+ int s = model.faces[i+((j+1)%3)];
+
+ vertices.push_back(vec3(model.vertices[f*3+0],
+ model.vertices[f*3+1],
+ model.vertices[f*3+2]));
+ vertices.push_back(vec3(model.vertices[s*3+0],
+ model.vertices[s*3+1],
+ model.vertices[s*3+2]));
+ }
+ }
+
+ //One of the few cases in this codebase where kVBOStream makes sense
+ //(Creating the buffer, filling it once, reading a couple of times then destroying, as per spec)
+ vbo->Fill( kVBOFloat | kVBOStream, vertices.size() * sizeof(vertices[0]), &vertices[0] );
+
+ mesh_edges_map[path] = vbo;
+ }
+ else
+ {
+ vbo = me_iter->second;
+ }
+
+ DebugDrawElement* element = new DebugDrawWireMesh(vbo, transform, color);
+
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddLineObject(const RC_VBOContainer &vbo,
+ const mat4 &transform,
+ const vec4 &color,
+ const DDLifespan lifespan)
+{
+ DebugDrawElement* element = new DebugDrawWire( vbo, transform, color, _DD_NO_FLAG );
+ return AddElement(element,lifespan);
+}
+
+int DebugDraw::AddStippleMesh(const RC_VBOContainer &vbo,
+ const mat4 &transform,
+ const vec4 &color,
+ const DDLifespan lifespan)
+{
+ DebugDrawElement* element = new DebugDrawStippleMesh(vbo, transform, color, _DD_NO_FLAG);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddLines( const std::vector<float> &vertices, const std::vector<unsigned> &indices, const vec4 &color, const DDLifespan lifespan, const DDFlag& flags ) {
+ DebugDrawElement* element = new DebugDrawLines(vertices, indices, color, flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddLines( const std::vector<vec3> &vertices, const vec4 &color, const DDLifespan lifespan, const DDFlag& flags ) {
+ DebugDrawElement* element = new DebugDrawLines(vertices, color, flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddCircle( const mat4 &transform, const vec4 &color, const DDLifespan lifespan, const DDFlag& flags ) {
+ DebugDrawElement* element = new DebugDrawCircle(transform, color, flags);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddBillboard(const TextureRef &ref, const vec3 &position, float scale, const vec4& color, AlphaMode mode, const DDLifespan lifespan) {
+ DebugDrawElement* element = new DebugDrawBillboard(ref, position, scale, color, mode);
+ return AddElement(element, lifespan);
+}
+
+int DebugDraw::AddTransformedWireScaledSphere( const mat4 &transform, const vec4 &color, const DDLifespan lifespan ) {
+
+ DebugDrawWireSphere* element = new DebugDrawWireSphere(transform, color);
+ return AddElement((DebugDrawElement*)element, lifespan);
+}
+
+DebugDrawLine::DebugDrawLine(
+ const vec3 &start,
+ const vec3 &end,
+ const vec4 &start_color,
+ const vec4 &end_color,
+ const DDFlag& _flags ) :
+DebugDrawWire((DDFlag)(_flags | _DD_COLOR))
+{
+
+ if( _flags & _DD_DASHED )
+ {
+ const float segment_length = 0.2f;
+ std::vector<GLfloat> line_data;
+
+ vec3 diff = end - start;
+ vec3 dir = normalize(diff);
+ float len2 = length_squared(diff);
+
+ vec3 cur = start;
+ while( length_squared((cur+dir*segment_length)-start) < len2 )
+ {
+ vec4 mix_color = lerp(start_color, end_color, (len2-length_squared(cur-start))/len2);
+ line_data.push_back(cur[0]);
+ line_data.push_back(cur[1]);
+ line_data.push_back(cur[2]);
+ line_data.push_back(mix_color[0]);
+ line_data.push_back(mix_color[1]);
+ line_data.push_back(mix_color[2]);
+ line_data.push_back(mix_color[3]);
+
+ vec3 next = cur+dir*segment_length;
+ line_data.push_back(next[0]);
+ line_data.push_back(next[1]);
+ line_data.push_back(next[2]);
+ line_data.push_back(mix_color[0]);
+ line_data.push_back(mix_color[1]);
+ line_data.push_back(mix_color[2]);
+ line_data.push_back(mix_color[3]);
+
+ cur = cur+dir*segment_length*2.0f;
+ }
+
+ if( length_squared(cur-start) < length_squared(end-start) )
+ {
+ line_data.push_back(cur[0]);
+ line_data.push_back(cur[1]);
+ line_data.push_back(cur[2]);
+
+ line_data.push_back(end_color[0]);
+ line_data.push_back(end_color[1]);
+ line_data.push_back(end_color[2]);
+ line_data.push_back(end_color[3]);
+
+ line_data.push_back(end[0]);
+ line_data.push_back(end[1]);
+ line_data.push_back(end[2]);
+
+ line_data.push_back(end_color[0]);
+ line_data.push_back(end_color[1]);
+ line_data.push_back(end_color[2]);
+ line_data.push_back(end_color[3]);
+ }
+
+ vbo->Fill(kVBODynamic | kVBOFloat, sizeof(GLfloat)*line_data.size(), &line_data[0]);
+ }
+ else
+ {
+ GLfloat data[] = {
+ start[0], start[1], start[2],
+ start_color[0], start_color[1], start_color[2], start_color[3],
+ end[0], end[1], end[2],
+ end_color[0], end_color[1], end_color[2], end_color[3]
+ };
+
+ vbo->Fill(kVBODynamic | kVBOFloat, sizeof(data), data);
+ }
+ type = kLine;
+}
+
+DebugDrawLines::DebugDrawLines(
+const std::vector<float> &vertices,
+const std::vector<unsigned> &indices,
+const vec4 &_color,
+const DDFlag& _flags):
+DebugDrawWire(_color, _flags)
+{
+ std::vector<vec3> data;
+ data.reserve( indices.size() );
+
+ for( unsigned i = 0; i < indices.size(); i++ )
+ {
+ data.push_back( vec3(
+ vertices[i*3+0],
+ vertices[i*3+1],
+ vertices[i*3+2]));
+ }
+
+ vbo->Fill(kVBOFloat | kVBOStatic, data.size() * sizeof(data[0]), &data[0]);
+ type = kLines;
+}
+
+DebugDrawLines::DebugDrawLines(
+const std::vector<vec3> &vertices,
+const vec4 &_color,
+const DDFlag& _flags):
+DebugDrawWire(_color, _flags)
+{
+ vbo->Fill(kVBOFloat | kVBOStatic, vertices.size() * sizeof(vertices[0]), (void*)&vertices[0]);
+ type = kLines;
+}
+
+void DebugDrawWire::DecreaseOpacity( float how_much )
+{
+ opacity -= how_much;
+ if( opacity < 0.0f ) opacity = 0.0f;
+}
+
+bool DebugDrawWire::IsInvisible()
+{
+ return opacity<=0;
+}
+
+DDLifespan LifespanFromInt(int lifespan_int) {
+ DDLifespan lifespan;
+ switch(lifespan_int){
+ case _delete_on_draw:
+ lifespan = _delete_on_draw;
+ break;
+ case _delete_on_update:
+ lifespan = _delete_on_update;
+ break;
+ case _persistent:
+ lifespan = _persistent;
+ break;
+ case _fade:
+ lifespan = _fade;
+ break;
+ default:
+ std::ostringstream os;
+ os << "Invalid lifespan int: " << lifespan_int;
+ DisplayError("Error", os.str().c_str());
+ return _delete_on_update;
+ }
+ return lifespan;
+}
+
+RC_VBOContainer DebugDrawWireCylinder::wire_cylinder_vbo;
+
+DebugDrawWireCylinder::DebugDrawWireCylinder( const vec3 &_position,
+ const float _radius,
+ const float _height,
+ const vec4 &_color ):
+ DebugDrawWire(_color, _DD_NO_FLAG)
+{
+ transform.AddTranslation( _position );
+ transform.AddRotation(vec3(0,0,0));
+
+ mat4 scaleMatrix( 1.0f );
+ scaleMatrix.SetScale( vec3( _radius, _height, _radius ) );
+
+ transform *= scaleMatrix;
+
+ if(!wire_cylinder_vbo->valid()){
+ //TODO: fix cleanup by correct referencecounting.
+ std::vector<vec3> vert_array;
+ GetWireCylinderVertArray(12,vert_array);
+ wire_cylinder_vbo->Fill(kVBOFloat | kVBOStatic, vert_array.size() * sizeof(vert_array[0]), &vert_array[0]);
+ }
+
+ vbo = wire_cylinder_vbo;
+ type = kWireCylinder;
+}
+
+DebugDrawWireCylinder::~DebugDrawWireCylinder()
+{
+}
+
+RC_VBOContainer DebugDrawWireSphere::wire_sphere_vbo;
+
+DebugDrawWireSphere::DebugDrawWireSphere( const vec3 &_position,
+ const float _radius,
+ const vec3 &_scale,
+ const vec4 &_color ):
+ DebugDrawWire(_color, _DD_NO_FLAG)
+{
+ if(!wire_sphere_vbo->valid()){
+ std::vector<float> vert_array;
+ GetWireSphereVertArray(1.0f,12,12,vert_array);
+ wire_sphere_vbo->Fill(kVBOFloat | kVBOStatic, vert_array.size() * sizeof(vert_array[0]), &vert_array[0]);
+ }
+ vbo = wire_sphere_vbo;
+
+ transform.AddTranslation( _position );
+ transform.AddRotation(vec3(PI_f/2.0f,0,0));
+ vec3 swizzle_scale = _scale;
+ std::swap(swizzle_scale[2], swizzle_scale[1]);
+
+
+ mat4 scaleMatrix( 1.0f );
+ scaleMatrix.SetScale( swizzle_scale * _radius );
+ transform *= scaleMatrix;
+ type = kWireSphere;
+}
+
+
+DebugDrawWireSphere::DebugDrawWireSphere(const mat4 _transform,
+ const vec4 &_color ):
+ DebugDrawWire(_transform, _color, _DD_NO_FLAG)
+{
+ if(!wire_sphere_vbo->valid()){
+ std::vector<float> vert_array;
+ GetWireSphereVertArray(1.0f,12,12,vert_array);
+ wire_sphere_vbo->Fill(kVBOFloat | kVBOStatic, vert_array.size() * sizeof(vert_array[0]), &vert_array[0]);
+ }
+ vbo = wire_sphere_vbo;
+ type = kWireSphere;
+}
+
+DebugDrawWireSphere::~DebugDrawWireSphere() {
+}
+
+RC_VBOContainer DebugDrawText::vbo;
+
+DebugDrawText::DebugDrawText( const vec3 &_position,
+ const float &_scale,
+ const std::string &_content,
+ const DDFlag& _flags,
+ const vec4& _color ):
+ DebugDrawElement(_flags),
+ scale(_scale),
+ color(_color)
+{
+ if( !vbo->valid())
+ {
+ const float origo[] = {
+ 0.0f,0.0f,0.0f,
+ };
+
+ vbo->Fill(kVBOFloat | kVBOStatic, sizeof(origo), (void*)&origo[0]);
+ }
+
+ transform = mat4(1.0f);
+ transform.SetTranslation( _position );
+
+ FormatString(text, kBufSize, "%s", _content.c_str());
+ type = kText;
+}
+
+DebugDrawText::~DebugDrawText()
+{
+}
+
+bool DebugDrawText::SetPosition(const vec3& position)
+{
+ transform = mat4(1.0f);
+ transform.SetTranslation( position );
+ return true;
+}
+
+void DebugDrawText::Draw()
+{
+ PROFILER_GPU_ZONE(g_profiler_ctx, "DebugDrawText::Draw()");
+ vec3 screen_point = ActiveCameras::Get()->worldToScreen(transform.GetTranslationPart());
+ if(screen_point[2] < 1.0){
+ int pos[] = {(int)screen_point[0], (int)(Graphics::Instance()->window_dims[1] - screen_point[1])};
+ g_text_atlas_renderer.num_characters = 0;
+ CHECK_GL_ERROR();
+ FontRenderer* font_renderer = FontRenderer::Instance();
+ TextMetrics metrics = g_text_atlas_renderer.GetMetrics(
+ &g_text_atlas[kTextAtlasMono],
+ text,
+ font_renderer,
+ 512);
+ pos[0] -= metrics.bounds[2] / 2;
+ g_text_atlas_renderer.AddText(
+ &g_text_atlas[kTextAtlasMono],
+ text,
+ pos, font_renderer,
+ 512);
+ CHECK_GL_ERROR();
+ vec4 gamma_corrected_color = vec4(powf(color.r(), 2.2f), powf(color.g(), 2.2f), powf(color.b(), 2.2f), color.a());
+ g_text_atlas_renderer.Draw(&g_text_atlas[kTextAtlasMono], Graphics::Instance(), TextAtlasRenderer::kTextShadow, gamma_corrected_color);
+ Textures::Instance()->InvalidateBindCache();
+ }
+}
+
+DebugDrawElement::DebugDrawElement(const DDFlag& _flags):
+ flags(_flags),
+ fade_amount(0.0f),
+ type(kUndefined),
+ visible(true)
+ {}
+
+DebugDrawElement::~DebugDrawElement( )
+{
+}
+
+bool DebugDrawElement::SetPosition(const vec3 &position)
+{
+ LOGW << "Function not implemented for current DebugDraw element" << std::endl;
+ return false;
+}
+
+DebugDrawWire::DebugDrawWire(
+ const DDFlag& _flags ) :
+DebugDrawElement(_flags),
+transform(1.0f),
+color(vec4(1.0f,0,0,1.0f)),
+opacity(1.0f)
+{
+ type = kWire;
+}
+
+DebugDrawWire::DebugDrawWire(
+ const vec4 &_color,
+ const DDFlag& _flags ) :
+DebugDrawElement(_flags),
+transform(1.0f),
+color(_color),
+opacity(1.0f)
+{
+ type = kWire;
+}
+
+DebugDrawWire::DebugDrawWire(
+ const mat4 &_transform,
+ const vec4 &_color,
+ const DDFlag& _flags ) :
+DebugDrawElement( _flags ),
+transform(_transform),
+color(_color),
+opacity(1.0f)
+{
+ type = kWire;
+}
+
+DebugDrawWire::DebugDrawWire(
+ const RC_VBOContainer& _vbo,
+ const mat4 &_transform,
+ const vec4 &_color,
+ const DDFlag& _flags):
+DebugDrawElement( _flags ),
+vbo(_vbo),
+transform(_transform),
+color(_color),
+opacity(1.0f)
+{
+ type = kWire;
+}
+
+RC_VBOContainer DebugDrawWireBox::wire_box_vbo;
+
+DebugDrawWireBox::DebugDrawWireBox( const vec3 &pos,
+ const vec3 &dim,
+ const vec4 &color ):
+ DebugDrawWire(color, _DD_NO_FLAG)
+{
+ transform.AddTranslation( pos );
+
+ mat4 scaleMatrix( 1.0f );
+ scaleMatrix.SetScale( dim );
+ transform *= scaleMatrix;
+
+ if( !wire_box_vbo->valid() )
+ {
+ //TODO: fix cleanup by correct referencecounting.
+ std::vector<vec3> vert_array;
+ GetWireBoxVertArray(vert_array);
+ wire_box_vbo->Fill(kVBOFloat | kVBOStatic, vert_array.size() * sizeof(vert_array[0]), &vert_array[0]);
+ }
+ vbo = wire_box_vbo;
+ type = kWireBox;
+}
+
+RC_VBOContainer DebugDrawPoint::vbo;
+
+DebugDrawPoint::DebugDrawPoint( const vec3 &_point,
+ const vec4 &_color,
+ const DDFlag& _flags ):
+ DebugDrawElement(_flags),
+ color(_color)
+{
+ if( !vbo->valid() )
+ {
+ vec3 origin(0.0f);
+ vbo->Fill( kVBOFloat | kVBOStatic, sizeof(origin), (void*)&origin );
+ }
+ transform.SetTranslation( _point );
+ type = kPoint;
+}
+
+void DebugDrawPoint::Draw()
+{
+ Graphics* graphics = Graphics::Instance();
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+
+ graphics->SetLineWidth(2);
+
+ int shader_id = shaders->returnProgram("3d_color #COLOR_UNIFORM #NO_VELOCITY_BUF");
+ shaders->setProgram(shader_id);
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix() * transform );
+ shaders->SetUniformVec4("color_uniform", color);
+ shaders->SetUniformFloat("opacity", (1.0f-fade_amount) );
+
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+
+ vbo->Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, sizeof(float) * 3, (const void*)0);
+
+ graphics->DrawArrays( GL_POINTS, 0, vbo->size()/sizeof(float)/3 );
+
+ graphics->ResetVertexAttribArrays();
+}
+
+void DebugDrawAux::Update(float timestep) {
+}
+
+DebugDrawWireMesh::DebugDrawWireMesh( const RC_VBOContainer& _vbo, const mat4 &_transform, const vec4 &_color ):
+DebugDrawWire( _vbo, _transform, _color, _DD_NO_FLAG )
+{
+ type = kWireMesh;
+}
+
+DebugDrawWireMesh::~DebugDrawWireMesh() {
+}
+
+RC_VBOContainer DebugDrawCircle::circle_vert_vbo;
+
+DebugDrawCircle::DebugDrawCircle(
+ const mat4 &_transform,
+ const vec4 &_color,
+ const DDFlag& _flags ):
+DebugDrawWire( _transform, _color, _flags )
+{
+ static const unsigned numLines = 50;
+ if(!circle_vert_vbo->valid()){
+ std::vector<vec3> circle_verts;
+ for(unsigned i=0; i<numLines; ++i){
+ float angle = (float)i/(float)(numLines) * PI_f * 2.0f;
+ float angle2 = (float)(i+1)/(float)(numLines) * PI_f * 2.0f;
+
+ circle_verts.push_back(vec3(
+ sinf(angle),
+ cosf(angle),
+ 0.0f));
+
+ circle_verts.push_back(vec3(
+ sinf(angle2),
+ cosf(angle2),
+ 0.0f));
+ }
+ circle_vert_vbo->Fill(kVBOFloat | kVBOStatic, sizeof(circle_verts[0]) * circle_verts.size(), (void*)&circle_verts[0]);
+ }
+
+ vbo = circle_vert_vbo;
+ type = kCircle;
+}
+
+DebugDrawBillboard::DebugDrawBillboard(const TextureRef& ref, const vec3 &position, float scale, const vec4& color, AlphaMode mode)
+:DebugDrawElement(_DD_NO_FLAG) {
+ ref_ = ref;
+ position_ = position;
+ scale_ = scale;
+ mode_ = mode;
+ color_ = color;
+ type = kBillboard;
+}
+
+bool DebugDrawBillboard::SetPosition(const vec3 &position) {
+ position_ = position;
+ return true;
+}
+
+void DebugDrawBillboard::SetScale(float scale) {
+ scale_ = scale;
+}
+
+void DebugDrawBillboard::Draw() {
+ DrawBillboard(ref_, position_, scale_, color_, mode_);
+ Graphics::Instance()->setBlend(true);
+}
+
+void DebugDrawWire::Draw()
+{
+ Graphics* graphics = Graphics::Instance();
+
+ if((flags & _DD_XRAY) == _DD_XRAY )
+ {
+ graphics->setDepthTest(false);
+ }
+
+ if((flags & _DD_COLOR) == _DD_COLOR )
+ {
+ DrawVertColor();
+ }
+ else
+ {
+ DrawVert();
+ }
+
+ if((flags & _DD_XRAY) == _DD_XRAY )
+ {
+ graphics->setDepthTest(true);
+ }
+}
+
+void DebugDrawWire::DrawVert()
+{
+ Graphics* graphics = Graphics::Instance();
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+
+ graphics->SetLineWidth(1);
+
+ int shader_id = shaders->returnProgram("3d_color #COLOR_UNIFORM #NO_VELOCITY_BUF");
+ shaders->setProgram(shader_id);
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix() * transform );
+ shaders->SetUniformVec4("color_uniform", color);
+ shaders->SetUniformFloat("opacity", opacity * (1.0f-fade_amount) );
+
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+
+ vbo->Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, sizeof(float) * 3, (const void*)0);
+
+ graphics->DrawArrays( GL_LINES, 0, vbo->size()/sizeof(float)/3 );
+
+ graphics->ResetVertexAttribArrays();
+}
+
+void DebugDrawWire::DrawVertColor()
+{
+ Graphics* graphics = Graphics::Instance();
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+
+ graphics->SetLineWidth(1);
+
+ int shader_id = shaders->returnProgram("3d_color #COLOR_ATTRIB #NO_VELOCITY_BUF");
+ shaders->setProgram(shader_id);
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+ int color_attrib_id = shaders->returnShaderAttrib("color_attrib", shader_id);
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix() * transform );
+ shaders->SetUniformFloat("opacity", opacity * (1.0f-fade_amount));
+
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+ graphics->EnableVertexAttribArray(color_attrib_id);
+
+ vbo->Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, sizeof(float) * 7, (const void*)0);
+ glVertexAttribPointer(color_attrib_id, 4, GL_FLOAT, false, sizeof(float) * 7, (const void*)(sizeof(float)*3));
+
+ graphics->DrawArrays( GL_LINES, 0, vbo->size()/sizeof(float)/7 );
+
+ graphics->ResetVertexAttribArrays();
+}
+
+DebugDrawStippleMesh::DebugDrawStippleMesh(const RC_VBOContainer& _vbo,
+ const mat4 &_transform,
+ const vec4 &_color,
+ const DDFlag& _flags):
+DebugDrawElement(_DD_NO_FLAG),
+vbo(_vbo),
+transform(_transform),
+color(_color)
+{
+ type = kStippleMesh;
+}
+
+void DebugDrawStippleMesh::Draw()
+{
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+ Graphics* graphics = Graphics::Instance();
+
+ int shader_id = shaders->returnProgram("debug_fill #STIPPLING #NO_VELOCITY_BUF");
+ shaders->setProgram(shader_id);
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix() * transform);
+ shaders->SetUniformVec3("close_stipple_color", vec3(0.1f, 0.8f, 1.0f));
+ shaders->SetUniformVec3("far_stipple_color", vec3(0.25f, 0.29f, 0.3f));
+ shaders->SetUniformVec3("camera_forward", cam->GetFacing());
+ shaders->SetUniformVec3("camera_position", cam->GetPos());
+
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+ vbo->Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, 0, 0);
+
+ graphics->DrawArrays(GL_TRIANGLES, 0, vbo->size() / (sizeof(float)*3));
+
+ graphics->ResetVertexAttribArrays();
+}
+
+void DebugDrawRibbon::Draw() {
+ if (g_debug_runtime_disable_debug_ribbon_draw) {
+ return;
+ }
+
+ PROFILER_GPU_ZONE(g_profiler_ctx, "DebugDrawRibbon::Draw()");
+ if(ribbon_points.size() < 2){
+ return;
+ }
+
+ Graphics* graphics = Graphics::Instance();
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+
+ int shader_id = shaders->returnProgram("3d_color #COLOR_ATTRIB #FIRE");
+ shaders->setProgram(shader_id);
+
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix());
+
+ std::vector<vec3> right;
+ right.resize(ribbon_points.size()-1);
+ for(int i=0, len=ribbon_points.size()-1; i<len; ++i) {
+ vec3 vec = ribbon_points[i+1].pos - ribbon_points[i].pos;
+ right[i] = normalize(cross(cam->GetFacing(), vec));
+ }
+
+ std::vector<GLfloat> data;
+ data.resize(7*ribbon_points.size()*2);
+ int index = 0;
+ for(int i=0, len=ribbon_points.size(); i<len; ++i) {
+ vec3 temp_right;
+ if(i==0) {
+ temp_right = right[i];
+ } else if(i==len-1){
+ temp_right = right[i-1];
+ } else {
+ temp_right = normalize(right[i] + right[i-1]);
+ }
+ ribbon_points[i].color[3] = 0.0f;
+ for(int j=0; j<4; ++j){
+ data[index++] = ribbon_points[i].color[j];
+ }
+ for(int j=0; j<3; ++j){
+ data[index++] = ribbon_points[i].pos[j] + temp_right[j] * ribbon_points[i].width;
+ }
+ ribbon_points[i].color[3] = 1.0f;
+ for(int j=0; j<4; ++j){
+ data[index++] = ribbon_points[i].color[j];
+ }
+ for(int j=0; j<3; ++j){
+ data[index++] = ribbon_points[i].pos[j] - temp_right[j] * ribbon_points[i].width;
+ }
+ }
+
+ vec2 viewport_dims;
+ for(int i=0; i<2; ++i){
+ viewport_dims[i] = (float)Graphics::Instance()->viewport_dim[i+2];
+ }
+ shaders->SetUniformVec2("viewport_dims",viewport_dims);
+ shaders->SetUniformVec3("cam_pos",cam->GetPos());
+ shaders->SetUniformFloat("time",game_timer.GetRenderTime());
+ Textures::Instance()->bindTexture(Graphics::Instance()->screen_depth_tex, 5);
+
+ static VBORingContainer data_vbo(V_MIBIBYTE, kVBODynamic | kVBOFloat);
+ data_vbo.Fill(data.size() * sizeof(GLfloat), &data[0]);
+ data_vbo.Bind();
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+ int color_attrib_id = shaders->returnShaderAttrib("color_attrib", shader_id);
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+ graphics->EnableVertexAttribArray(color_attrib_id);
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, 7*sizeof(GLfloat), (const void*)(data_vbo.offset() + sizeof(GLfloat) * 4));
+ glVertexAttribPointer(color_attrib_id, 4, GL_FLOAT, false, 7*sizeof(GLfloat), (const void*)data_vbo.offset());
+ Graphics::Instance()->DrawArrays(GL_TRIANGLE_STRIP, 0, ribbon_points.size()*2);
+ graphics->ResetVertexAttribArrays();
+
+ /*glEnableVertexAttribArray(vert_attrib_id);
+ vbo->Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, 0, 0);
+
+ glDrawArrays(GL_TRIANGLES, 0, vbo->size() / (sizeof(float)*3));
+
+ glDisableVertexAttribArray(vert_attrib_id);*/
+}
+
+DebugDrawRibbon::DebugDrawRibbon(const vec3 &start, const vec3 &end, const vec4 &start_color, const vec4 &end_color, const float start_width, const float end_width, const DDFlag& flags)
+ :DebugDrawElement(flags)
+{
+ ribbon_points.resize(2);
+ ribbon_points[0].pos = start;
+ ribbon_points[1].pos = end;
+ ribbon_points[0].color = start_color;
+ ribbon_points[1].color = end_color;
+ ribbon_points[0].width = start_width;
+ ribbon_points[1].width = end_width;
+ type = kRibbon;
+}
+
+DebugDrawRibbon::DebugDrawRibbon(const DDFlag& flags)
+ :DebugDrawElement(flags)
+{
+ type = kRibbon;
+}
+
+void DebugDrawRibbon::AddPoint(const vec3 &pos, const vec4 &color, float width) {
+ RibbonPoint point;
+ point.pos = pos;
+ point.color = color;
+ point.width = width;
+ ribbon_points.push_back(point);
+}
+
+void TempLines::Draw() {
+ PROFILER_GPU_ZONE(g_profiler_ctx, "Draw TempLines");
+ if(!verts.empty()){
+ vbo.Fill(verts.size() * sizeof(verts[0]), &verts[0]);
+
+ Graphics* graphics = Graphics::Instance();
+ Shaders* shaders = Shaders::Instance();
+ Camera* cam = ActiveCameras::Get();
+
+ graphics->SetLineWidth(1);
+
+ int shader_id = shaders->returnProgram("3d_color #COLOR_ATTRIB #NO_VELOCITY_BUF");
+ shaders->setProgram(shader_id);
+ int vert_attrib_id = shaders->returnShaderAttrib("vert_attrib", shader_id);
+ int color_attrib_id = shaders->returnShaderAttrib("color_attrib", shader_id);
+ shaders->SetUniformMat4("mvp", cam->GetProjMatrix() * cam->GetViewMatrix() );
+ shaders->SetUniformFloat("opacity", 1.0f);
+
+ graphics->EnableVertexAttribArray(vert_attrib_id);
+ graphics->EnableVertexAttribArray(color_attrib_id);
+
+ vbo.Bind();
+ glVertexAttribPointer(vert_attrib_id, 3, GL_FLOAT, false, sizeof(float) * 7, (const void*)(vbo.offset()));
+ glVertexAttribPointer(color_attrib_id, 4, GL_FLOAT, false, sizeof(float) * 7, (const void*)(vbo.offset()+sizeof(float)*3));
+
+ graphics->DrawArrays( GL_LINES, 0, vbo.size()/sizeof(float)/7 );
+
+ graphics->ResetVertexAttribArrays();
+ }
+}