00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "xrb_render.hpp"
00012
00013 #include "xrb_gltexture.hpp"
00014 #include "xrb_math.hpp"
00015
00016 namespace Xrb
00017 {
00018
00019 void Render::DrawLine (
00020 RenderContext const &render_context,
00021 FloatVector2 const &from,
00022 FloatVector2 const &to,
00023 Color const &color)
00024 {
00025 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00026 return;
00027
00028 glMatrixMode(GL_MODELVIEW);
00029 glLoadIdentity();
00030
00031
00032
00033 SetupTextureUnits(
00034 GL::GLTexture_OpaqueWhite().Handle(),
00035 render_context.MaskedColor(color),
00036 render_context.ColorBias());
00037
00038 {
00039 FloatVector2 vertex_array[2] = { from, to };
00040
00041 glEnableClientState(GL_VERTEX_ARRAY);
00042 glVertexPointer(2, GL_FLOAT, 0, vertex_array);
00043 glDrawArrays(GL_LINES, 0, 2);
00044 glDisableClientState(GL_VERTEX_ARRAY);
00045 }
00046 }
00047
00048 void Render::DrawArrow (
00049 RenderContext const &render_context,
00050 FloatVector2 const &from,
00051 FloatVector2 const &to,
00052 Color const &color)
00053 {
00054 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00055 return;
00056
00057
00058 if (to == from)
00059 return;
00060
00061 FloatVector2 basis_x(to - from);
00062 FloatVector2 basis_y(PerpendicularVector2(basis_x));
00063
00064 glMatrixMode(GL_MODELVIEW);
00065 glLoadIdentity();
00066
00067 SetupTextureUnits(
00068 GL::GLTexture_OpaqueWhite().Handle(),
00069 render_context.MaskedColor(color),
00070 render_context.ColorBias());
00071
00072 glEnableClientState(GL_VERTEX_ARRAY);
00073
00074 {
00075 FloatVector2 vertex_array[3] = { from, to, to+0.25f*(basis_y-basis_x) };
00076
00077 glVertexPointer(2, GL_FLOAT, 0, vertex_array);
00078 glDrawArrays(GL_LINE_STRIP, 0, 3);
00079 }
00080
00081 {
00082 FloatVector2 vertex_array[2] = { to-0.25f*(basis_y+basis_x), to };
00083
00084 glVertexPointer(2, GL_FLOAT, 0, vertex_array);
00085 glDrawArrays(GL_LINE_STRIP, 0, 2);
00086 }
00087
00088 glDisableClientState(GL_VERTEX_ARRAY);
00089 }
00090
00091 void Render::DrawPolygon (
00092 RenderContext const &render_context,
00093 FloatVector2 const ¢er,
00094 Float const radius,
00095 Float angle,
00096 Color const &color,
00097 Uint32 const vertex_count)
00098 {
00099
00100 ASSERT1(vertex_count >= 3);
00101
00102 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00103 return;
00104
00105 glMatrixMode(GL_MODELVIEW);
00106 glLoadIdentity();
00107
00108 SetupTextureUnits(
00109 GL::GLTexture_OpaqueWhite().Handle(),
00110 render_context.MaskedColor(color),
00111 render_context.ColorBias());
00112
00113
00114
00115 angle = Math::Radians(angle);
00116
00117
00118 FloatVector2 vertex = center + radius * FloatVector2(cos(angle), sin(angle));
00119 Float const angle_delta = 2.0f * static_cast<Float>(M_PI) / static_cast<Float>(vertex_count);
00120
00121
00122
00123 {
00124 FloatVector2 *vertex_array = new FloatVector2[vertex_count];
00125 for (Uint32 i = 0; i < vertex_count; ++i, angle += angle_delta)
00126 vertex_array[i] = center + radius * FloatVector2(cos(angle), sin(angle));
00127
00128 glEnableClientState(GL_VERTEX_ARRAY);
00129 glVertexPointer(2, GL_FLOAT, 0, vertex_array);
00130 glDrawArrays(GL_LINE_LOOP, 0, vertex_count);
00131 glDisableClientState(GL_VERTEX_ARRAY);
00132
00133 delete[] vertex_array;
00134 }
00135 }
00136
00137 void Render::DrawCircle (
00138 RenderContext const &render_context,
00139 FloatMatrix2 const &transformation,
00140 FloatVector2 const ¢er,
00141 Float const radius,
00142 Color const &color)
00143 {
00144 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00145 return;
00146
00147
00148 Float pixel_radius =
00149 Max((transformation * FloatVector2(radius, 0.0f) -
00150 transformation * FloatVector2::ms_zero).Length(),
00151 (transformation * FloatVector2(0.0f, radius) -
00152 transformation * FloatVector2::ms_zero).Length());
00153
00154 Float const radius_limit_upper = 100.0f;
00155 Float const radius_limit_lower = 2.0f;
00156 Float const tesselation_limit_upper = 30.0f;
00157 Float const tesselation_limit_lower = 6.0f;
00158
00159 Uint32 facet_count;
00160 if (pixel_radius <= radius_limit_lower)
00161 facet_count = static_cast<Uint32>(tesselation_limit_lower);
00162 else if (pixel_radius >= radius_limit_upper)
00163 facet_count = static_cast<Uint32>(tesselation_limit_upper);
00164 else
00165 {
00166 Float x =
00167 (pixel_radius - radius_limit_lower) /
00168 (radius_limit_upper - radius_limit_lower);
00169 facet_count =
00170 static_cast<Uint32>(
00171 tesselation_limit_upper * x +
00172 tesselation_limit_lower * (1.0f - x));
00173 }
00174
00175 ASSERT1(facet_count >= 6);
00176 ASSERT2(facet_count <= 30);
00177
00178 DrawPolygon(render_context, center, radius, 0.0f, color, facet_count);
00179 }
00180
00181 void Render::DrawCircularArc (
00182 RenderContext const &render_context,
00183 FloatMatrix2 const &transformation,
00184 FloatVector2 const ¢er,
00185 Float const radius,
00186 Float start_angle,
00187 Float end_angle,
00188 Color const &color)
00189 {
00190 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00191 return;
00192
00193
00194 if (start_angle == end_angle)
00195 return;
00196
00197
00198
00199 start_angle = Math::Radians(start_angle);
00200 end_angle = Math::Radians(end_angle);
00201
00202
00203 if (start_angle > end_angle)
00204 {
00205 Float temp = start_angle;
00206 start_angle = end_angle;
00207 end_angle = temp;
00208 }
00209 ASSERT1(end_angle > start_angle);
00210
00211
00212 Float pixel_radius =
00213 (transformation * FloatVector2(radius, 0.0f) -
00214 transformation * FloatVector2::ms_zero).Length();
00215
00216 Float arc_portion = (end_angle - start_angle) / (2.0f * static_cast<Float>(M_PI));
00217
00218 Float const radius_limit_upper = 100.0f;
00219 Float const radius_limit_lower = 2.0f;
00220 Float const tesselation_limit_upper = 30.0f;
00221 Float const tesselation_limit_lower = 6.0f;
00222
00223 Uint32 facet_count;
00224 if (pixel_radius <= radius_limit_lower)
00225 facet_count =
00226 static_cast<Uint32>(Math::Ceiling(tesselation_limit_lower * arc_portion));
00227 else if (pixel_radius >= radius_limit_upper)
00228 facet_count =
00229 static_cast<Uint32>(Math::Ceiling(tesselation_limit_upper * arc_portion));
00230 else
00231 {
00232 Float x = (pixel_radius - radius_limit_lower) /
00233 (radius_limit_upper - radius_limit_lower);
00234 facet_count =
00235 static_cast<Uint32>(
00236 Math::Ceiling(arc_portion *
00237 (tesselation_limit_upper * x +
00238 tesselation_limit_lower * (1.0f - x))));
00239 }
00240
00241 if (facet_count < 1)
00242 facet_count = 1;
00243
00244 glMatrixMode(GL_MODELVIEW);
00245 glLoadIdentity();
00246
00247 SetupTextureUnits(
00248 GL::GLTexture_OpaqueWhite().Handle(),
00249 render_context.MaskedColor(color),
00250 render_context.ColorBias());
00251
00252
00253
00254
00255 {
00256 Float const angle_delta = (end_angle - start_angle) / facet_count;
00257 Float angle = start_angle + angle_delta;
00258
00259 FloatVector2 *vertex_array = new FloatVector2[facet_count+1];
00260 for (Uint32 i = 0; i < facet_count; ++i, angle += angle_delta)
00261 vertex_array[i] = center + radius * FloatVector2(cos(angle), sin(angle));
00262
00263 vertex_array[facet_count] = center + radius * FloatVector2(cos(angle), sin(angle));
00264
00265 glEnableClientState(GL_VERTEX_ARRAY);
00266 glVertexPointer(2, GL_FLOAT, 0, vertex_array);
00267 glDrawArrays(GL_LINE_STRIP, 0, facet_count+1);
00268 glDisableClientState(GL_VERTEX_ARRAY);
00269
00270 delete[] vertex_array;
00271 }
00272 }
00273
00274 void Render::DrawScreenRect (
00275 RenderContext const &render_context,
00276 Color const &color,
00277 ScreenCoordRect const &screen_rect)
00278 {
00279 if (render_context.MaskAndBiasWouldResultInNoOp(color[Dim::A]))
00280 return;
00281
00282 glMatrixMode(GL_MODELVIEW);
00283 glLoadIdentity();
00284
00285 SetupTextureUnits(
00286 GL::GLTexture_OpaqueWhite().Handle(),
00287 render_context.MaskedColor(color),
00288 render_context.ColorBias());
00289
00290 {
00291 Sint16 vertex_coordinate_array[8] =
00292 {
00293 screen_rect.BottomLeft()[Dim::X], screen_rect.BottomLeft()[Dim::Y],
00294 screen_rect.BottomRight()[Dim::X], screen_rect.BottomRight()[Dim::Y],
00295 screen_rect.TopLeft()[Dim::X], screen_rect.TopLeft()[Dim::Y],
00296 screen_rect.TopRight()[Dim::X], screen_rect.TopRight()[Dim::Y]
00297 };
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 glEnableClientState(GL_VERTEX_ARRAY);
00309 glVertexPointer(2, GL_SHORT, 0, vertex_coordinate_array);
00310
00311 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00312 glDisableClientState(GL_VERTEX_ARRAY);
00313 }
00314 }
00315
00316 void Render::DrawScreenRectTexture (
00317 RenderContext const &render_context,
00318 GLTexture const *const gl_texture,
00319 ScreenCoordRect const &screen_rect,
00320 FloatSimpleTransform2 const &transformation)
00321 {
00322 if (render_context.MaskAndBiasWouldResultInNoOp())
00323 return;
00324
00325 glMatrixMode(GL_MODELVIEW);
00326 glLoadIdentity();
00327
00328 SetupTextureUnits(
00329 gl_texture->Handle(),
00330 render_context.ColorMask(),
00331 render_context.ColorBias());
00332
00333 {
00334 FloatVector2 texture_coordinate_array[4] =
00335 {
00336 FloatVector2((transformation * FloatVector2(0.0f, 1.0f)).m),
00337 FloatVector2((transformation * FloatVector2(1.0f, 1.0f)).m),
00338 FloatVector2((transformation * FloatVector2(0.0f, 0.0f)).m),
00339 FloatVector2((transformation * FloatVector2(1.0f, 0.0f)).m)
00340 };
00341 Sint16 vertex_coordinate_array[8] =
00342 {
00343 screen_rect.BottomLeft()[Dim::X], screen_rect.BottomLeft()[Dim::Y],
00344 screen_rect.BottomRight()[Dim::X], screen_rect.BottomRight()[Dim::Y],
00345 screen_rect.TopLeft()[Dim::X], screen_rect.TopLeft()[Dim::Y],
00346 screen_rect.TopRight()[Dim::X], screen_rect.TopRight()[Dim::Y]
00347 };
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 glEnableClientState(GL_VERTEX_ARRAY);
00359 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00360
00361 glVertexPointer(2, GL_SHORT, 0, vertex_coordinate_array);
00362
00363 glClientActiveTexture(GL_TEXTURE0);
00364 glTexCoordPointer(2, GL_FLOAT, 0, texture_coordinate_array);
00365 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
00366
00367 glDisableClientState(GL_VERTEX_ARRAY);
00368 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00369 }
00370 }
00371
00372 void Render::SetupTextureUnits (
00373 GLuint gltexture_handle,
00374 Color const &color_mask,
00375 Color const &color_bias)
00376 {
00377
00378 glActiveTexture(GL_TEXTURE0);
00379 glEnable(GL_TEXTURE_2D);
00380 glBindTexture(GL_TEXTURE_2D, gltexture_handle);
00381
00382
00383
00384
00385
00386 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color_bias.m);
00387
00388 glColor4f(color_mask[Dim::R], color_mask[Dim::G], color_mask[Dim::B], color_mask[Dim::A]);
00389
00390
00391
00392
00393
00394
00395 glActiveTexture(GL_TEXTURE1);
00396 glEnable(GL_TEXTURE_2D);
00397
00398 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color_bias.m);
00399
00400 }
00401
00402 }