void TreeLoader2D::loadPage(PageInfo &page) { //Calculate x/z indexes for the grid array page.xIndex -= Math::Floor(gridBounds.left / pageSize); page.zIndex -= Math::Floor(gridBounds.top / pageSize); //Check if the requested page is in bounds if (page.xIndex < 0 || page.zIndex < 0 || page.xIndex >= pageGridX || page.zIndex >= pageGridZ) return; //For each tree type... PageGridListIterator i; for (i = pageGridList.begin(); i != pageGridList.end(); ++i) { //Get the appropriate tree list for the specified page std::vector<TreeDef> *pageGrid = i->second; std::vector<TreeDef> &treeList = _getGridPage(pageGrid, page.xIndex, page.zIndex); Entity *entity = i->first; //Load the listed trees into the page std::vector<TreeDef>::iterator o; for (o = treeList.begin(); o != treeList.end(); ++o) { //Get position Vector3 pos; pos.x = page.bounds.left + ((Real)o->xPos / 65535) * pageSize; pos.z = page.bounds.top + ((Real)o->zPos / 65535) * pageSize; //Calculate terrain height at pos.x / pos.z to get pos.y if (heightFunction != NULL) pos.y = heightFunction(pos.x, pos.z, heightFunctionUserData); else pos.y = 0.0f; //Get rotation Degree angle((Real)o->rotation * (360.0f / 255)); Quaternion rot(angle, Vector3::UNIT_Y); //Get scale Vector3 scale; scale.y = (Real)o->scale * (maximumScale / 255) + minimumScale; scale.x = scale.y; scale.z = scale.y; //Get color ColourValue color; if (colorMap) color = colorMap->getColorAt_Unpacked(pos.x, pos.z, actualBounds); else color = ColourValue::White; addEntity(entity, pos, rot, scale, color); } } }
Mesh *GrassLoader::generateGrass_SPRITE(PageInfo &page, GrassLayer *layer, float *grassPositions, unsigned int grassCount) { //Calculate the number of quads to be added unsigned int quadCount; quadCount = grassCount; // check for overflows of the uint16's unsigned int maxUInt16 = std::numeric_limits<uint16>::max(); if(grassCount > maxUInt16) { LogManager::getSingleton().logMessage("grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } if(quadCount > maxUInt16) { LogManager::getSingleton().logMessage("quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } //Create manual mesh to store grass quads MeshPtr mesh = MeshManager::getSingleton().createManual(getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = false; //Setup vertex format information subMesh->vertexData = new VertexData; subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = 4 * quadCount; VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration; size_t offset = 0; dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); dcl->addElement(0, offset, VET_FLOAT4, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT4); dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE); offset += VertexElement::getTypeSize(VET_COLOUR); dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES); offset += VertexElement::getTypeSize(VET_FLOAT2); //Populate a new vertex buffer with grass HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton() .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); //Calculate size variance float rndWidth = layer->maxWidth - layer->minWidth; float rndHeight = layer->maxHeight - layer->minHeight; float minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY; float *posPtr = grassPositions; //Position array "iterator" for (uint16 i = 0; i < grassCount; ++i) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Calculate height float y; if (heightFunction){ y = heightFunction(x, z, heightFunctionUserData); } else { y = 0; } float x1 = (x - page.centerPoint.x); float z1 = (z - page.centerPoint.z); //Get the color at the grass position uint32 color; if (layer->colorMap) color = layer->colorMap->getColorAt(x, z, layer->mapBounds); else color = 0xFFFFFFFF; //Calculate size float rnd = *posPtr++; //The same rnd value is used for width and height to maintain aspect ratio float halfXScale = (layer->minWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer->minHeight + rndHeight * rnd); //Randomly mirror grass textures float uvLeft, uvRight; if (*posPtr++ > 0.5f){ uvLeft = 0; uvRight = 1; } else { uvLeft = 1; uvRight = 0; } //Add vertices *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 1; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 1; //uv //Update bounds if (y < minY) minY = y; if (y + scaleY > maxY) maxY = y + scaleY; } vbuf->unlock(); subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf); //Populate index buffer subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount = 6 * quadCount; subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton() .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); uint16* pI = static_cast<uint16*>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); for (uint16 i = 0; i < quadCount; ++i) { uint16 offset = i * 4; *pI++ = 0 + offset; *pI++ = 2 + offset; *pI++ = 1 + offset; *pI++ = 1 + offset; *pI++ = 2 + offset; *pI++ = 3 + offset; } subMesh->indexData->indexBuffer->unlock(); //subMesh->setBuildEdgesEnabled(autoEdgeBuildEnabled); //Finish up mesh AxisAlignedBox bounds(page.bounds.left - page.centerPoint.x, minY, page.bounds.top - page.centerPoint.z, page.bounds.right - page.centerPoint.x, maxY, page.bounds.bottom - page.centerPoint.z); mesh->_setBounds(bounds); Vector3 temp = bounds.getMaximum() - bounds.getMinimum(); mesh->_setBoundingSphereRadius(temp.length() * 0.5f); LogManager::getSingleton().setLogDetail(static_cast<LoggingLevel>(0)); mesh->setAutoBuildEdgeLists(autoEdgeBuildEnabled); mesh->load(); LogManager::getSingleton().setLogDetail(LL_NORMAL); //Apply grass material to mesh subMesh->setMaterialName(layer->material->getName()); //Return the mesh return mesh.getPointer(); }