本文整理汇总了C++中NvStripInfoVec类的典型用法代码示例。如果您正苦于以下问题:C++ NvStripInfoVec类的具体用法?C++ NvStripInfoVec怎么用?C++ NvStripInfoVec使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了NvStripInfoVec类的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: RemoveSmallStrips
////////////////////////////////////////////////////////////////////////////////////////
// RemoveSmallStrips()
//
// allStrips is the whole strip _vector_...all small strips will be deleted from this list, to avoid leaking mem
// allBigStrips is an out parameter which will contain all strips above minStripLength
// faceList is an out parameter which will contain all faces which were removed from the striplist
//
void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList)
{
faceList.clear();
allBigStrips.clear(); //make sure these are empty
NvFaceInfoVec tempFaceList;
for(int i = 0; i < allStrips.size(); i++)
{
if(allStrips[i]->m_faces.size() < minStripLength)
{
//strip is too small, add faces to faceList
for(int j = 0; j < allStrips[i]->m_faces.size(); j++)
tempFaceList.push_back(allStrips[i]->m_faces[j]);
//and xr_free memory
xr_delete(allStrips[i]);
}
else
{
allBigStrips.push_back(allStrips[i]);
}
}
bool *bVisitedList = xr_alloc<bool> (tempFaceList.size());
ZeroMemory (bVisitedList, tempFaceList.size()*sizeof(bool));
VertexCache* vcache = xr_new<VertexCache> (cacheSize);
int bestNumHits = -1;
int numHits = 0;
int bestIndex = 0;
while(1)
{
bestNumHits = -1;
//find best face to add next, given the current cache
for(int i = 0; i < tempFaceList.size(); i++)
{
if(bVisitedList[i])
continue;
numHits = CalcNumHitsFace(vcache, tempFaceList[i]);
if(numHits > bestNumHits)
{
bestNumHits = numHits;
bestIndex = i;
}
}
if(bestNumHits == -1.0f)
break;
bVisitedList[bestIndex] = true;
UpdateCacheFace(vcache, tempFaceList[bestIndex]);
faceList.push_back(tempFaceList[bestIndex]);
}
xr_delete (vcache);
xr_free (bVisitedList);
}
示例2: FindGoodResetPoint
void NvStripifier::Stripify(const WordVec &in_indices, const int in_cacheSize,
const int in_minStripLength, const unsigned short maxIndex,
NvStripInfoVec &outStrips, NvFaceInfoVec& outFaceList)
{
meshJump = 0.0f;
bFirstTimeResetPoint = true; //used in FindGoodResetPoint()
//the number of times to run the experiments
int numSamples = 10;
int i;
//the cache size, clamped to one
cacheSize = max(1, in_cacheSize - CACHE_INEFFICIENCY);
minStripLength = in_minStripLength; //this is the strip size threshold below which we dump the strip into a list
indices = in_indices;
// build the stripification info
NvFaceInfoVec allFaceInfos;
NvEdgeInfoVec allEdgeInfos;
BuildStripifyInfo(allFaceInfos, allEdgeInfos, maxIndex);
NvStripInfoVec allStrips;
// stripify
FindAllStrips(allStrips, allFaceInfos, allEdgeInfos, numSamples);
//split up the strips into cache friendly pieces, optimize them, then dump these into outStrips
SplitUpStripsAndOptimize(allStrips, outStrips, allEdgeInfos, outFaceList);
//clean up
for(i = 0; i < allStrips.size(); i++)
{
delete allStrips[i];
}
for (i = 0; i < allEdgeInfos.size(); i++)
{
NvEdgeInfo *info = allEdgeInfos[i];
while (info != NULL)
{
NvEdgeInfo *next = (info->m_v0 == i ? info->m_nextV0 : info->m_nextV1);
info->Unref();
info = next;
}
}
}
示例3: AvgStripSize
///////////////////////////////////////////////////////////////////////////////////////////
// AvgStripSize()
//
// Finds the average strip size of the input _vector_ of strips
//
float NvStripifier::AvgStripSize(const NvStripInfoVec &strips){
int sizeAccum = 0;
int numStrips = strips.size();
for (int i = 0; i < numStrips; i++){
NvStripInfo *strip = strips[i];
sizeAccum += strip->m_faces.size();
}
return ((float)sizeAccum) / ((float)numStrips);
}
示例4: CommitStrips
///////////////////////////////////////////////////////////////////////////////////////////
// CommitStrips()
//
// "Commits" the input strips by setting their m_experimentId to -1 and adding to the allStrips
// vector
//
void NvStripifier::CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips)
{
// Iterate through strips
size_t numStrips = strips.size();
for (size_t i = 0; i < numStrips; i++){
// Tell the strip that it is now real
NvStripInfo *strip = strips[i];
strip->m_experimentId = -1;
// add to the list of real strips
allStrips.push_back(strip);
// Iterate through the faces of the strip
// Tell the faces of the strip that they belong to a real strip now
const NvFaceInfoVec &faces = strips[i]->m_faces;
size_t numFaces = faces.size();
for (size_t j = 0; j < numFaces; j++)
{
strip->MarkTriangle(faces[j]);
}
}
}
示例5: Cleanup
////////////////////////////////////////////////////////////////////////////////////////
//Cleanup strips / faces, used by generatestrips
void Cleanup(NvStripInfoVec& tempStrips, NvFaceInfoVec& tempFaces)
{
//delete strips
for(size_t i = 0; i < tempStrips.size(); i++)
{
for(size_t j = 0; j < tempStrips[i]->m_faces.size(); j++)
{
delete tempStrips[i]->m_faces[j];
tempStrips[i]->m_faces[j] = NULL;
}
tempStrips[i]->m_faces.resize(0);
delete tempStrips[i];
tempStrips[i] = NULL;
}
//delete faces
for(size_t i = 0; i < tempFaces.size(); i++)
{
delete tempFaces[i];
tempFaces[i] = NULL;
}
}
示例6: GenerateStrips
////////////////////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled)
{
int i = 0;
//put data in format that the stripifier likes
WordVec tempIndices;
tempIndices.resize(in_numIndices);
unsigned short maxIndex = 0;
unsigned short minIndex = 0xFFFF;
for(i = 0; i < in_numIndices; i++)
{
tempIndices[i] = in_indices[i];
if (in_indices[i] > maxIndex)
maxIndex = in_indices[i];
if (in_indices[i] < minIndex)
minIndex = in_indices[i];
}
NvStripInfoVec tempStrips;
NvFaceInfoVec tempFaces;
NvStripifier stripifier;
//do actual stripification
stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
//stitch strips together
IntVec stripIndices;
unsigned int numSeparateStrips = 0;
if(bListsOnly)
{
//if we're outputting only lists, we're done
*numGroups = 1;
(*primGroups) = new PrimitiveGroup[*numGroups];
PrimitiveGroup* primGroupArray = *primGroups;
//count the total number of indices
unsigned int numIndices = 0;
for(i = 0; i < tempStrips.size(); i++)
{
numIndices += tempStrips[i]->m_faces.size() * 3;
}
//add in the list
numIndices += tempFaces.size() * 3;
primGroupArray[0].type = PT_LIST;
primGroupArray[0].numIndices = numIndices;
primGroupArray[0].indices = new unsigned short[numIndices];
//do strips
unsigned int indexCtr = 0;
for(i = 0; i < tempStrips.size(); i++)
{
for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
{
//degenerates are of no use with lists
if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
{
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2;
}
else
{
//we've removed a tri, reduce the number of indices
primGroupArray[0].numIndices -= 3;
}
}
}
//do lists
for(i = 0; i < tempFaces.size(); i++)
{
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2;
}
}
else
{
stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips, bRestart, restartVal);
//if we're stitching strips together, we better get back only one strip from CreateStrips()
assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
//convert to output format
*numGroups = numSeparateStrips; //for the strips
if(tempFaces.size() != 0)
//.........这里部分代码省略.........
示例7: CreateStrips
////////////////////////////////////////////////////////////////////////////////////////
// CreateStrips()
//
// Generates actual strips from the list-in-strip-order.
//
void NvStripifier::CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices,
const bool bStitchStrips, unsigned int& numSeparateStrips,
const bool bRestart, const unsigned int restartVal)
{
assert(numSeparateStrips == 0);
NvFaceInfo tLastFace(0, 0, 0);
NvFaceInfo tPrevStripLastFace(0, 0, 0);
size_t nStripCount = allStrips.size();
//we infer the cw/ccw ordering depending on the number of indices
//this is screwed up by the fact that we insert -1s to denote changing strips
//this is to account for that
int accountForNegatives = 0;
for (size_t i = 0; i < nStripCount; i++)
{
NvStripInfo *strip = allStrips[i];
int nStripFaceCount = strip->m_faces.size();
assert(nStripFaceCount > 0);
// Handle the first face in the strip
{
NvFaceInfo tFirstFace(strip->m_faces[0]->m_v0, strip->m_faces[0]->m_v1, strip->m_faces[0]->m_v2);
// If there is a second face, reorder vertices such that the
// unique vertex is first
if (nStripFaceCount > 1)
{
int nUnique = NvStripifier::GetUniqueVertexInB(strip->m_faces[1], &tFirstFace);
if (nUnique == tFirstFace.m_v1)
{
SWAP(tFirstFace.m_v0, tFirstFace.m_v1);
}
else if (nUnique == tFirstFace.m_v2)
{
SWAP(tFirstFace.m_v0, tFirstFace.m_v2);
}
// If there is a third face, reorder vertices such that the
// shared vertex is last
if (nStripFaceCount > 2)
{
if(IsDegenerate(strip->m_faces[1]))
{
int pivot = strip->m_faces[1]->m_v1;
if(tFirstFace.m_v1 == pivot)
{
SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
}
}
else
{
int nShared0, nShared1;
GetSharedVertices(strip->m_faces[2], &tFirstFace, &nShared0, &nShared1);
if ( (nShared0 == tFirstFace.m_v1) && (nShared1 == -1) )
{
SWAP(tFirstFace.m_v1, tFirstFace.m_v2);
}
}
}
}
if( (i == 0) || !bStitchStrips || bRestart)
{
if(!IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
stripIndices.push_back(tFirstFace.m_v0);
}
else
{
// Double tap the first in the new strip
stripIndices.push_back(tFirstFace.m_v0);
// Check CW/CCW ordering
if (NextIsCW(stripIndices.size() - accountForNegatives) != IsCW(strip->m_faces[0], tFirstFace.m_v0, tFirstFace.m_v1))
{
stripIndices.push_back(tFirstFace.m_v0);
}
}
stripIndices.push_back(tFirstFace.m_v0);
stripIndices.push_back(tFirstFace.m_v1);
stripIndices.push_back(tFirstFace.m_v2);
// Update last face info
tLastFace = tFirstFace;
}
for (int j = 1; j < nStripFaceCount; j++)
{
int nUnique = GetUniqueVertexInB(&tLastFace, strip->m_faces[j]);
if (nUnique != -1)
{
stripIndices.push_back(nUnique);
//.........这里部分代码省略.........
示例8: RemoveSmallStrips
////////////////////////////////////////////////////////////////////////////////////////
// RemoveSmallStrips()
//
// allStrips is the whole strip vector...all small strips will be deleted from this list, to avoid leaking mem
// allBigStrips is an out parameter which will contain all strips above minStripLength
// faceList is an out parameter which will contain all faces which were removed from the striplist
//
void NvStripifier::RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList)
{
faceList.clear();
allBigStrips.clear(); //make sure these are empty
NvFaceInfoVec tempFaceList;
for(size_t i = 0; i < allStrips.size(); i++)
{
if(allStrips[i]->m_faces.size() < (size_t)minStripLength)
{
//strip is too small, add faces to faceList
for(size_t j = 0; j < allStrips[i]->m_faces.size(); j++)
tempFaceList.push_back(allStrips[i]->m_faces[j]);
//and free memory
delete allStrips[i];
}
else
{
allBigStrips.push_back(allStrips[i]);
}
}
if(tempFaceList.size())
{
bool *bVisitedList = new bool[tempFaceList.size()];
memset(bVisitedList, 0, tempFaceList.size()*sizeof(bool));
VertexCache* vcache = new VertexCache(cacheSize);
int bestNumHits = -1;
int numHits;
int bestIndex;
while(1)
{
bestNumHits = -1;
//find best face to add next, given the current cache
for(size_t i = 0; i < tempFaceList.size(); i++)
{
if(bVisitedList[i])
continue;
numHits = CalcNumHitsFace(vcache, tempFaceList[i]);
if(numHits > bestNumHits)
{
bestNumHits = numHits;
bestIndex = i;
}
}
if(bestNumHits == -1.0f)
break;
bVisitedList[bestIndex] = true;
UpdateCacheFace(vcache, tempFaceList[bestIndex]);
faceList.push_back(tempFaceList[bestIndex]);
}
delete vcache;
delete[] bVisitedList;
}
}
示例9: startInfo
///////////////////////////////////////////////////////////////////////////////////////////
// SplitUpStripsAndOptimize()
//
// Splits the input vector of strips (allBigStrips) into smaller, cache friendly pieces, then
// reorders these pieces to maximize cache hits
// The final strips are output through outStrips
//
void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips,
NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList)
{
int threshold = cacheSize;
NvStripInfoVec tempStrips;
//split up strips into threshold-sized pieces
for(size_t i = 0; i < allStrips.size(); i++)
{
NvStripInfo* currentStrip;
NvStripStartInfo startInfo(NULL, NULL, false);
int actualStripSize = 0;
for(size_t j = 0; j < allStrips[i]->m_faces.size(); ++j)
{
if( !IsDegenerate(allStrips[i]->m_faces[j]) )
actualStripSize++;
}
if(actualStripSize /*allStrips[i]->m_faces.size()*/ > threshold)
{
int numTimes = actualStripSize /*allStrips[i]->m_faces.size()*/ / threshold;
int numLeftover = actualStripSize /*allStrips[i]->m_faces.size()*/ % threshold;
int degenerateCount = 0;
int j = 0;
for(; j < numTimes; j++)
{
currentStrip = new NvStripInfo(startInfo, 0, -1);
int faceCtr = j*threshold + degenerateCount;
bool bFirstTime = true;
while(faceCtr < threshold+(j*threshold)+degenerateCount)
{
if(IsDegenerate(allStrips[i]->m_faces[faceCtr]))
{
degenerateCount++;
//last time or first time through, no need for a degenerate
if( (((faceCtr + 1) != threshold+(j*threshold)+degenerateCount) ||
((j == numTimes - 1) && (numLeftover < 4) && (numLeftover > 0))) &&
!bFirstTime)
{
currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
}
else
{
//but, we do need to delete the degenerate, if it's marked fake, to avoid leaking
if(allStrips[i]->m_faces[faceCtr]->m_bIsFake)
{
delete allStrips[i]->m_faces[faceCtr], allStrips[i]->m_faces[faceCtr] = NULL;
}
++faceCtr;
}
}
else
{
currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
bFirstTime = false;
}
}
/*
for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++)
{
currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]);
}
*/
if(j == numTimes - 1) //last time through
{
if( (numLeftover < 4) && (numLeftover > 0) ) //way too small
{
//just add to last strip
int ctr = 0;
while(ctr < numLeftover)
{
IsDegenerate( allStrips[i]->m_faces[faceCtr] ) ? ++degenerateCount : ++ctr;
currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr++]);
}
numLeftover = 0;
}
}
tempStrips.push_back(currentStrip);
}
int leftOff = j * threshold + degenerateCount;
if(numLeftover != 0)
{
currentStrip = new NvStripInfo(startInfo, 0, -1);
int ctr = 0;
bool bFirstTime = true;
//.........这里部分代码省略.........
示例10: startInfo
///////////////////////////////////////////////////////////////////////////////////////////
// SplitUpStripsAndOptimize()
//
// Splits the input _vector_ of strips (allBigStrips) into smaller, cache friendly pieces, then
// reorders these pieces to maximize cache hits
// The final strips are output through outStrips
//
void NvStripifier::SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips,
NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList)
{
int threshold = cacheSize;
NvStripInfoVec tempStrips;
//split up strips into threshold-sized pieces
int i;
for(i = 0; i < allStrips.size(); i++)
{
NvStripInfo* currentStrip;
NvStripStartInfo startInfo(NULL, NULL, false);
if(allStrips[i]->m_faces.size() > threshold)
{
int numTimes = allStrips[i]->m_faces.size() / threshold;
int numLeftover = allStrips[i]->m_faces.size() % threshold;
int j;
for(j = 0; j < numTimes; j++)
{
currentStrip = xr_new<NvStripInfo> (startInfo, 0, -1);
for(int faceCtr = j*threshold; faceCtr < threshold+(j*threshold); faceCtr++) {
currentStrip->m_faces.push_back(allStrips[i]->m_faces[faceCtr]);
}
tempStrips.push_back(currentStrip);
}
int leftOff = j * threshold;
if(numLeftover != 0)
{
currentStrip = xr_new<NvStripInfo> (startInfo, 0, -1);
for(int k = 0; k < numLeftover; k++)
{
currentStrip->m_faces.push_back(allStrips[i]->m_faces[leftOff++]);
}
tempStrips.push_back(currentStrip);
}
}
else
{
//we're not just doing a tempStrips.push_back(allBigStrips[i]) because
// this way we can _delete allBigStrips later to xr_free the memory
currentStrip = xr_new<NvStripInfo> (startInfo, 0, -1);
for(int j = 0; j < allStrips[i]->m_faces.size(); j++)
currentStrip->m_faces.push_back(allStrips[i]->m_faces[j]);
tempStrips.push_back(currentStrip);
}
}
//add small strips to face list
NvStripInfoVec tempStrips2;
RemoveSmallStrips(tempStrips, tempStrips2, outFaceList);
outStrips.clear();
if(tempStrips2.size() != 0)
{
//Optimize for the vertex cache
VertexCache* vcache = xr_new<VertexCache> (cacheSize);
float bestNumHits = -1.0f;
float numHits = 0;
int bestIndex = 0;
int firstIndex = 0;
float minCost = 10000.0f;
for(i = 0; i < tempStrips2.size(); i++)
{
int numNeighbors = 0;
//find strip with least number of neighbors per face
for(int j = 0; j < tempStrips2[i]->m_faces.size(); j++)
{
numNeighbors += NumNeighbors(tempStrips2[i]->m_faces[j], edgeInfos);
}
float currCost = (float)numNeighbors / (float)tempStrips2[i]->m_faces.size();
if(currCost < minCost)
{
minCost = currCost;
firstIndex = i;
}
}
//.........这里部分代码省略.........
示例11: GenerateStrips
////////////////////////////////////////////////////////////////////////////////////////
// GenerateStrips()
//
// in_indices: input index list, the indices you would use to render
// in_numIndices: number of entries in in_indices
// primGroups: array of optimized/stripified PrimitiveGroups
// numGroups: number of groups returned
//
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
//
void GenerateStrips(const U16* in_indices, const U32 in_numIndices,
PrimitiveGroup** primGroups, U16* numGroups)
{
//put data in format that the stripifier likes
WordVec tempIndices;
tempIndices.resize(in_numIndices);
U16 maxIndex = 0;
U32 i;
for(i = 0; i < in_numIndices; i++)
{
tempIndices[i] = in_indices[i];
if(in_indices[i] > maxIndex)
maxIndex = in_indices[i];
}
NvStripInfoVec tempStrips;
NvFaceInfoVec tempFaces;
NvStripifier stripifier;
//do actual stripification
stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
//stitch strips together
IntVec stripIndices;
U32 numSeparateStrips = 0;
if(bListsOnly)
{
//if we're outputting only lists, we're done
*numGroups = 1;
(*primGroups) = new PrimitiveGroup[*numGroups];
PrimitiveGroup* primGroupArray = *primGroups;
//count the total number of indices
U32 numIndices = 0;
U32 i;
for(i = 0; i < tempStrips.size(); i++)
{
numIndices += tempStrips[i]->m_faces.size() * 3;
}
//add in the list
numIndices += tempFaces.size() * 3;
primGroupArray[0].type = PT_LIST;
primGroupArray[0].numIndices = numIndices;
primGroupArray[0].indices = new U16[numIndices];
//do strips
U32 indexCtr = 0;
for(U32 k = 0; k < tempStrips.size(); k++)
{
for(U32 j = 0; j < tempStrips[i]->m_faces.size(); j++)
{
//degenerates are of no use with lists
if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
{
primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempStrips[k]->m_faces[j]->m_v2;
}
else
{
//we've removed a tri, reduce the number of indices
primGroupArray[0].numIndices -= 3;
}
}
}
//do lists
for(i = 0; i < tempFaces.size(); i++)
{
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1;
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2;
}
}
else
{
stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips);
//if we're stitching strips together, we better get back only one strip from CreateStrips()
assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
//convert to output format
*numGroups = numSeparateStrips; //for the strips
if(tempFaces.size() != 0)
(*numGroups)++; //we've got a list as well, increment
(*primGroups) = new PrimitiveGroup[*numGroups];
//.........这里部分代码省略.........