void HalfSpace3<Real>::Get (Vector3<Real>& rkNormal, Real& rfConstant) const { rkNormal.X() = m_afTuple[0]; rkNormal.Y() = m_afTuple[1]; rkNormal.Z() = m_afTuple[2]; rfConstant = m_afTuple[3]; }
void HalfSpace3<Real>::Set (const Vector3<Real>& rkNormal, Real fConstant) { m_afTuple[0] = rkNormal.X(); m_afTuple[1] = rkNormal.Y(); m_afTuple[2] = rkNormal.Z(); m_afTuple[3] = fConstant; }
// http://forums.macrumors.com/showthread.php?t=547587 void CameraRenderNode::perspective(double fovy, double zNear, double zFar) { Vector2 screenBounds = scene->getSettingsManager()->getPixelViewportBounds(); double aspect = (double)screenBounds.X()/screenBounds.Y(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); double xmin, xmax, ymin, ymax; ymax = zNear * tan(fovy * M_PI / 360.0); //ymax = zNear * tan(fovy); ymin = -ymax; xmin = ymin * aspect; xmax = ymax * aspect; glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDepthMask(GL_TRUE); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); switch(scene->getSettingsManager()->getRotation()) { case ROTATION_PORTRAIT: break; case ROTATION_LANDSCAPE_COUNTERCLOCKWISE: glRotatef(-90.0f, 0.0f, 0.0f, 1.0f); break; case ROTATION_PORTRAIT_UPSIDEDOWN: glRotatef(-180.0f, 0.0f, 0.0f, 1.0f); break; case ROTATION_LANDSCAPE_CLOCKWISE: glRotatef(-270.0f, 0.0f, 0.0f, 1.0f); break; } Quaternion* orientation = owner->getTransform()->getOrientation(); GLfloat angle; Vector3 axis; orientation->ToAxisAngle(axis, angle); angle = angle/Wm5::Mathf::PI * 180.0f; glRotatef(angle, axis.X(), axis.Y(), axis.Z()); Vector3* pos = owner->getTransform()->getPosition(); glTranslatef(-pos->X(), -pos->Y(), -pos->Z()); }
void ModelLoader::ReadVertexData(FILE* apFile) { Vector3 tmpVec; fscanf(apFile, "%f %f %f",&tmpVec.X(),&tmpVec.Y(),&tmpVec.Z()); mVertices.push_back(tmpVec); }
void ModelLoader::ReadNormalData(FILE* apFile) { Vector3 tmpVec; fscanf(apFile, "%f %f %f",&tmpVec.X(),&tmpVec.Y(),&tmpVec.Z()); mNormals.push_back(tmpVec); }
HalfSpace3<Real>::HalfSpace3 (const Vector3<Real>& rkNormal, const Vector3<Real>& rkPoint) { m_afTuple[0] = rkNormal.X(); m_afTuple[1] = rkNormal.Y(); m_afTuple[2] = rkNormal.Z(); m_afTuple[3] = rkNormal.Dot(rkPoint); }
void Shader::SetVector3(std::string name, Vector3 value) { int uloc = SIG_FindUniform(name); if (uloc != -1) { glUniform3fARB(uloc, value.X(), value.Y(), value.Z()); } else { SIG_LOG("Could not find uniform \"" << name << "\""); } }
void RenderUtils::drawLine(const Vector3& from, const Vector3& to, const Vector3& color) { glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); GLfloat points[6]; points[0] = from.X(); points[1] = from.Y(); points[2] = from.Z(); points[3] = to.X(); points[4] = to.Y(); points[5] = to.Z(); glColor4f (color.X(), color.Y(), color.Z(), 1.0f); glVertexPointer(3, GL_FLOAT, 0, points); glDrawArrays(GL_LINES, 0, 2); }
Plane::Plane(const Vector3 &n, double d) { Vector3 norm = n; norm.normalize(); a = norm.X(); b = norm.Y(); c = norm.Z(); this->d = d; }
Vector3 Matrix4::operator*(const Vector3 &aRHS) const { if(mIdentity) { return aRHS; } else { Vector3 r; float fInvW = 1.0f / ( mComponents[3][0] * aRHS.X() + mComponents[3][1] * aRHS.Y() + mComponents[3][2] * aRHS.Z() + mComponents[3][3] ); r.X() = ( mComponents[0][0] * aRHS.X() + mComponents[0][1] * aRHS.Y() + mComponents[0][2] * aRHS.Z() + mComponents[0][3] ) * fInvW; r.Y() = ( mComponents[1][0] * aRHS.X() + mComponents[1][1] * aRHS.Y() + mComponents[1][2] * aRHS.Z() + mComponents[1][3] ) * fInvW; r.Z() = ( mComponents[2][0] * aRHS.X() + mComponents[2][1] * aRHS.Y() + mComponents[2][2] * aRHS.Z() + mComponents[2][3] ) * fInvW; return r; } }
void RenderUtils::drawPolygon(const std::vector<Vector3>& points, const Vector3& color, bool filled) { glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); GLfloat vertices[3 * points.size()]; int count=0; for (int i = 0; i < points.size(); i++) { Vector3 p = points[i]; vertices[count++] = p.X(); vertices[count++] = p.Y(); vertices[count++] = p.Z(); } glColor4f (color.X(), color.Y(), color.Z(), 1.0f); glVertexPointer (3, GL_FLOAT, 0, vertices); glDrawArrays ((filled) ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, points.size()); }
Vector3<Real> Torus3<Real>::Normal (Real fS, Real fT) { Real fTwoPiS = Math<Real>::TWO_PI*fS; Real fCosTwoPiS = Math<Real>::Cos(fTwoPiS); Real fSinTwoPiS = Math<Real>::Sin(fTwoPiS); Vector3<Real> kPos = Position(fS,fT); Vector3<Real> kNor(kPos.X()-m_fRo*fCosTwoPiS,kPos.Y()-m_fRo*fSinTwoPiS, kPos.Z()); kNor.Normalize(); return kNor; }
HalfSpace3<Real>::HalfSpace3 (const Vector3<Real>& rkPoint0, const Vector3<Real>& rkPoint1, const Vector3<Real>& rkPoint2) { Vector3<Real> kEdge1 = rkPoint1 - rkPoint0; Vector3<Real> kEdge2 = rkPoint2 - rkPoint0; Vector3<Real> kNormal = kEdge1.UnitCross(kEdge2); m_afTuple[0] = kNormal.X(); m_afTuple[1] = kNormal.Y(); m_afTuple[2] = kNormal.Z(); m_afTuple[3] = kNormal.Dot(rkPoint0); }
bool BoundingBox::GetCollisionNormalAndDepth(BoundingBox const& other, Vector3& normal, float& depth) const { Vector3 mina = Vector3(minX_, minY_, minZ_); Vector3 maxa = Vector3(maxX_, maxY_, maxZ_); Vector3 minb = Vector3(other.minX_, other.minY_, other.minZ_); Vector3 maxb = Vector3(other.maxX_, other.maxY_, other.maxZ_); // the normal of each face. static const Vector3 faces[6] = { Vector3(-1, 0, 0), Vector3(1, 0, 0), Vector3(0, -1, 0), Vector3(0, 1, 0), Vector3(0, 0, -1), Vector3(0, 0, 1) }; float distances[6] = { (maxb.X() - mina.X()), (maxa.X() - minb.X()), (maxb.Y() - mina.Y()), (maxa.Y() - minb.Y()), (maxb.Z() - mina.Z()), (maxa.Z() - minb.Z()) }; for (unsigned int i = 0; i < 6; i++) { if (distances[i] <= 0.0f) { return false; } if ((i == 0) || (distances[i] < depth)) { normal = faces[i]; depth = distances[i]; } } return true; }
Matrix4 Matrix4::GenerateOrthogonalBaseFromAxis(const Vector3 &aAxis) { Vector3 FirstVector = aAxis.NormalisedCopy(); Vector3 SecondVector; Vector3 ThirdVector; if(aAxis != Vector3::UnitX) { SecondVector = Vector3::UnitX; } else { SecondVector = Vector3::UnitY; } ThirdVector = FirstVector.CrossProduct(SecondVector).NormalisedCopy(); SecondVector = FirstVector.CrossProduct(ThirdVector).NormalisedCopy(); return Matrix4( SecondVector.X(), SecondVector.Y(), SecondVector.Z(), 0, FirstVector.X(), FirstVector.Y(), FirstVector.Z(), 0, ThirdVector.X(), ThirdVector.Y(), ThirdVector.Z(), 0, 0, 0, 0, 1); }
ContEllipsoid3MinCR<Real>::ContEllipsoid3MinCR (int numPoints, const Vector3<Real>* points, const Vector3<Real>& C, const Matrix3<Real>& R, Real D[3]) { // Compute the constraint coefficients, of the form (A[0],A[1]) for // each i. std::vector<Vector3<Real> > A(numPoints); for (int i = 0; i < numPoints; ++i) { Vector3<Real> diff = points[i] - C; // P[i] - C Vector3<Real> prod = diff*R; // R^T*(P[i] - C) = (u,v,w) A[i].X() = prod.X()*prod.X(); // u^2 A[i].Y() = prod.Y()*prod.Y(); // v^2 A[i].Z() = prod.Z()*prod.Z(); // w^2 } // TODO: Sort the constraints to eliminate redundant ones. It is clear // how to do this in ContEllipse2MinCR. How to do this in 3D? MaxProduct(A, D); }
//--------------------------------- // //--------------------------------- void Matrix4::LookAt(const Vector3& pos, const Vector3& look, const Vector3& up) { Vector3 zVector = pos - look; zVector.Normalized(); Vector3 xVector = zVector.Cross( up ); Vector3 yVector = xVector.Cross( zVector ); xVector.Normalized(); yVector.Normalized(); float values[ MATRIX_SIZE ] = { xVector.X(), yVector.X(), zVector.X(), 0, xVector.Y(), yVector.Y(), zVector.Y(), 0, xVector.Z(), yVector.Z(), zVector.Z(), 0, 0, 0, 0, 1 }; Matrix4 lookMatrix( values ); lookMatrix.Translate( Vector3( -pos.X(), -pos.Y(), -pos.Z() ) ); }
void MeshRenderNode::render() { glPushMatrix(); Vector3* position = getOwner()->getTransform()->getPosition(); glTranslatef(position->X(), position->Y(), position->Z()); Quaternion* orientation = getOwner()->getTransform()->getOrientation(); GLfloat angle; Vector3 axis; orientation->ToAxisAngle(axis, angle); angle = angle/Wm5::Mathf::PI * 180.0f; glRotatef(angle, axis.X(), axis.Y(), axis.Z()); Vector3* scale = getOwner()->getTransform()->getScale(); glScalef(scale->X(), scale->Y(), scale->Z()); // TODO should be using animation component int animationFrame = 0; mesh->setAnimationFrame(animationFrame); mesh->Render(); glPopMatrix(); }
/** **************************************************************************************************** \fn void MatrixRotationZ( Matrix &o_matrix, const Vector3 &i_position ) \brief Matrix rotation around Z axis creator \param o_matrix output matrix \param i_rotation rotation angle \return NONE **************************************************************************************************** */ void GameEngine::Math::Matrix::MatrixTranslation( Matrix &o_matrix, const Vector3 &i_position ) { FUNCTION_START; assert( o_matrix._u32Column == 4 ); assert( o_matrix._u32Row == 4 ); o_matrix = o_matrix.Identity(); o_matrix( 3, 0 ) = i_position.X(); o_matrix( 3, 1 ) = i_position.Y(); o_matrix( 3, 2 ) = i_position.Z(); FUNCTION_FINISH; }
void Wml::ContAlignedBox (int iQuantity, const Vector3<Real>* akPoint, Vector3<Real>& rkMin, Vector3<Real>& rkMax) { rkMin = akPoint[0]; rkMax = rkMin; for (int i = 1; i < iQuantity; i++) { if ( akPoint[i].X() < rkMin.X() ) rkMin.X() = akPoint[i].X(); else if ( akPoint[i].X() > rkMax.X() ) rkMax.X() = akPoint[i].X(); if ( akPoint[i].Y() < rkMin.Y() ) rkMin.Y() = akPoint[i].Y(); else if ( akPoint[i].Y() > rkMax.Y() ) rkMax.Y() = akPoint[i].Y(); if ( akPoint[i].Z() < rkMin.Z() ) rkMin.Z() = akPoint[i].Z(); else if ( akPoint[i].Z() > rkMax.Z() ) rkMax.Z() = akPoint[i].Z(); } }
bool KernelCollection::isWithinConvexHull(const kernel::base& k) const { NUKLEI_TRACE_BEGIN(); #ifdef NUKLEI_USE_CGAL using namespace cgal_convex_hull_types; Vector3 loc = k.getLoc(); if (!deco_.has_key(HULL_KEY)) NUKLEI_THROW("Undefined convex hull. Call buildConvexHull() first."); return deco_.get< boost::shared_ptr<Convex_hull_3> >(HULL_KEY)->bounded_side (Point_3(loc.X(), loc.Y(), loc.Z())) != CGAL::ON_UNBOUNDED_SIDE; #else NUKLEI_THROW("This function requires CGAL. See http://nuklei.sourceforge.net/doxygen/group__install.html"); #endif NUKLEI_TRACE_END(); }
void rms::ComputePerpVectors( const Vector3<Real> & vIn, Vector3<Real> & vOut1, Vector3<Real> & vOut2, bool bInIsNormalized ) { Wml::Vector3<Real> vPerp(vIn); if ( ! bInIsNormalized ) vPerp.Normalize(); if ( Wml::Math<Real>::FAbs(vPerp.X()) >= Wml::Math<Real>::FAbs(vPerp.Y()) && Wml::Math<Real>::FAbs(vPerp.X()) >= Wml::Math<Real>::FAbs(vPerp.Z()) ) { vOut1.X() = -vPerp.Y(); vOut1.Y() = vPerp.X(); vOut1.Z() = (Real)0.0; } else { vOut1.X() = (Real)0.0; vOut1.Y() = vPerp.Z(); vOut1.Z() = -vPerp.Y(); } vOut1.Normalize(); vOut2 = vPerp.Cross(vOut1); }
void Camera::Sync3DAudio(Vector3 lookingAt) { Vector3 completeAt = Owner()->GetTransform()->Position() + lookingAt; mListenerProperties.LookAtVector[0] = completeAt.X(); mListenerProperties.LookAtVector[1] = completeAt.Y(); mListenerProperties.LookAtVector[2] = completeAt.Z(); mListenerProperties.UpVector[0] = Owner()->GetTransform()->Up().X(); mListenerProperties.UpVector[1] = Owner()->GetTransform()->Up().Y(); mListenerProperties.UpVector[2] = Owner()->GetTransform()->Up().Z(); mListenerProperties.Position[0] = Owner()->GetTransform()->Position().X(); mListenerProperties.Position[1] = Owner()->GetTransform()->Position().X(); mListenerProperties.Position[2] = Owner()->GetTransform()->Position().X(); mpAudioListener->SetListenerProperties(mListenerProperties); }
bool c_CurveClustering::get_recovered_curves(const t_ClusterSet &_cluster_set, const t_CurveSet &_curve_set, const t_MatrixSet &_matrix_set, t_CurveSet &_recovered) { size_t n_curves = _curve_set.size(); _recovered.reserve(n_curves); t_ClusterSet::const_iterator cit = _cluster_set.begin(); t_ClusterSet::const_iterator cit_end = _cluster_set.end(); for (; cit != cit_end; ++cit) { /*!< for each cluster */ int index = cit->m_i_center; const c_Curve &curve = *(_curve_set[index]); const t_PointSet &controls = curve.get_controls(); size_t n_controls = controls.size(); const std::vector<int> &indices = cit->m_i_data; std::vector<int>::const_iterator cit_i = indices.begin(); std::vector<int>::const_iterator cit_i_end = indices.end(); for (; cit_i != cit_i_end; ++cit_i) { /*!< for each element in the cluster */ const t_Matrix &matrix = _matrix_set[*cit_i]; t_PointSet new_controls(n_controls); for (size_t i = 0; i < n_controls; ++i) { Vector3<t_Real> temp = matrix * Vector3<t_Real>(controls[i].X(), controls[i].Y(), 1); new_controls[i] = Vector2<t_Real>(temp.X(), temp.Y()); } _recovered.push_back(new c_Curve(new_controls)); } } return true; }
void MinBox3<Real>::MinimalBoxForAngles (int iQuantity, const Vector3<Real>* akPoint, Real afAngle[3], Box3<Real>& rkBox) { Real fCos0 = Math<Real>::Cos(afAngle[0]); Real fSin0 = Math<Real>::Sin(afAngle[0]); Real fCos1 = Math<Real>::Cos(afAngle[1]); Real fSin1 = Math<Real>::Sin(afAngle[1]); Vector3<Real> kAxis(fCos0*fSin1,fSin0*fSin1,fCos1); Matrix3<Real> kRot(kAxis,afAngle[2]); Vector3<Real> kMin = akPoint[0]*kRot, kMax = kMin; for (int i = 1; i < iQuantity; i++) { Vector3<Real> kTest = akPoint[i]*kRot; if ( kTest.X() < kMin.X() ) kMin.X() = kTest.X(); else if ( kTest.X() > kMax.X() ) kMax.X() = kTest.X(); if ( kTest.Y() < kMin.Y() ) kMin.Y() = kTest.Y(); else if ( kTest.Y() > kMax.Y() ) kMax.Y() = kTest.Y(); if ( kTest.Z() < kMin.Z() ) kMin.Z() = kTest.Z(); else if ( kTest.Z() > kMax.Z() ) kMax.Z() = kTest.Z(); } Vector3<Real> kMid = ((Real)0.5)*(kMax + kMin); Vector3<Real> kRng = ((Real)0.5)*(kMax - kMin); rkBox.Center() = kRot*kMid; rkBox.Axis(0) = kRot.GetColumn(0); rkBox.Axis(1) = kRot.GetColumn(1); rkBox.Axis(2) = kRot.GetColumn(2); rkBox.Extent(0) = kRng.X(); rkBox.Extent(1) = kRng.Y(); rkBox.Extent(2) = kRng.Z(); }
bool c_CurveClustering::standardize(const c_Curve *_p_original_curve, c_Curve *&_p_standard_curve) { /*!< create an oriented bounding box for sample points */ const t_PointSet samples = _p_original_curve->get_samples(); Box2<t_Real> box = ContOrientedBox(samples.size(), samples.data()); /*!< ensure that extends of the box are not too small */ if (box.Extent[0] < epsilon) { box.Extent[0] = 1; } if (box.Extent[1] < epsilon) { box.Extent[1] = 1; } /*!< set the affine matrix in the transform, using the box */ Matrix3<t_Real> affine_matrix; c_Curve::t_Point const &first = samples.front(); __set_affine_matrix(box, Vector3<t_Real>(first.X(), first.Y(), 1), affine_matrix); m_affine_matrices.push_back(affine_matrix.Inverse()); /*!< calculate the new standard control points */ const t_PointSet old_controls = _p_original_curve->get_controls(); size_t n_controls = old_controls.size(); t_PointSet new_controls(n_controls); for (size_t i = 0; i < n_controls; ++i) { Vector3<t_Real> temp = affine_matrix * Vector3<t_Real>(old_controls[i].X(), old_controls[i].Y(), 1); new_controls[i] = Vector2<t_Real>(temp.X(), temp.Y()); } _p_standard_curve = new c_Curve(new_controls); return true; }
Vector2 CameraRenderNode::convertToWorldCoords(const Vector2& screenCoords) { if(guiCamera) { return screenCoords; } else { // TODO - this is inefficient as shit, but it works Vector2 rotatedBounds = getCameraBounds().min; switch(scene->getSettingsManager()->getRotation()) { case ROTATION_PORTRAIT: case ROTATION_PORTRAIT_UPSIDEDOWN: break; case ROTATION_LANDSCAPE_COUNTERCLOCKWISE: case ROTATION_LANDSCAPE_CLOCKWISE: Vector2 cameraBoundsMin = getCameraBounds().min; rotatedBounds = Vector2(cameraBoundsMin.Y(), cameraBoundsMin.X()); break; } Vector3* pos = owner->getTransform()->getPosition(); return zoomFactor * screenCoords + rotatedBounds + Vector2(pos->X(), pos->Y()); } }
// http://iphonedevelopment.blogspot.com/2008/10/circles-and-ellipses-in-opengl-es.html void RenderUtils::drawEllipse(int segments, float width, float height, const Vector2& center, const Vector3& color, bool filled) { glBindBuffer(GL_ARRAY_BUFFER, 0); glEnableClientState(GL_VERTEX_ARRAY); glDisable(GL_TEXTURE_2D); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glPushMatrix(); glTranslatef(center.X(), center.Y(), 0.0); GLfloat vertices[segments*3]; int count=0; for (GLfloat i = 0; i < (2*Wm5::Mathf::PI); i+=((2*Wm5::Mathf::PI)/segments)) { vertices[count++] = (Wm5::Mathf::Cos(i)*width); vertices[count++] = (Wm5::Mathf::Sin(i)*height); vertices[count++] = 0.0f; } glColor4f (color.X(), color.Y(), color.Z(), 1.0f); glVertexPointer (3, GL_FLOAT, 0, vertices); glDrawArrays ((filled) ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, segments); glPopMatrix(); }
Real MinBox3<Real>::Volume (const Real* afAngle, void* pvData) { MinBox3& rkSelf = *(MinBox3*)pvData; Real fCos0 = Math<Real>::Cos(afAngle[0]); Real fSin0 = Math<Real>::Sin(afAngle[0]); Real fCos1 = Math<Real>::Cos(afAngle[1]); Real fSin1 = Math<Real>::Sin(afAngle[1]); Vector3<Real> kAxis(fCos0*fSin1,fSin0*fSin1,fCos1); Matrix3<Real> kRot(kAxis,afAngle[2]); Vector3<Real> kMin = rkSelf.m_akPoint[0]*kRot, kMax = kMin; for (int i = 1; i < rkSelf.m_iQuantity; i++) { Vector3<Real> kTest = rkSelf.m_akPoint[i]*kRot; if ( kTest.X() < kMin.X() ) kMin.X() = kTest.X(); else if ( kTest.X() > kMax.X() ) kMax.X() = kTest.X(); if ( kTest.Y() < kMin.Y() ) kMin.Y() = kTest.Y(); else if ( kTest.Y() > kMax.Y() ) kMax.Y() = kTest.Y(); if ( kTest.Z() < kMin.Z() ) kMin.Z() = kTest.Z(); else if ( kTest.Z() > kMax.Z() ) kMax.Z() = kTest.Z(); } Real fVolume = (kMax.X()-kMin.X()) * (kMax.Y()-kMin.Y()) * (kMax.Z()-kMin.Z()); return fVolume; }
bool CylinderIntersector<real>::Intersect( const Cylinder<real>* cylinder, const Ray<real>& ray, Intersection<real>& oIntersection ) { real nearestDistance = std::numeric_limits<real>::max(); real distance = 0; bool hasIntersection = false; //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// //Ici, vous calculerez l'intersection entre //le rayon "ray" et le cylindre "cylinder" //Pensez à initialiser les quatre attributs //de oIntersection (retourné par référence) //correctement si une intersection est trouvée. //////////////////////////////////////////// //////////////////IFT 3355////////////////// //////////////////////////////////////////// real halfHeight = cylinder->GetHeight() / 2; real radius = cylinder->GetRadius(); // Intersection with extremeties. Vector3<real> extremeties[2] = { Vector3<real>(0, halfHeight, 0), Vector3<real>(0, -halfHeight, 0), }; for (int k = 0; k < 2; ++k) { Vector3<real> plane = extremeties[k]; real denom = ray.GetDirection() * plane; bool intersectsPlane = fabs(denom) > EPS; // Ray intersects with the extremety. if (intersectsPlane) { // Intersection position on the infinite plane. real t = ((plane - ray.GetOrigin()) * plane) / denom; Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); // Ray intersects in the window. if ((plane - intersectionPos).Length() <= radius && ray.GetDirection() * plane < 0 && t > EPS && t <= nearestDistance) { oIntersection.SetNormal(plane); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } } // Intersection with main body Vector3<real> o = Vector3<real>(ray.GetOrigin().X(), 0, ray.GetOrigin().Z()); Vector3<real> d = Vector3<real>(ray.GetDirection().X(), 0, ray.GetDirection().Z()); real a = d*d; real b = 2 * d * o; real c = o * o - (radius*radius); real discr = b*b - 4*a*c; if (discr < -EPS) { return hasIntersection; // No intersection. } else { real t1 = (-b - sqrt(discr)) / (2*a); real t2 = (-b + sqrt(discr)) / (2*a); real t = std::min<real>(t1, t2); Vector3<real> intersectionPos = ray.GetOrigin() + t * ray.GetDirection(); if (t >= EPS && t < nearestDistance && fabs(intersectionPos.Y()) < halfHeight+EPS) { oIntersection.SetNormal(intersectionPos - Vector3<real>(0, intersectionPos.Y(), 0)); oIntersection.SetPosition(intersectionPos); oIntersection.SetTextureCoordinates(intersectionPos); oIntersection.IsInside(false); nearestDistance = t; hasIntersection = true; } } return hasIntersection; }