00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #include <GL/gl.h>
00028
00029 #include <archon/x3d/server/field_type.H>
00030 #include <archon/x3d/server/field.H>
00031 #include <archon/x3d/server/aux.H>
00032
00033 namespace Archon
00034 {
00035 namespace X3D
00036 {
00037 const NodeType *Torus::type = 0;
00038
00039 void initializeAuxComponent()
00040 {
00041 vector<const FieldBase *> fields;
00042
00043
00044
00045 fields.push_back(newPrivateField("majorRadius", SFFloat::type,
00046 &Torus::majorRadius));
00047 fields.push_back(newPrivateField("minorRadius", SFFloat::type,
00048 &Torus::minorRadius));
00049 Torus::type =
00050 NodeType::newConcrete("Torus", "geometry", Torus::instantiate, &fields,
00051 Geometry3DNode::type);
00052 fields.clear();
00053 }
00054
00055 int Torus::intersect(const Math::Ray3 &ray, double &dist) const
00056 {
00057 return Math::intersectTorus(ray, majorRadius, minorRadius, dist) ? 1 : 0;
00058 }
00059
00063 void Torus::getNormalAndTexCoord(Vector3 hitPoint, int where,
00064 const Shape *,
00065 Vector3 *hitNormal,
00066 Vector2 *hitTexCoord) const
00067 {
00068 double a = sqrt(hitPoint[0]*hitPoint[0] + hitPoint[2]*hitPoint[2]);
00069 double b = a - majorRadius;
00070
00071 if(hitTexCoord)
00072 {
00073 hitTexCoord->set(hitPoint[0] == 0 ? hitPoint[2] < 0 ? 0 : 0.5 :
00074 (hitPoint[0] < 0 ? 0.25 : 0.75) -
00075 atan(hitPoint[2]/hitPoint[0]) / (2 * M_PI),
00076 hitPoint[1] == 0 ? b < 0 ? 0 : 0.5 :
00077 (hitPoint[1] < 0 ? 0.25 : 0.75) -
00078 atan(b/hitPoint[1]) / (2 * M_PI));
00079 }
00080
00081 if(hitNormal)
00082 {
00083 b /= a;
00084 hitNormal->set(hitPoint[0]*b, hitPoint[1], hitPoint[2]*b);
00085 }
00086 }
00087
00088 void renderNormals(const vector<Vector3> &, const RenderConfig *);
00089
00090 void Torus::render(bool texture,
00091 const Shape *shape,
00092 const RenderConfig *config)
00093 {
00094 glFrontFace(GL_CW);
00095 glDisable(GL_COLOR_MATERIAL);
00096 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
00097 glEnable(GL_CULL_FACE);
00098
00099 vector<Vector3> normals;
00100 const bool showNormals = config->showNormals;
00101
00102 const int phiSteps = config->subdivision2;
00103 const int thetaSteps = config->subdivision1;
00104
00105 vector<Vector3> nl(thetaSteps);
00106 vector<Vector3> vl(thetaSteps);
00107 vector<Vector3> fnl(thetaSteps);
00108 vector<Vector3> fvl(thetaSteps);
00109
00110 for(int i=0; i<thetaSteps; ++i)
00111 {
00112 double texS = 1.0 / thetaSteps * i;
00113 double theta = 2 * M_PI * texS;
00114
00115 double cos_theta = cos(theta);
00116 double sin_theta = sin(theta);
00117
00118 fnl[i] = nl[i] = Vector3(sin_theta, 0, cos_theta);
00119 fvl[i] = vl[i] = nl[i] * (minorRadius - majorRadius);
00120 }
00121
00122 double prevTexT = 0;
00123 Vector3 v;
00124
00125 for(int i=1; i<phiSteps; ++i)
00126 {
00127 glBegin(GL_QUAD_STRIP);
00128
00129 const Vector3 pvl0 = vl[0];
00130 const Vector3 pnl0 = nl[0];
00131
00132 double texT = 1.0 / phiSteps * i;
00133 double phi = 2 * M_PI * texT;
00134
00135 double cos_phi = cos(phi);
00136 double sin_phi = sin(phi);
00137
00138 double a = majorRadius - minorRadius * cos_phi;
00139 double b = -minorRadius * sin_phi;
00140
00141 for(int j=0; j<thetaSteps; ++j)
00142 {
00143 double texS = 1.0 / thetaSteps * j;
00144 double theta = 2 * M_PI * texS;
00145
00146 double cos_theta = cos(theta);
00147 double sin_theta = sin(theta);
00148
00149 if(texture) glTexCoord2d(texS, prevTexT);
00150 v = nl[j];
00151 glNormal3d(v[0], v[1], v[2]);
00152 v = vl[j];
00153 glVertex3d(v[0], v[1], v[2]);
00154 if(showNormals)
00155 {
00156 normals.push_back(v);
00157 normals.push_back(nl[j]);
00158 }
00159
00160 if(texture) glTexCoord2d(texS, texT);
00161 v = nl[j] = Vector3(cos_phi*sin_theta, -sin_phi, cos_phi*cos_theta);
00162 glNormal3d(v[0], v[1], v[2]);
00163 v = vl[j] = Vector3(-sin_theta * a, b, -cos_theta * a);
00164 glVertex3d(v[0], v[1], v[2]);
00165 }
00166
00167 if(texture) glTexCoord2d(1, prevTexT);
00168 glNormal3d(pnl0[0], pnl0[1], pnl0[2]);
00169 glVertex3d(pvl0[0], pvl0[1], pvl0[2]);
00170
00171 if(texture) glTexCoord2d(1, texT);
00172 v = nl[0];
00173 glNormal3d(v[0], v[1], v[2]);
00174 v = vl[0];
00175 glVertex3d(v[0], v[1], v[2]);
00176
00177 prevTexT = texT;
00178
00179 glEnd();
00180 }
00181
00182 glBegin(GL_QUAD_STRIP);
00183
00184 for(int i=0; i<thetaSteps; ++i)
00185 {
00186 double texS = 1.0 / thetaSteps * i;
00187
00188 if(texture) glTexCoord2d(texS, prevTexT);
00189 v = nl[i];
00190 glNormal3d(v[0], v[1], v[2]);
00191 v = vl[i];
00192 glVertex3d(v[0], v[1], v[2]);
00193 if(showNormals)
00194 {
00195 normals.push_back(v);
00196 normals.push_back(nl[i]);
00197 }
00198
00199 if(texture) glTexCoord2d(texS, 1);
00200 v = fnl[i];
00201 glNormal3d(v[0], v[1], v[2]);
00202 v = fvl[i];
00203 glVertex3d(v[0], v[1], v[2]);
00204 }
00205
00206 if(texture) glTexCoord2d(1, prevTexT);
00207 v = nl[0];
00208 glNormal3d(v[0], v[1], v[2]);
00209 v = vl[0];
00210 glVertex3d(v[0], v[1], v[2]);
00211
00212 if(texture) glTexCoord2d(1, 1);
00213 v = fnl[0];
00214 glNormal3d(v[0], v[1], v[2]);
00215 v = fvl[0];
00216 glVertex3d(v[0], v[1], v[2]);
00217
00218 glEnd();
00219
00220 if(showNormals) renderNormals(normals, config);
00221 }
00222 }
00223 }