void Torus3<Real>::GetParameters (const Vector3<Real>& rkPos, Real& rfS, Real& rfT) const { Real fRc = Math<Real>::Sqrt(rkPos.X()*rkPos.X() + rkPos.Y()*rkPos.Y()); Real fAngle; if ( fRc < Math<Real>::EPSILON ) { rfS = (Real)0.0; } else { fAngle = Math<Real>::ATan2(rkPos.Y(),rkPos.X()); if ( fAngle >= (Real)0.0 ) rfS = fAngle*Math<Real>::INV_TWO_PI; else rfS = (Real)1.0 + fAngle*Math<Real>::INV_TWO_PI; } Real fDiff = fRc - m_fRo; if ( Math<Real>::FAbs(fDiff) < Math<Real>::EPSILON && Math<Real>::FAbs(rkPos.Z()) < Math<Real>::EPSILON ) { rfT = (Real)0.0; } else { fAngle = Math<Real>::ATan2(rkPos.Z(),fDiff); if ( fAngle >= (Real)0.0 ) rfT = fAngle*Math<Real>::INV_TWO_PI; else rfT = (Real)1.0 + fAngle*Math<Real>::INV_TWO_PI; } }
void Wml::MinEllipsoidCR3 (int iQuantity, const Vector3<Real>* akPoint, const Vector3<Real>& rkC, const Matrix3<Real>& rkR, Real afD[3]) { // Given center C and orientation R, finds minimum volume ellipsoid // (X-C)^t R^t D R (X-C) = 1 where D is a diagonal matrix whose diagonal // entries are positive. The problem is equivalent to maximizing the // product D[0]*D[1]*D[2] given C and R and subject to the constraints // (P[i]-C)^t R^t D R (P[i]-C) <= 1 for all input points P[i] with // 0 <= i < N. Each constraint has form a0*D[0]+a1*D[1]+a2*D[2] <= 1 // where a0 >= 0, a1 >= 0, and a2 >= 0. Real* afA0 = new Real[iQuantity]; Real* afA1 = new Real[iQuantity]; Real* afA2 = new Real[iQuantity]; for (int i = 0; i < iQuantity; i++) { Vector3<Real> kDiff = akPoint[i] - rkC; Vector3<Real> kProd = rkR*kDiff; afA0[i] = kProd.X()*kProd.X(); afA1[i] = kProd.Y()*kProd.Y(); afA2[i] = kProd.Z()*kProd.Z(); } MaxProduct(iQuantity,afA0,afA1,afA2,afD[0],afD[1],afD[2]); delete[] afA2; delete[] afA1; delete[] afA0; }
bool BoundingBox::Contains(Vector3 const& point) const { if (point.X() < minX_) { return false; } if (point.X() > maxX_) { return false; } if (point.Y() < minY_) { return false; } if (point.Y() > maxY_) { return false; } if (point.Z() < minZ_) { return false; } if (point.Z() > maxZ_) { return false; } return true; }
Vector3 Vector3::Add(const Vector3 a, const Vector3 b) { return Vector3( a.X() + b.X(), a.Y() + b.Y(), a.Z() + b.Z()); }
float Vector3::Distance(const Vector3 a, const Vector3 b) { return sqrtf( pow(a.X() - b.X(), 2) + pow(a.Y() - b.Y(), 2) + pow(a.Z() - b.Z(), 2)); }
Vector3 Vector3::Multiply(const Vector3 a, const Vector3 b) { return Vector3( a.X() * b.X(), a.Y() * b.Y(), a.Z() * b.Z()); }
bool PlaneIntersector<real>::Intersect( const Plane<real>* plane, const Ray<real>& ray, Intersection<real>& oIntersection ) { const Vector3<real>& origin = ray.GetOrigin(); const Vector3<real>& direction = ray.GetDirection(); // Do not perform intersection if the direction of the ray is degenerated relative to the plane if ( fabs( direction.Y() ) > EPS ) { // Compute the intersection point and see if it's inside the plane bounds real t = -origin.Y() / direction.Y(); Vector3<real> intersectionPoint = origin + t * direction; bool isInsideXBounds = ( fabs( intersectionPoint.X() ) < plane->GetSizeX() * 0.5 ) ? true : false; bool isInsideZBounds = ( fabs( intersectionPoint.Z() ) < plane->GetSizeZ() * 0.5 ) ? true : false; // If the ray intersect and the intersection is in front if ( ( t > 0 ) && isInsideXBounds && isInsideZBounds ) { oIntersection.SetPosition( intersectionPoint ); oIntersection.SetNormal( Vector3<real>( 0, -sign<real>( direction.Y() ), 0 ) ); oIntersection.IsInside( false ); // Compute texture coodinates as (z=-0.5 => u=0 and x=-0.5 => v=0) real u = ( intersectionPoint.Z() + plane->GetSizeZ() * 0.5 ) / plane->GetSizeZ(); real v = ( intersectionPoint.X() + plane->GetSizeX() * 0.5 ) / plane->GetSizeX(); oIntersection.SetTextureCoordinates( Vector3<real>( u, v, 0 ) ); return true; } } return false; }
Transformation<real> SceneImporter<real>::ReadTransformation( std::istream& stream ) { Transformation<real> transformation; ReadNextExactToken( stream, "Transformation" ); ReadNextExactToken( stream, "(" ); if ( TryReadClosingParenthesis( stream ) ) return transformation; Vector3<real> rotation = ReadVector3( stream ); ReadNextExactToken( stream, "," ); Vector3<real> translation = ReadVector3( stream ); ReadNextExactToken( stream, "," ); Vector3<real> scale = ReadVector3( stream ); ReadNextExactToken( stream, ")" ); transformation.RotateX( rotation.X() ); transformation.RotateY( rotation.Y() ); transformation.RotateZ( rotation.Z() ); transformation.SetTranslation( translation ); transformation.SetScaleX( scale.X() ); transformation.SetScaleY( scale.Y() ); transformation.SetScaleZ( scale.Z() ); return transformation; }
/** **************************************************************************************************** \fn Matrix operator*( const Matrix &i_matrix, const Vector &i_vector ) \brief operator * of Matrix class \param i_matrix the Matrix to be multiplied \param i_vector Vector3 multiplied \return Matrix \retval Result matrix **************************************************************************************************** */ Matrix operator*( const Matrix &i_matrix, const Vector3 &i_vector ) { FUNCTION_START; assert( (i_matrix._u32Row == 1) || (i_matrix._u32Row == 3) ); assert( (i_matrix._u32Column == 1) || (i_matrix._u32Column == 3) ); if( i_matrix._u32Row == 1 ) { Matrix vectorMatrix( 3, 1 ); vectorMatrix(0, 0) = i_vector.X(); vectorMatrix(1, 0) = i_vector.Y(); vectorMatrix(2, 0) = i_vector.Z(); FUNCTION_FINISH; return i_matrix * vectorMatrix; } else { Matrix vectorMatrix( 1, 3 ); vectorMatrix( 0, 0 ) = i_vector.X(); vectorMatrix( 0, 1 ) = i_vector.Y(); vectorMatrix( 0, 2 ) = i_vector.Z(); FUNCTION_FINISH; return i_matrix * vectorMatrix; } FUNCTION_FINISH; }
void Ball::draw(const Vector3 &color) const { glPushMatrix(); glPushAttrib(GL_ALL_ATTRIB_BITS); glColor3fv(color.toArray()); Vector3 b = rotationaxis.getBegin(); Vector3 e = rotationaxis.getEnd() - b; glTranslated(b.X(), b.Y(), b.Z()); glRotated(thetarotate * 180 / PI, e.X(), e.Y(), e.Z()); glTranslated(-b.X(), -b.Y(), -b.Z()); glTranslated(centerofmass.X(), centerofmass.Y(), centerofmass.Z()); glColor3fv(color.toArray()); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D,texture_id); glutSolidSphere(radius,40,40); glPopAttrib(); glPopMatrix(); }
Box3<Real> GaussPointsFit3 (int iQuantity, const Vector3<Real>* akPoint) { Box3<Real> kBox(Vector3<Real>::ZERO,Vector3<Real>::UNIT_X, Vector3<Real>::UNIT_Y,Vector3<Real>::UNIT_Z,(Real)1.0,(Real)1.0, (Real)1.0); // compute the mean of the points kBox.Center = akPoint[0]; int i; for (i = 1; i < iQuantity; i++) { kBox.Center += akPoint[i]; } Real fInvQuantity = ((Real)1.0)/iQuantity; kBox.Center *= fInvQuantity; // compute the covariance matrix of the points Real fSumXX = (Real)0.0, fSumXY = (Real)0.0, fSumXZ = (Real)0.0; Real fSumYY = (Real)0.0, fSumYZ = (Real)0.0, fSumZZ = (Real)0.0; for (i = 0; i < iQuantity; i++) { Vector3<Real> kDiff = akPoint[i] - kBox.Center; fSumXX += kDiff.X()*kDiff.X(); fSumXY += kDiff.X()*kDiff.Y(); fSumXZ += kDiff.X()*kDiff.Z(); fSumYY += kDiff.Y()*kDiff.Y(); fSumYZ += kDiff.Y()*kDiff.Z(); fSumZZ += kDiff.Z()*kDiff.Z(); } fSumXX *= fInvQuantity; fSumXY *= fInvQuantity; fSumXZ *= fInvQuantity; fSumYY *= fInvQuantity; fSumYZ *= fInvQuantity; fSumZZ *= fInvQuantity; // setup the eigensolver Eigen<Real> kES(3); kES(0,0) = fSumXX; kES(0,1) = fSumXY; kES(0,2) = fSumXZ; kES(1,0) = fSumXY; kES(1,1) = fSumYY; kES(1,2) = fSumYZ; kES(2,0) = fSumXZ; kES(2,1) = fSumYZ; kES(2,2) = fSumZZ; kES.IncrSortEigenStuff3(); for (i = 0; i < 3; i++) { kBox.Extent[i] = kES.GetEigenvalue(i); kES.GetEigenvector(i,kBox.Axis[i]); } return kBox; }
Vector3 Vector3::Cross(Vector3 other) { Vector3 result; result.SetX((mY * other.Z()) - (other.Y() * mZ)); result.SetY((mZ * other.X()) - (other.Z() * mX)); result.SetZ((mX * other.Y()) - (other.X() * mY)); return result; }
Line3<Real> OrthogonalLineFit3 (int iQuantity, const Vector3<Real>* akPoint) { Line3<Real> kLine(Vector3<Real>::ZERO,Vector3<Real>::ZERO); // compute the mean of the points kLine.Origin = akPoint[0]; int i; for (i = 1; i < iQuantity; i++) { kLine.Origin += akPoint[i]; } Real fInvQuantity = ((Real)1.0)/iQuantity; kLine.Origin *= fInvQuantity; // compute the covariance matrix of the points Real fSumXX = (Real)0.0, fSumXY = (Real)0.0, fSumXZ = (Real)0.0; Real fSumYY = (Real)0.0, fSumYZ = (Real)0.0, fSumZZ = (Real)0.0; for (i = 0; i < iQuantity; i++) { Vector3<Real> kDiff = akPoint[i] - kLine.Origin; fSumXX += kDiff.X()*kDiff.X(); fSumXY += kDiff.X()*kDiff.Y(); fSumXZ += kDiff.X()*kDiff.Z(); fSumYY += kDiff.Y()*kDiff.Y(); fSumYZ += kDiff.Y()*kDiff.Z(); fSumZZ += kDiff.Z()*kDiff.Z(); } fSumXX *= fInvQuantity; fSumXY *= fInvQuantity; fSumXZ *= fInvQuantity; fSumYY *= fInvQuantity; fSumYZ *= fInvQuantity; fSumZZ *= fInvQuantity; // set up the eigensolver Eigen<Real> kES(3); kES(0,0) = fSumYY+fSumZZ; kES(0,1) = -fSumXY; kES(0,2) = -fSumXZ; kES(1,0) = kES(0,1); kES(1,1) = fSumXX+fSumZZ; kES(1,2) = -fSumYZ; kES(2,0) = kES(0,2); kES(2,1) = kES(1,2); kES(2,2) = fSumXX+fSumYY; // compute eigenstuff, smallest eigenvalue is in last position kES.DecrSortEigenStuff3(); // unit-length direction for best-fit line kES.GetEigenvector(2,kLine.Direction); return kLine; }
void DrawCylinder(float radius,float height,Vector3 center,Vector3 axis) { Vector3 pos=Vector3(0,0,height/2); float theta=Vector3::anglebetweeninradian(axis,Vector3(0,0,1)); pos.Rotate(Vector3(0,0,0),Vector3(axis.Y(),axis.X(),0),theta); center-=pos; glPushMatrix(); glTranslatef(center.X(),center.Y(),center.Z()); glRotatef(theta/PIdiv180,axis.Y(),axis.X(),0); glutSolidCylinder(radius,height,50,50); glPopMatrix(); }
Real ConvexPolyhedron3<Real>::GetTriangleArea (const Vector3<Real>& rkN, const Vector3<Real>& rkV0, const Vector3<Real>& rkV1, const Vector3<Real>& rkV2) const { // compute maximum absolute component of normal vector int iMax = 0; Real fMax = Math<Real>::FAbs(rkN.X()); Real fAbs = Math<Real>::FAbs(rkN.Y()); if ( fAbs > fMax ) { iMax = 1; fMax = fAbs; } fAbs = Math<Real>::FAbs(rkN.Z()); if ( fAbs > fMax ) { iMax = 2; fMax = fAbs; } // catch degenerate triangles if ( fMax == (Real)0.0 ) return (Real)0.0; // compute area of projected triangle Real fD0, fD1, fD2, fArea; if ( iMax == 0 ) { fD0 = rkV1.Z() - rkV2.Z(); fD1 = rkV2.Z() - rkV0.Z(); fD2 = rkV0.Z() - rkV1.Z(); fArea = Math<Real>::FAbs(rkV0.Y()*fD0 + rkV1.Y()*fD1 + rkV2.Y()*fD2); } else if ( iMax == 1 ) { fD0 = rkV1.X() - rkV2.X(); fD1 = rkV2.X() - rkV0.X(); fD2 = rkV0.X() - rkV1.X(); fArea = Math<Real>::FAbs(rkV0.Z()*fD0 + rkV1.Z()*fD1 + rkV2.Z()*fD2); } else { fD0 = rkV1.Y() - rkV2.Y(); fD1 = rkV2.Y() - rkV0.Y(); fD2 = rkV0.Y() - rkV1.Y(); fArea = Math<Real>::FAbs(rkV0.X()*fD0 + rkV1.X()*fD1 + rkV2.X()*fD2); } fArea *= ((Real)0.5)/fMax; return fArea; }
Matrix4 Matrix4::GenerateCoordinatesChangeMatrix(const Vector3 &aInitialAxis1, const Vector3 &aInitialAxis2, const Vector3 &aInitialAxis3, const Vector3 &aInitialOrigin, const Vector3 &aResultingAxis1, const Vector3 &aResultingAxis2, const Vector3 &aResultingAxis3, const Vector3 &aResultingOrigin) { Matrix4 FirstOrigin(1,0,0,aInitialOrigin.X(), 0,1,0,aInitialOrigin.Y(), 0,0,1,aInitialOrigin.Z(), 0,0,0,1); Matrix4 FirstONB( aInitialAxis1.X(),aInitialAxis2.X(),aInitialAxis3.X(),0, aInitialAxis1.Y(),aInitialAxis2.Y(),aInitialAxis3.Y(),0, aInitialAxis1.Z(),aInitialAxis2.Z(),aInitialAxis3.Z(),0, 0,0,0,1); Matrix4 SecondOrigin( 1,0,0,-aResultingOrigin.X(), 0,1,0,-aResultingOrigin.Y(), 0,0,1,-aResultingOrigin.Z(), 0,0,0,1); Matrix4 SecondONB( aResultingAxis1.X(),aResultingAxis2.X(),aResultingAxis3.X(),0, aResultingAxis1.Y(),aResultingAxis2.Y(),aResultingAxis3.Y(),0, aResultingAxis1.Z(),aResultingAxis2.Z(),aResultingAxis3.Z(),0, 0,0,0,1); return SecondONB * SecondOrigin * FirstOrigin * FirstONB; }
bool Vector3::operator<(const Vector3 other) const { if (_x != other.X()) { return _x < other.X(); } if (_y != other.Y()) { return _y < other.Y(); } return _z < other.Z(); }
void SpriteRenderNode::render() { if(!hidden && (!scene->isPaused() || renderWhenPaused)) { bool renderSprites = scene->getAttribute(RENDER_SPRITES)->getBooleanValue(); if(renderSprites) { pantheios::log(pantheios::debug, "Rendering Sprite ", HashedStringInserter(texture), " for ", GameObjectInserter(*(getOwner()))); Texture* tex = CalicoAPI::getResourceManager()->getTexture(texture); assert(tex != NULL); if(tex != NULL) { if(needToRegenerateVBO) { generateVBO(); } Rect2D boundsRect = getWorldRect(); Transform* ownerTransform = owner->getTransform(); Vector3 ownerPosition = *(ownerTransform->getPosition()); Rect2D spriteBounds(Vector2(ownerPosition.X() + boundsRect.min.X(), ownerPosition.Y() + boundsRect.min.Y()), Vector2(ownerPosition.X() + boundsRect.max.X(), ownerPosition.Y() + boundsRect.max.Y())); Rect2D cameraBounds = layer->getCamera()->getWorldBounds(); // only draw if the sprite is actually on-screen // TODO - this is buggy! // if(spriteBounds.intersects(cameraBounds)) { glPushMatrix(); glMultMatrixf(ownerTransform->ToGlWorldMatrix(flip)); tex->bind(); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexPointer(2, GL_FLOAT, sizeof(VertexPt), 0); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(VertexPt), (unsigned char*) (sizeof(GLfloat) * 2)); glTexCoordPointer(2, GL_FLOAT, sizeof(VertexPt), (unsigned char*) (sizeof(GLfloat) * 2 + sizeof(GLubyte) * 4)); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindBuffer(GL_ARRAY_BUFFER, 0); glPopMatrix(); // } } } } }
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 Matrix4::SetScale(const Vector3 &aVec) { m11 = aVec.X(); m22 = aVec.Y(); m33 = aVec.Z(); mIdentity = false; }
void Matrix4::SetTranslationData(const Vector3 &aVector) { m14 = aVector.X(); m24 = aVector.Y(); m34 = aVector.Z(); mIdentity = false; }
HSVConeColor::HSVConeColor(const Color& c) { const RGBColor* rgbc = NULL; const HSVColor* hsvc = NULL; const HSVConeColor* hsvcc = NULL; if ( (rgbc = dynamic_cast<const RGBColor*>(&c)) != NULL) { HSVColor hsv(c); HSVConeColor hsvCone(hsv); c_ = hsvCone.c_; valueWeight_ = hsvCone.valueWeight_; } else if ( (hsvc = dynamic_cast<const HSVColor*>(&c)) != NULL) { Vector3 ec; ec.X() = std::cos(hsvc->H()) * hsvc->S() * hsvc->V(); ec.Y() = std::sin(hsvc->H()) * hsvc->S() * hsvc->V(); NUKLEI_RANGE_CHECK(HSV_METRIC_VALUE_WEIGHT, 0, 1); ec.Z() = hsvc->V()*HSV_METRIC_VALUE_WEIGHT; c_ = ec; valueWeight_ = HSV_METRIC_VALUE_WEIGHT; } else if ( (hsvcc = dynamic_cast<const HSVConeColor*>(&c)) != NULL) { c_ = hsvcc->c_; valueWeight_ = hsvcc->valueWeight_; } else NUKLEI_THROW("Unknown color type"); assertConsistency(); }
/* ------------------------------------------------------- */ void Transformation::setScale(const Vector3& scale) { assert(m_isRSMatrix && scale.X() != 0.0f && scale.Y() != 0.0f && scale.Z() != 0.0f); m_scale = scale; m_isIdentity = false; m_isUniformScale = false; }
Vector3 Vector3::operator*(const Vector3 b) { return Vector3( X() * b.X(), Y() * b.Y(), Z() * b.Z()); }
/* ------------------------------------------------------- */ void Transformation::invS(Vector3& v) const { assert(m_isRSMatrix); if (m_isUniformScale) { v /= m_scale[0]; } else { // The direct inverse scaling is // result.X() /= m_scale.X(); // result.Y() /= m_scale.Y(); // result.Z() /= m_scale.Z(); // When division is much more expensive than multiplication, // three divisions are replaced by one division and nine // multiplications. float fSXY = m_scale.X()*m_scale.Y(); float fSXYZ = fSXY*m_scale.Z(); float fInvSXYZ = 1.0f/fSXYZ; float fInvSXY = fInvSXYZ*m_scale.Z(); float fInvXScale = fInvSXY*m_scale.Y(); float fInvYScale = fInvSXY*m_scale.X(); float fInvZScale = fInvSXYZ*fSXY; v.X() *= fInvXScale; v.Y() *= fInvYScale; v.Z() *= fInvZScale; } }
Sphere::Sphere(const Vector3& position, const float radius, const ColorRGB& color) : SceneObject(position, color), m_radius(radius) { m_AABBMin = Vector3(position.X() - radius, position.Y() - radius, position.Z() - radius); m_AABBMax = Vector3(position.X() + radius, position.Y() + radius, position.Z() + radius); }
void KernelCollection::buildConvexHull(unsigned n) { NUKLEI_TRACE_BEGIN(); #ifdef NUKLEI_USE_CGAL using namespace cgal_convex_hull_types; if (n > size()) n = size(); // create instance of the class with dimension == 3 boost::shared_ptr<Convex_hull_3> CH_p(new Convex_hull_3(3)); for (const_sample_iterator i = as_const(*this).sampleBegin(n); i != i.end(); ++i) { Vector3 loc = i->getLoc(); CH_p->insert(Point_3(loc.X(), loc.Y(), loc.Z())); } if (!CH_p->is_valid()) NUKLEI_LOG("As it often happens, CGAL says the hull is invalid."); if (deco_.has_key(HULL_KEY)) deco_.erase(HULL_KEY); deco_.insert(HULL_KEY, CH_p); #else NUKLEI_THROW("This function requires CGAL. See http://nuklei.sourceforge.net/doxygen/group__install.html"); #endif NUKLEI_TRACE_END(); }
//--------------------------------- // //--------------------------------- void Matrix4::SetTranslation(const Vector3& trans) { SetIdentity(); m[ 12 ] = trans.X(); m[ 13 ] = trans.Y(); m[ 14 ] = trans.Z(); }
//--------------------------------- // //--------------------------------- void Matrix4::SetScale(const Vector3& scale) { SetIdentity(); m[ 0 ] *= scale.X(); m[ 5 ] *= scale.Y(); m[ 10 ] *= scale.Z(); }
void World::DrawShadows() { float shadow_plane[] = { 0.0f, 0.0f, 100.0f, 1.0f }; Vector3 vec = light_.GetLocation(); float position[] = {vec.X(), vec.Y(), vec.Z(), 1.0f}; BuildShadowMatrix(shadow_matrix, position, shadow_plane); glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.1f, 0.1f, 0.1f, 0.8f); glPushMatrix(); glTranslatef(0.0f, -0.8f, 0.5f); glMultMatrixf(shadow_matrix); DrawSprites(); glPopMatrix(); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); }