From c7c4be2b13bf7d5bad40b0abd5f85c503c905580 Mon Sep 17 00:00:00 2001 From: Andrew Richards Date: Wed, 18 Sep 2024 11:15:04 +0100 Subject: [PATCH] Updated RenderPlatform::DrawCircle() Overload for taking doubles and parameter switch for view centred to stop floating-point error causing jagged circles. --- CrossPlatform/RenderPlatform.cpp | 61 +++++++++++++++++++++++--------- CrossPlatform/RenderPlatform.h | 8 +++-- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/CrossPlatform/RenderPlatform.cpp b/CrossPlatform/RenderPlatform.cpp index 731c5ed5..75c67574 100644 --- a/CrossPlatform/RenderPlatform.cpp +++ b/CrossPlatform/RenderPlatform.cpp @@ -1237,25 +1237,29 @@ void RenderPlatform::DrawLines(GraphicsDeviceContext &deviceContext,PosColourVer posColourLayout->Unapply(deviceContext); } - -static float length(const vec3 &u) -{ - float size=u.x*u.x+u.y*u.y+u.z*u.z; - return sqrt(size); -} -void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float *dir,float rads,const float *colr,bool fill) +void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float *dir,float rads,const float *colr,bool fill,bool view_centred) { - vec3 pos=GetCameraPosVector(deviceContext.viewStruct.view); + vec3 pos = view_centred ? vec3d(0, 0, 0) : GetCameraPosVector(deviceContext.viewStruct.view); vec3 d=dir; d/=length(d); pos += 1.5f * d; float radius = 1.5f * rads; - DrawCircle(deviceContext,pos,dir,radius,colr,fill); + DrawCircle(deviceContext,pos,dir,radius,colr,fill,view_centred); +} + +void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const double *dir,double rads,const float *colr,bool fill,bool view_centred) +{ + vec3d pos = view_centred ? vec3d(0,0,0) : GetCameraPosVector(deviceContext.viewStruct.view); + vec3d d=dir; + d/=length(d); + pos += 1.5 * d; + double radius = 1.5 * rads; + DrawCircle(deviceContext,pos,dir,radius,colr,fill,view_centred); } -void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float *pos,const float *dir,float radius,const float *colr,bool fill) +void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float *pos,const float *dir,float radius,const float *colr,bool fill,bool view_centred) { - PosColourVertex line_vertices[37]; + PosColourVertex line_vertices[36]; vec3 direction(dir); direction = normalize(direction); vec3 z(0,0,1.f); @@ -1268,14 +1272,39 @@ void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext,const float x*=radius; y = cross(direction , x); int l=0; - for(int j=0;j<36;j++) + for(int j=0;j<_countof(line_vertices);j++) { - float angle =(float(j)/35.0f)*2.0f*3.1415926536f; - math::Vector3 p = math::Vector3((x * cos(angle) + y * sin(angle))); - line_vertices[l].pos =vec3(pos)+vec3((const float*)&p); + float angle =(float(j)/float(_countof(line_vertices)-1))*2.0f*3.1415926536f; + vec3 p =vec3((x * cos(angle) + y * sin(angle))); + line_vertices[l].pos =vec3(pos)+p; line_vertices[l++].colour =colr; } - DrawLines(deviceContext,line_vertices,36,true,false,false); + DrawLines(deviceContext, line_vertices, _countof(line_vertices), true, false, view_centred); +} + +void RenderPlatform::DrawCircle(GraphicsDeviceContext &deviceContext, const double *pos, const double *dir, double radius, const float *colr, bool fill, bool view_centred) +{ + PosColourVertex line_vertices[36]; + vec3d direction(dir); + direction = normalize(direction); + vec3d z(0, 0, 1.0); + vec3d y(0, 1.0, 0); + vec3d x = cross(z, direction); + if (length(x) > 0.1) + x = normalize(x); + else + x = cross(direction, y); + x *= radius; + y = cross(direction, x); + int l = 0; + for (int j = 0; j < _countof(line_vertices); j++) + { + double angle = (double(j) / float(_countof(line_vertices) - 1)) * 2.0 * 3.1415926536; + vec3d p = vec3d((x * cos(angle) + y * sin(angle))); + line_vertices[l].pos = vec3(vec3d(pos) + p); + line_vertices[l++].colour = colr; + } + DrawLines(deviceContext, line_vertices, _countof(line_vertices), true, false, view_centred); } void RenderPlatform::SetModelMatrix(GraphicsDeviceContext &deviceContext, const double *m, const crossplatform::PhysicalLightRenderData &physicalLightRenderData) diff --git a/CrossPlatform/RenderPlatform.h b/CrossPlatform/RenderPlatform.h index 62c66468..895d615f 100644 --- a/CrossPlatform/RenderPlatform.h +++ b/CrossPlatform/RenderPlatform.h @@ -321,9 +321,13 @@ namespace platform void Draw2dLine (GraphicsDeviceContext &deviceContext,vec2 pos1,vec2 pos2,vec4 colour); virtual void Draw2dLines (GraphicsDeviceContext &/*deviceContext*/,PosColourVertex * /*lines*/,int /*vertex_count*/,bool /*strip*/){} /// Draw a circle facing the viewer at the specified direction and angular size. - virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const float *dir,float rads,const float *colr,bool fill=false); + virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const float *dir,float rads,const float *colr,bool fill=false,bool view_centred=false); + /// Draw a circle facing the viewer at the specified direction and angular size. + virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const double *dir,double rads,const float *colr,bool fill=false,bool view_centred=false); + /// Draw a circle in 3D space at pos + virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const float *pos,const float *dir,float radius,const float *colr,bool fill=false,bool view_centred=false); /// Draw a circle in 3D space at pos - virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const float *pos,const float *dir,float radius,const float *colr,bool fill=false); + virtual void DrawCircle (GraphicsDeviceContext &deviceContext,const double *pos,const double *dir,double radius,const float *colr,bool fill=false,bool view_centred=false); /// Draw a cubemap as a sphere at the specified screen position and size. virtual void DrawCubemap (GraphicsDeviceContext &deviceContext,Texture *cubemap,int x,int y,int pixelSize,float exposure,float gamma,float displayMip=0.0f); virtual void DrawCubemap (GraphicsDeviceContext &deviceContext,Texture *cubemap,float offsetx,float offsety,float size,float exposure,float gamma,float displayMip=0.0f);