Changeset 350
- Timestamp:
- 10/27/05 03:25:09 (19 years ago)
- Location:
- trunk/VUT
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/VUT/GtpVisibility/src/CoherentHierarchicalCullingManager.cpp
r348 r350 90 90 DecideVisible(node) && mHierarchyInterface->HasGeometry(node); 91 91 92 //if (mHierarchyInterface->LastVisited(node) == mHierarchyInterface->GetFrameId())92 //if (mHierarchyInterface->LastVisited(node) >= mHierarchyInterface->GetFrameId()) 93 93 // Ogre::LogManager::getSingleton().logMessage("error"); 94 94 -
trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
r349 r350 120 120 Termination { 121 121 # autopartition 122 maxRays 10122 maxRays 30 123 123 maxPolygons 0 124 124 maxDepth 100 -
trunk/VUT/GtpVisibilityPreprocessor/src/Mesh.cpp
r349 r350 343 343 if (!eq(Magnitude(plane.mNormal), 1.0f)) 344 344 return false; 345 346 return true; 345 347 } 346 348 -
trunk/VUT/GtpVisibilityPreprocessor/src/Pvs.h
r341 r350 37 37 int GetSize() {return (int)mEntries.size();} 38 38 bool Empty() {return mEntries.size() == 0;} 39 void Merge(const Pvs<T> &a );39 void Merge(const Pvs<T> &a, const Pvs<T> &b); 40 40 41 41 PvsData<T> *Find(T sample); … … 49 49 50 50 template <typename T> 51 void Pvs<T>::Merge(const Pvs<T> &a )51 void Pvs<T>::Merge(const Pvs<T> &a, const Pvs<T> &b) 52 52 { 53 std::map<T, PvsData<T>, LtSample<T> >::iterator it, it_end = mEntries.end(); 54 55 for (it = mEntries.begin(); it != mEntries.end(); ++ it) 56 { 57 // TODO 58 } 53 //std::merge(a.mEntries.begin(), a.mEntries.end(), 54 // b.mEntries.begin(), b.mEntries.end(), mEntries.begin()); 59 55 } 60 56 -
trunk/VUT/GtpVisibilityPreprocessor/src/Ray.h
r349 r350 25 25 enum { NO_INTERSECTION=0, INTERSECTION_OUT_OF_LIMITS, INTERSECTION }; 26 26 27 /// if ray is on back (front) side of plane, or goes from the front (back) to the back (front) 27 /// if ray is on back (front) side of plane, or goes from the 28 /// front (back) to the back (front) 28 29 enum {FRONT, BACK, BACK_FRONT, FRONT_BACK, COINCIDENT}; 29 30 -
trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp
r349 r350 161 161 cout<<ray<<endl; 162 162 } 163 164 // cout<<object->GetId()<<" "<<TimeDiff(t1, t2)<<endl;165 163 166 164 if (mViewCellsType == BSP_VIEW_CELLS) … … 419 417 420 418 // construct a ray 421 SetupRay(ray, point, direction, 422 collectSamplesForBsp ? Ray::LINE_SEGMENT : Ray::LOCAL_RAY); 419 SetupRay(ray, point, direction, Ray::LOCAL_RAY); 423 420 424 // also add origin to sample in order to extract it as input polygons425 if (0 && collectSamplesForBsp)426 {427 MeshInstance *meshInst = dynamic_cast<MeshInstance *>(object);428 ray.intersections.push_back(Ray::Intersection(0.0, meshInst, faceIndex));429 }430 431 421 sampleContributions = CastRay(object, ray); 432 422 433 423 //-- CORR matt: put block inside loop 434 424 if (sampleContributions) { 435 passContributingSamples ++;425 passContributingSamples ++; 436 426 passSampleContributions += sampleContributions; 437 427 } … … 455 445 if (collectSamplesForBsp) 456 446 { 447 // also add origin to sample in order to extract it as input polygons 448 MeshInstance *mi = dynamic_cast<MeshInstance *>(object); 449 ray.sourceObject = Ray::Intersection(0.0, mi, faceIndex); 450 457 451 mSampleRays.push_back(new Ray(ray)); 458 452 } … … 465 459 466 460 cout << "generated " << (int)mViewCells.size() << " view cells" << endl; 461 467 462 passContributingSamples += mBspTree->GetStat().contributingSamples; 468 passSampleContributions += mBspTree->GetStat(). pvs;463 passSampleContributions += mBspTree->GetStat().sampleContributions; 469 464 470 465 BspTreeStatistics(Debug); -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
r349 r350 165 165 else 166 166 DEL_PTR(*poly); 167 }168 169 int BspInterior::SplitRays(RayContainer &rays,170 RayContainer &frontRays,171 RayContainer &backRays,172 const AxisAlignedBox3 &box)173 {174 int splits = 0;175 176 while (!rays.empty())177 {178 Ray *ray = rays.back();179 rays.pop_back();180 181 //-- ray-plane intersection182 float maxT = 1e6;183 float minT = 0;184 185 // test with tree bounding box186 if (!box.GetMinMaxT(*ray, &minT, &maxT))187 continue;188 189 if (minT < 0) // start ray from origin190 minT = 0;191 192 // bound ray193 if ((ray->GetType() == Ray::LOCAL_RAY) &&194 (!ray->intersections.empty()) &&195 (ray->intersections[0].mT <= maxT))196 {197 maxT = ray->intersections[0].mT;198 }199 200 const int classification = ray->ClassifyPlane(mPlane, minT, maxT);201 202 ray->SetId(classification);203 204 switch (classification)205 {206 case Ray::COINCIDENT:207 break;208 case Ray::BACK:209 backRays.push_back(ray);210 break;211 case Ray::FRONT:212 frontRays.push_back(ray);213 break;214 case Ray::FRONT_BACK:215 ray->SetId(Ray::FRONT_BACK);216 backRays.push_back(ray);217 ++ splits;218 break;219 case Ray::BACK_FRONT:220 frontRays.push_back(ray);221 ++ splits;222 break;223 default:224 Debug << "Should not come here" << endl;225 break;226 }227 }228 229 return splits;230 167 } 231 168 … … 313 250 /* class BspLeaf implementation */ 314 251 /****************************************************************/ 315 BspLeaf::BspLeaf(): mViewCell(NULL) 316 { 317 } 318 319 BspLeaf::BspLeaf(ViewCell *viewCell): mViewCell(viewCell) 320 { 321 } 322 323 BspLeaf::BspLeaf(BspInterior *parent): BspNode(parent), mViewCell(NULL) 252 BspLeaf::BspLeaf(): mViewCell(NULL), mPiercingRays(0) 253 { 254 } 255 256 BspLeaf::BspLeaf(ViewCell *viewCell): 257 mViewCell(viewCell), mPiercingRays(0) 258 { 259 } 260 261 BspLeaf::BspLeaf(BspInterior *parent): 262 BspNode(parent), mViewCell(NULL), mPiercingRays(0) 324 263 {} 325 264 326 265 BspLeaf::BspLeaf(BspInterior *parent, ViewCell *viewCell): 327 BspNode(parent), mViewCell(viewCell) 266 BspNode(parent), mViewCell(viewCell), mPiercingRays(0) 328 267 { 329 268 } … … 344 283 } 345 284 346 int BspLeaf::GenerateViewCell(const RayContainer &rays) 347 { 348 int contributingSamples = 0; 285 void BspLeaf::GenerateViewCell(const RayContainer &rays, 286 int &sampleContributions, 287 int &contributingSamples) 288 { 289 sampleContributions = 0; 290 contributingSamples = 0; 349 291 350 292 mViewCell = new ViewCell(); … … 355 297 for (it = rays.begin(); it != it_end; ++ it) 356 298 { 299 int contribution = 0; 300 357 301 if (!(*it)->intersections.empty()) 358 302 { 359 if (mViewCell->GetPvs().AddSample((*it)->intersections[0].mObject) > 0) 360 ++ contributingSamples; 361 } 362 } 363 364 return contributingSamples; 303 contribution += mViewCell->GetPvs().AddSample((*it)->intersections[0].mObject); 304 } 305 306 contribution += mViewCell->GetPvs().AddSample((*it)->sourceObject.mObject); 307 308 if (contribution > 0) 309 { 310 sampleContributions += contribution; 311 ++ contributingSamples; 312 } 313 } 365 314 } 366 315 … … 371 320 372 321 BspTree::BspTree(ViewCell *viewCell): 373 mRootCell(viewCell), mRoot(NULL), mGenerateViewCells(false) 322 mRootCell(viewCell), mRoot(NULL), mGenerateViewCells(false), 323 mStorePiercingRays(true) 374 324 { 375 325 Randomize(); // initialise random generator for heuristics … … 638 588 639 589 long startTime = GetTime(); 590 640 591 Debug << "**** Extracting polygons from rays ****\n"; 641 592 … … 649 600 rays->push_back(ray); 650 601 602 //Debug << "extracting ray with intersections" << ray->intersections.size() << endl; 603 651 604 // get ray-face intersection. Store polygon representing the rays together 652 605 // with rays intersecting the face. … … 656 609 Face *face = obj->GetMesh()->mFaces[ray->intersections[0].mFace]; 657 610 658 std::map<Face *, Polygon3 *>::iterator it = facePolyMap.find(face);611 std::map<Face *, Polygon3 *>::iterator it = facePolyMap.find(face); 659 612 660 613 if (it != facePolyMap.end()) … … 721 674 // generate new view cell for each leaf 722 675 if (mGenerateViewCells) 723 mStat.contributingSamples += leaf->GenerateViewCell(*tData.mRays); 676 { 677 int conSamp, sampCon; 678 leaf->GenerateViewCell(*tData.mRays, conSamp, sampCon); 679 680 mStat.contributingSamples += conSamp; 681 mStat.sampleContributions += sampCon; 682 } 724 683 else 684 { 725 685 // add view cell to leaf 726 686 leaf->SetViewCell(tData.mViewCell); 687 } 688 689 EvaluateLeafStats(tData); 727 690 728 EvaluateLeafStats(tData);729 730 691 //-- clean up 692 731 693 // remaining polygons are discarded or added to node 732 694 leaf->ProcessPolygons(tData.mPolygons, sStoreSplitPolys); 733 695 DEL_PTR(tData.mPolygons); 696 697 if (mStorePiercingRays) 698 { 699 RayContainer::const_iterator it, it_end = tData.mRays->end(); 700 for (it = tData.mRays->begin(); it != it_end; ++ it) 701 { 702 leaf->mPiercingRays.push_back(*it); 703 } 704 } 734 705 DEL_PTR(tData.mRays); 735 706 … … 852 823 853 824 // subdivide rays into front and back rays 854 interior->SplitRays(rays, frontRays, backRays, mBox);825 SplitRays(interior->mPlane, rays, frontRays, backRays); 855 826 856 827 // split polygons with split plane … … 1096 1067 1097 1068 // swap candidates to avoid testing same plane 2 times 1098 Polygon3 *p = polys[candidateIdx]; 1069 std::swap(polys[currentIdx], polys[candidateIdx]); 1070 1071 /*Polygon3 *p = polys[candidateIdx]; 1099 1072 polys[candidateIdx] = polys[currentIdx]; 1100 polys[currentIdx] = p; 1073 polys[currentIdx] = p;*/ 1101 1074 1102 1075 return currentIdx; … … 1219 1192 } 1220 1193 1194 bool BspTree::BoundRay(const Ray &ray, float &minT, float &maxT) const 1195 { 1196 maxT = 1e6; 1197 minT = 0; 1198 1199 // test with tree bounding box 1200 if (!mBox.GetMinMaxT(ray, &minT, &maxT)) 1201 return false; 1202 1203 if (minT < 0) // start ray from origin 1204 minT = 0; 1205 1206 //Debug << "ray intersections " << ray.intersections.size() << endl; 1207 // bound ray or line segment 1208 if ((ray.GetType() == Ray::LOCAL_RAY) && 1209 !ray.intersections.empty() && 1210 (ray.intersections[0].mT <= maxT)) 1211 { 1212 maxT = ray.intersections[0].mT; 1213 } 1214 1215 return true; 1216 } 1217 1221 1218 float BspTree::SplitPlaneCost(const Plane3 &candidatePlane, 1222 1219 const RayContainer &rays) const … … 1233 1230 Ray *ray = *rit; 1234 1231 1235 float maxT = 1e6; 1236 float minT = 0; 1237 1238 // test with tree bounding box 1239 if (!mBox.GetMinMaxT(*ray, &minT, &maxT)) 1232 float minT, maxT; 1233 if (!BoundRay(*ray, minT, maxT)) 1240 1234 continue; 1241 if (minT < 0) // start ray from origin1242 minT = 0;1243 1244 // bound ray1245 if ((ray->GetType() == Ray::LOCAL_RAY) &&1246 (!ray->intersections.empty()) &&1247 (ray->intersections[0].mT <= maxT))1248 {1249 maxT = ray->intersections[0].mT;1250 }1251 1235 1252 1236 const int classification = … … 1438 1422 } 1439 1423 1440 //#ifdef _DEBUG1424 #ifdef _DEBUG 1441 1425 Debug << "BSP stats: " 1442 1426 << "Depth: " << data.mDepth << " (max: " << sTermMaxDepth << "), " 1443 1427 << "#polygons: " << (int)data.mPolygons->size() << " (max: " << sTermMaxPolygons << "), " 1444 1428 << "#rays: " << (int)data.mRays->size() << " (max: " << sTermMaxRays << ")" << endl; 1445 //#endif1429 #endif 1446 1430 } 1447 1431 … … 1452 1436 stack<BspRayTraversalData> tStack; 1453 1437 1454 float maxt = 1e6; 1455 float mint = 0; 1456 1438 float maxt, mint; 1439 1457 1440 Intersectable::NewMail(); 1458 1441 1459 // test with tree bounding box 1460 if (!mBox.GetMinMaxT(ray, &mint, &maxt)) 1461 return 0; 1462 1463 if (mint < 0) // start ray from origin 1464 mint = 0; 1465 1466 // bound ray 1467 if ((ray.GetType() == Ray::LOCAL_RAY) && 1468 (!ray.intersections.empty()) && 1469 (ray.intersections[0].mT <= maxt)) 1470 { 1471 maxt = ray.intersections[0].mT; 1472 } 1473 1442 BoundRay(ray, mint, maxt); 1443 1474 1444 Vector3 entp = ray.Extrap(mint); 1475 1445 Vector3 extp = ray.Extrap(maxt); … … 1608 1578 { 1609 1579 stack<BspNode *> nodeStack; 1610 stack<BspLeaf *> leafStack;1611 1612 1580 nodeStack.push(mRoot); 1613 1614 // collect leaves 1581 1582 BspLeaf *rightLeaf = NULL; 1583 1615 1584 while (!nodeStack.empty()) 1616 1585 { 1617 1586 BspNode *node = nodeStack.top(); 1618 1619 1587 nodeStack.pop(); 1620 1588 1621 if (node->IsLeaf()) 1622 { 1623 BspNode *leaf = dynamic_cast<BspLeaf *>(node); 1624 1625 // get other leaf we can merge with 1626 while (!leafStack.empty() && leafStack.top()->mParent == node->mParent) 1627 { 1628 leafStack.pop(); 1629 BspNode *mergedNode = MergeNodes(node->mParent); 1630 1631 if (mergedNode->IsLeaf()) 1632 leafStack.push(dynamic_cast<BspLeaf *>(mergedNode)); 1633 else 1634 leafStack.push(dynamic_cast<BspLeaf *>(node)); 1635 } 1636 } 1637 else 1589 if (node->IsLeaf()) 1590 { 1591 BspLeaf *leaf = dynamic_cast<BspLeaf *>(node); 1592 1593 if (rightLeaf && MergeNecessary(leaf, rightLeaf)) 1594 MergeLeafs(leaf, rightLeaf); 1595 } 1596 else 1638 1597 { 1639 1598 BspInterior *interior = dynamic_cast<BspInterior *>(node); 1599 1640 1600 nodeStack.push(interior->mFront); 1641 1601 nodeStack.push(interior->mBack); 1642 1602 } 1643 1603 } 1644 1645 1604 return 0; 1646 1605 } … … 1648 1607 bool BspTree::MergeNecessary(BspLeaf *front, BspLeaf *back) const 1649 1608 { 1609 //if (Raydiff 1650 1610 return true; 1651 1611 } 1652 1612 1653 BspNode *BspTree::MergeNodes(BspInterior *node) 1654 { 1655 BspLeaf *front = dynamic_cast<BspLeaf *>(node->mFront); 1656 BspLeaf *back = dynamic_cast<BspLeaf *>(node->mBack); 1657 1658 if (!MergeNecessary(front, back)) 1659 return node; 1613 void BspTree::MergeLeafs(BspLeaf *front, BspLeaf *back) 1614 { 1615 //std::merge(front->mPvs.mEntries.begin(), back->mPvs.mEntries.begin()); 1616 ViewCell *viewCell = new ViewCell(); 1617 viewCell->GetPvs().Merge(front->mViewCell->GetPvs(), back->mViewCell->GetPvs()); 1660 1618 1661 1619 DEL_PTR(front->mViewCell); 1662 DEL_PTR(front); 1620 DEL_PTR(back->mViewCell); 1621 1622 front->SetViewCell(viewCell); 1623 back->SetViewCell(viewCell); 1624 } 1625 1626 void BspTree::SetGenerateViewCells(int generateViewCells) 1627 { 1628 mGenerateViewCells = generateViewCells; 1629 } 1630 1631 BspTreeStatistics &BspTree::GetStat() 1632 { 1633 return mStat; 1634 } 1635 1636 int BspTree::SplitRays(const Plane3 &plane, 1637 RayContainer &rays, 1638 RayContainer &frontRays, 1639 RayContainer &backRays) 1640 { 1641 int splits = 0; 1642 1643 while (!rays.empty()) 1644 { 1645 Ray *ray = rays.back(); 1646 rays.pop_back(); 1647 1648 //-- ray-plane intersection 1649 float maxT, minT; 1650 1651 if (!BoundRay(*ray, minT, maxT)) 1652 continue; 1653 1654 const int classification = ray->ClassifyPlane(plane, minT, maxT); 1663 1655 1664 DEL_PTR(back->mViewCell); 1665 DEL_PTR(back); 1666 1667 BspLeaf *leaf = new BspLeaf(new ViewCell()); 1668 BspInterior *parent = node->GetParent(); 1669 1670 // replace a link from node's parent 1671 if (!node->IsRoot()) 1672 { 1673 parent->ReplaceChildLink(node, leaf); 1674 node->SetParent(parent); 1675 } 1676 else // new root 1677 { 1678 mRoot = leaf; 1679 } 1680 1681 return leaf; 1682 } 1683 1684 /*BspNode *BspTree::MergeNodes(BspNode *node) 1685 { 1686 BspNode *front = MergeNodes(dynamic_cast<BspInterior *>(node)->mFront); 1687 BspNode *back = MergeNodes(dynamic_cast<BspInterior *>(node)->mBack); 1688 1689 if (!front->IsLeaf() && !back->IsLeaf()) 1690 1691 { 1692 if (!MergeNecessary(front, back)) 1693 return node; 1694 1695 DEL_PTR(front->mViewCell); 1696 DEL_PTR(front); 1697 1698 DEL_PTR(back->mViewCell); 1699 DEL_PTR(back); 1700 1701 BspLeaf *leaf = new BspLeaf(new ViewCell()); 1702 BspInterior *parent = node->GetParent(); 1703 1704 // replace a link from node's parent 1705 if (!node->IsRoot()) 1706 { 1707 parent->ReplaceChildLink(node, leaf); 1708 node->SetParent(parent); 1709 } 1710 else // new root 1711 { 1712 mRoot = leaf; 1713 } 1714 1715 return leaf; 1716 } 1717 1718 return node; 1719 }*/ 1720 1721 void BspTree::SetGenerateViewCells(int generateViewCells) 1722 { 1723 mGenerateViewCells = generateViewCells; 1724 } 1725 1726 BspTreeStatistics &BspTree::GetStat() 1727 { 1728 return mStat; 1729 } 1656 ray->SetId(classification); 1657 1658 switch (classification) 1659 { 1660 case Ray::COINCIDENT: 1661 break; 1662 case Ray::BACK: 1663 backRays.push_back(ray); 1664 break; 1665 case Ray::FRONT: 1666 frontRays.push_back(ray); 1667 break; 1668 case Ray::FRONT_BACK: 1669 ray->SetId(Ray::FRONT_BACK); 1670 backRays.push_back(ray); 1671 ++ splits; 1672 break; 1673 case Ray::BACK_FRONT: 1674 frontRays.push_back(ray); 1675 ++ splits; 1676 break; 1677 default: 1678 Debug << "Should not come here" << endl; 1679 break; 1680 } 1681 } 1682 1683 return splits; 1684 } -
trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
r349 r350 54 54 /// samples contributing to pvs 55 55 int contributingSamples; 56 /// sample contributions to pvs 57 int sampleContributions; 58 56 59 // Constructor 57 60 BspTreeStatistics() … … 77 80 pvs = 0; 78 81 contributingSamples = 0; 82 sampleContributions = 0; 79 83 } 80 84 … … 171 175 const bool storePolys = false); 172 176 173 /** Subdivides the rays into front and back rays according to the split plane.174 @param rays contains the rays to be split. The rays are175 distributed into front and back rays.176 @param frontRays returns rays on the front side of the plane177 @param backRays returns rays on the back side of the plane178 @param box the bounding box of the scene179 @returns the number of splits180 */181 int SplitRays(RayContainer &rays,182 RayContainer &frontRays,183 RayContainer &backRays,184 const AxisAlignedBox3 &box);185 186 177 /** Stores polygon in node or discards them according to storePolys. 187 178 @param polys the polygons … … 228 219 229 220 /** Generates new view cell and adds rays to the PVS. 230 @returns the number of samples contributing to the pvs. 231 */ 232 int GenerateViewCell(const RayContainer &rays); 221 @param sampleContributions the number contributions of the sampels 222 @param contributingSampels the number of contributing rays 223 */ 224 void BspLeaf::GenerateViewCell(const RayContainer &rays, 225 int &sampleContributions, 226 int &contributingSamples); 233 227 234 228 protected: … … 236 230 /// if NULL this does not correspond to feasible viewcell 237 231 ViewCell *mViewCell; 232 RayContainer mPiercingRays; 238 233 }; 239 234 … … 569 564 bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const; 570 565 566 /** Bounds ray and returns minT and maxT. 567 @returns true if ray hits BSP tree bounding box 568 */ 569 bool BoundRay(const Ray &ray, float &minT, float &maxT) const; 570 571 /** Subdivides the rays into front and back rays according to the split plane. 572 573 @param plane the split plane 574 @param rays contains the rays to be split. The rays are 575 distributed into front and back rays. 576 @param frontRays returns rays on the front side of the plane 577 @param backRays returns rays on the back side of the plane 578 579 @returns the number of splits 580 */ 581 int SplitRays(const Plane3 &plane, 582 RayContainer &rays, 583 RayContainer &frontRays, 584 RayContainer &backRays); 585 586 void MergeLeafs(BspLeaf *front, BspLeaf *back); 587 571 588 /// Pointer to the root of the tree 572 589 BspNode *mRoot; … … 596 613 /// view cell corresponding to unbounded space 597 614 ViewCell *mRootCell; 615 598 616 /// should view cells be stored or generated in the leaves? 599 617 bool mGenerateViewCells; 618 619 /// if rays should be stored that are piercing this view cell 620 bool mStorePiercingRays; 600 621 601 622 public: -
trunk/VUT/work/TestCullingTerrain/TestCullingTerrainApplication.cpp
r347 r350 306 306 // the objects are generated randomly distributed over the terrain 307 307 generateScene(1000, 0); // create soldiers, trees, ninjas 308 generateScene( 1000, 1);309 generateScene( 200, 2);308 generateScene(500, 1); 309 generateScene(100, 2); 310 310 } 311 311 } -
trunk/VUT/work/ogre_changes/Plugins/OctreeSceneManager/src/OgreOctree.cpp
r347 r350 105 105 #ifdef GTP_VISIBILITY_MODIFIED_OGRE 106 106 // update bounds because we want tight octree 107 if (1) _updateBounds();107 _updateBounds(); 108 108 109 109 #endif //GTP_VISIBILITY_MODIFIED_OGRE -
trunk/VUT/work/ogre_changes/RenderSystems/GL/src/OgreGLRenderSystem.cpp
r347 r350 2344 2344 glDisableVertexAttribArrayARB_ptr(1); // disable weights 2345 2345 } 2346 glColor4f(1,1,1,1); 2346 2347 2347 glSecondaryColor3fEXT_ptr(0.0f, 0.0f, 0.0f); 2348 2348
Note: See TracChangeset
for help on using the changeset viewer.