00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "r_local.h"
00027 #include "r_sphere.h"
00028 #include "r_error.h"
00029
00030 static cvar_t *r_sphereDetails;
00031
00032 sphere_t r_globeEarth;
00033 sphere_t r_globeMoon;
00034 sphere_t r_globeEarthAtmosphere;
00035
00036 static inline float rhoSpiral (const int index, const float deltaRho,const float thetaAngle)
00037 {
00038 const float rhoAngle = (index == 0) ? 0.0f : (float) ((index - 1) * deltaRho + thetaAngle * deltaRho / (2.0f * M_PI));
00039 return rhoAngle > M_PI ? M_PI : rhoAngle;
00040 }
00041
00050 void R_SphereGenerate (sphere_t *sphere, const int tris, const float radius)
00051 {
00052 const float drho = M_PI / tris;
00053
00054
00055 const float dtheta = 2.0f * M_PI / tris;
00057 int i, j;
00058
00059 int vertspos = 0;
00060 int texespos = 0;
00061
00062 sphere->glslProgram = NULL;
00063
00064 sphere->verts = (float*)Mem_PoolAlloc(sizeof(float) * ((tris + 1) * (tris + 2) * 6), vid_genericPool, 0);
00065 sphere->texes = (float*)Mem_PoolAlloc(sizeof(float) * ((tris + 1) * (tris + 2) * 4), vid_genericPool, 0);
00066 sphere->normals = (float*)Mem_PoolAlloc(sizeof(float) * ((tris + 1) * (tris + 2) * 6), vid_genericPool, 0);
00067
00068
00069 for (i = 0; i <= tris; i++) {
00070
00071 for (j = 0; j <= tris ; j++) {
00072 const float theta = j * dtheta;
00073 const float stheta = (float) (-sin(theta));
00074 const float ctheta = (float) (cos(theta));
00075
00076
00077 const float rho = rhoSpiral(i, drho, theta);
00078 const float rhodrho = rhoSpiral(i + 1, drho, theta);
00079 const float srho = (float) (sin(rho));
00080 const float crho = (float) (cos(rho));
00081 const float srhodrho = (float) (sin(rhodrho));
00082 const float crhodrho = (float) (cos(rhodrho));
00083
00084 const float st = 1 - rho / M_PI;
00085 const float stdt = 1 - rhodrho / M_PI;
00086
00087 const float s = theta / (4.0f * M_PI);
00088
00089 Vector2Set((&sphere->texes[texespos]), s, stdt);
00090 texespos += 2;
00091
00092 VectorSet((&sphere->verts[vertspos]),
00093 stheta * srhodrho * radius,
00094 ctheta * srhodrho * radius,
00095 crhodrho * radius);
00096 VectorNormalize2((&sphere->verts[vertspos]), (&sphere->normals[vertspos]));
00097 vertspos += 3;
00098
00099 Vector2Set((&sphere->texes[texespos]), s, st);
00100 texespos += 2;
00101
00102 VectorSet((&sphere->verts[vertspos]),
00103 stheta * srho * radius,
00104 ctheta * srho * radius,
00105 crho * radius);
00106 VectorNormalize2((&sphere->verts[vertspos]), (&sphere->normals[vertspos]));
00107 vertspos += 3;
00108 }
00109 }
00110 sphere->num_tris = (tris + 1) * (tris + 2) * 2;
00111 }
00112
00120 void R_SphereInit (void)
00121 {
00122 r_sphereDetails = Cvar_Get("r_sphereDetails", "1.0", CVAR_ARCHIVE, "Factor to increase or decrease the sphere tris");
00123 if (r_sphereDetails->integer <= 0)
00124 Cvar_SetValue("r_sphereDetails", 1.0);
00125
00126 R_SphereGenerate(&r_globeEarth, 60 * r_sphereDetails->value, EARTH_RADIUS);
00127 R_SphereGenerate(&r_globeEarthAtmosphere, 60 * r_sphereDetails->value, EARTH_RADIUS * 1.03);
00128
00129 R_SphereGenerate(&r_globeMoon, 20 * r_sphereDetails->value, MOON_RADIUS);
00130 }
00131
00132 static inline void R_SphereActivateTextureUnit (gltexunit_t *texunit, void *texCoordBuffer)
00133 {
00134 R_SelectTexture(texunit);
00135 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, texCoordBuffer);
00136 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00137 }
00138
00139 static inline void R_SphereDeactivateTextureUnit (gltexunit_t *texunit)
00140 {
00141 R_SelectTexture(texunit);
00142 R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
00143 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00144 }
00145
00146 static void R_SphereRenderTris (const sphere_t *sphere)
00147 {
00148 glEnable(GL_CULL_FACE);
00149 glEnable(GL_NORMALIZE);
00150
00151 glDrawArrays(GL_TRIANGLE_STRIP, 0, sphere->num_tris);
00152
00153 glDisable(GL_NORMALIZE);
00154 glDisable(GL_CULL_FACE);
00155 }
00156
00161 static inline qboolean R_SphereCheckGLSL (const sphere_t *sphere)
00162 {
00163 return sphere->glslProgram && qglUseProgram && r_programs->integer;
00164 }
00165
00174 void R_SphereRender (const sphere_t *sphere, const vec3_t pos, const vec3_t rotate, const float scale, const vec4_t lightPos)
00175 {
00176
00177
00178 glPushMatrix();
00179
00180 glMatrixMode(GL_MODELVIEW);
00181 glTranslatef(pos[0], pos[1], pos[2]);
00182
00183
00184 glScalef(scale * viddef.rx, scale * viddef.ry, scale);
00185 R_CheckError();
00186
00187
00188 glRotatef(rotate[YAW], 1, 0, 0);
00189 glRotatef(rotate[ROLL], 0, 1, 0);
00190 glRotatef(rotate[PITCH], 0, 0, 1);
00191
00192 if (lightPos && VectorNotEmpty(lightPos))
00193 glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
00194
00195 R_CheckError();
00196
00197 if (!sphere->overlay && R_SphereCheckGLSL(sphere))
00198 R_SphereShadeGLSL(sphere);
00199 else
00200 R_SphereShade(sphere);
00201
00202
00203 R_CheckError();
00204
00205
00206 glPopMatrix();
00207
00208 refdef.aliasCount += sphere->num_tris * sphere->num_tris;
00209
00210 R_BindDefaultArray(GL_VERTEX_ARRAY);
00211 R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
00212 R_BindDefaultArray(GL_NORMAL_ARRAY);
00213 }
00214
00218 void R_SphereShade (const sphere_t *sphere)
00219 {
00220 if (sphere->overlay)
00221 R_BindTexture(sphere->overlay->texnum);
00222 else
00223 R_BindTexture(sphere->texture->texnum);
00224
00225 if (sphere->overlayAlphaMask) {
00226 R_EnableTexture(&texunit_lightmap, qtrue);
00227 R_SelectTexture(&texunit_lightmap);
00228 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, sphere->texes);
00229 R_BindLightmapTexture(sphere->overlayAlphaMask->texnum);
00230 }
00231
00232 R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, sphere->verts);
00233 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, sphere->texes);
00234 R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, sphere->normals);
00235
00236 glEnableClientState(GL_NORMAL_ARRAY);
00237
00238 R_SphereRenderTris(sphere);
00239
00240 glDisableClientState(GL_NORMAL_ARRAY);
00241
00242 if (sphere->overlayAlphaMask)
00243 R_EnableTexture(&texunit_lightmap, qfalse);
00244 }
00245
00249 void R_SphereShadeGLSL (const sphere_t *sphere)
00250 {
00251 if (Vector4NotEmpty(sphere->nightLightPos))
00252 glLightfv(GL_LIGHT1, GL_POSITION, sphere->nightLightPos);
00253
00254
00255 R_EnableLighting(sphere->glslProgram, qtrue);
00256
00257 R_BindTexture(sphere->texture->texnum);
00258 if (sphere->blendTexture)
00259 R_BindTextureForTexUnit(sphere->blendTexture->texnum, &texunit_1);
00260 if (sphere->normalMap)
00261 R_BindTextureForTexUnit(sphere->normalMap->texnum, &texunit_2);
00262
00263 if (r_lights->integer) {
00264 if (sphere->blendScale >= 0)
00265 R_ProgramParameter1f("BLENDSCALE", sphere->blendScale);
00266 if (r_postprocess->integer && sphere->glowScale >= 0)
00267 R_ProgramParameter1f("GLOWSCALE", sphere->glowScale);
00268 }
00269
00270
00271 R_SphereActivateTextureUnit(&texunit_1, sphere->texes);
00272 R_SphereActivateTextureUnit(&texunit_2, sphere->texes);
00273
00274 R_SelectTexture(&texunit_diffuse);
00275 R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, sphere->verts);
00276 R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, sphere->texes);
00277 R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, sphere->normals);
00278
00279 R_SphereRenderTris(sphere);
00280
00281 R_SphereDeactivateTextureUnit(&texunit_1);
00282 R_SphereDeactivateTextureUnit(&texunit_2);
00283
00284
00285 R_EnableLighting(NULL, qfalse);
00286 R_SelectTexture(&texunit_diffuse);
00287 }
00288