void Nx3DSceneObjectPatch::Create( const Ogre::String& mesh_name, const Ogre::String& resource_group_name, float width, float height ) { //m_row = 7; //m_col = 7; //m_row = 5; //33 vertices //m_col = 5; // 33 vertices m_row = 3; // 17 vertices // minimum 3 X 3 control points m_col = 3; // 17 vertices m_MaxSubdivisionU = 3 ; // 3 X r + 2 x r = 5 vertices m_MaxSubdivisionV = 3 ; PatchMeshVerticesWidth = (LEVEL_WIDTH( m_MaxSubdivisionU )-1) * (( m_row -1)/2) + 1; PatchMeshVerticesHeight = (LEVEL_WIDTH( m_MaxSubdivisionV )-1) * ((m_col-1)/2) + 1; //Log( " ----- NUM VERTICE WIDTH ======= " + Ogre::StringConverter::toString( PatchMeshVerticesWidth ) ); //Log( " ----- NUM VERTICE HEIGHT ======= " + Ogre::StringConverter::toString( PatchMeshVerticesHeight ) ); m_patchCtlPoints=(float*)(new PatchVertex[m_row*m_col]); int cnt=0; PatchVertex *pVert=(PatchVertex*)m_patchCtlPoints; int i,j; for(j=0;j<m_row;j++) { for(i=0;i<m_col;i++) { pVert->x=((float)i)/(m_col-1)* width; pVert->y=((float)j)/(m_row-1)*-height; pVert->z=0; pVert->nx=1.0; pVert->ny=0.0; pVert->nz=0.0; pVert->u=((float)i)/(m_col-1); pVert->v=((float)j)/(m_row-1); pVert++; ++cnt; } } m_patchDecl = Ogre::HardwareBufferManager::getSingleton().createVertexDeclaration(); // destroyVertexDeclaration VertexElement PosElement = m_patchDecl->addElement(0,0,Ogre::VET_FLOAT3,Ogre::VES_POSITION); m_patchDecl->addElement(0,sizeof(float)*3,Ogre::VET_FLOAT3,Ogre::VES_NORMAL); m_patchDecl->addElement(0,sizeof(float)*6,Ogre::VET_FLOAT2,Ogre::VES_TEXTURE_COORDINATES,0); NxPatchMesh = Ogre::MeshManager::getSingleton(). createBezierPatch( mesh_name,resource_group_name, m_patchCtlPoints,m_patchDecl, m_col, m_row, m_MaxSubdivisionU , m_MaxSubdivisionV ,PatchSurface::VS_BOTH ).get(); NxPatchMesh->setSubdivision(1.0f); return ;//NxPatchMesh ; }
//----------------------------------------------------------------------- void PatchSurface::defineSurface(void* controlPointBuffer, VertexDeclaration *declaration, size_t width, size_t height, PatchSurfaceType pType, size_t uMaxSubdivisionLevel, size_t vMaxSubdivisionLevel, VisibleSide visibleSide) { if (height == 0 || width == 0) return; // Do nothing - garbage mType = pType; mCtlWidth = width; mCtlHeight = height; mCtlCount = width * height; mControlPointBuffer = controlPointBuffer; mDeclaration = declaration; // Copy positions into Vector3 vector mVecCtlPoints.clear(); const VertexElement* elem = declaration->findElementBySemantic(VES_POSITION); size_t vertSize = declaration->getVertexSize(0); const unsigned char *pVert = static_cast<const unsigned char*>(controlPointBuffer); float* pFloat; for (size_t i = 0; i < mCtlCount; ++i) { elem->baseVertexPointerToElement(const_cast<unsigned char*>(pVert), &pFloat); mVecCtlPoints.push_back(Vector3(pFloat[0], pFloat[1], pFloat[2])); pVert += vertSize; } mVSide = visibleSide; // Determine max level // Initialise to 100% detail mSubdivisionFactor = 1.0f; if (uMaxSubdivisionLevel == (size_t)AUTO_LEVEL) { mULevel = mMaxULevel = getAutoULevel(); } else { mULevel = mMaxULevel = uMaxSubdivisionLevel; } if (vMaxSubdivisionLevel == (size_t)AUTO_LEVEL) { mVLevel = mMaxVLevel = getAutoVLevel(); } else { mVLevel = mMaxVLevel = vMaxSubdivisionLevel; } // Derive mesh width / height mMeshWidth = (LEVEL_WIDTH(mMaxULevel)-1) * ((mCtlWidth-1)/2) + 1; mMeshHeight = (LEVEL_WIDTH(mMaxVLevel)-1) * ((mCtlHeight-1)/2) + 1; // Calculate number of required vertices / indexes at max resolution mRequiredVertexCount = mMeshWidth * mMeshHeight; int iterations = (mVSide == VS_BOTH)? 2 : 1; mRequiredIndexCount = (mMeshWidth-1) * (mMeshHeight-1) * 2 * iterations * 3; // Calculate bounds based on control points vector<Vector3>::type::const_iterator ctli; Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE; Real maxSqRadius = 0; bool first = true; for (ctli = mVecCtlPoints.begin(); ctli != mVecCtlPoints.end(); ++ctli) { if (first) { min = max = *ctli; maxSqRadius = ctli->squaredLength(); first = false; } else { min.makeFloor(*ctli); max.makeCeil(*ctli); maxSqRadius = std::max(ctli->squaredLength(), maxSqRadius); } } mAABB.setExtents(min, max); mBoundingSphere = Math::Sqrt(maxSqRadius); }
//----------------------------------------------------------------------- void PatchSurface::makeTriangles(void) { // Our vertex buffer is subdivided to the highest level, we need to generate tris // which step over the vertices we don't need for this level of detail. // Calculate steps int vStep = 1 << (mMaxVLevel - mVLevel); int uStep = 1 << (mMaxULevel - mULevel); size_t currWidth = (LEVEL_WIDTH(mULevel)-1) * ((mCtlWidth-1)/2) + 1; size_t currHeight = (LEVEL_WIDTH(mVLevel)-1) * ((mCtlHeight-1)/2) + 1; bool use32bitindexes = (mIndexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); // The mesh is built, just make a list of indexes to spit out the triangles int vInc, uInc; size_t vCount, uCount, v, u, iterations; if (mVSide == VS_BOTH) { iterations = 2; vInc = vStep; v = 0; // Start with front } else { iterations = 1; if (mVSide == VS_FRONT) { vInc = vStep; v = 0; } else { vInc = -vStep; v = mMeshHeight - 1; } } // Calc num indexes mCurrIndexCount = (currWidth - 1) * (currHeight - 1) * 6 * iterations; size_t v1, v2, v3; // Lock just the section of the buffer we need unsigned short* p16 = 0; unsigned int* p32 = 0; if (use32bitindexes) { p32 = static_cast<unsigned int*>( mIndexBuffer->lock( mIndexOffset * sizeof(unsigned int), mRequiredIndexCount * sizeof(unsigned int), HardwareBuffer::HBL_NO_OVERWRITE)); } else { p16 = static_cast<unsigned short*>( mIndexBuffer->lock( mIndexOffset * sizeof(unsigned short), mRequiredIndexCount * sizeof(unsigned short), HardwareBuffer::HBL_NO_OVERWRITE)); } while (iterations--) { // Make tris in a zigzag pattern (compatible with strips) u = 0; uInc = uStep; // Start with moving +u vCount = currHeight - 1; while (vCount--) { uCount = currWidth - 1; while (uCount--) { // First Tri in cell // ----------------- v1 = ((v + vInc) * mMeshWidth) + u; v2 = (v * mMeshWidth) + u; v3 = ((v + vInc) * mMeshWidth) + (u + uInc); // Output indexes if (use32bitindexes) { *p32++ = static_cast<unsigned int>(v1); *p32++ = static_cast<unsigned int>(v2); *p32++ = static_cast<unsigned int>(v3); } else { *p16++ = static_cast<unsigned short>(v1); *p16++ = static_cast<unsigned short>(v2); *p16++ = static_cast<unsigned short>(v3); } // Second Tri in cell // ------------------ v1 = ((v + vInc) * mMeshWidth) + (u + uInc); v2 = (v * mMeshWidth) + u; v3 = (v * mMeshWidth) + (u + uInc); // Output indexes if (use32bitindexes) { *p32++ = static_cast<unsigned int>(v1); *p32++ = static_cast<unsigned int>(v2); *p32++ = static_cast<unsigned int>(v3); } else { *p16++ = static_cast<unsigned short>(v1); *p16++ = static_cast<unsigned short>(v2); *p16++ = static_cast<unsigned short>(v3); } // Next column u += uInc; } // Next row v += vInc; u = 0; } // Reverse vInc for double sided v = mMeshHeight - 1; vInc = -vInc; } mIndexBuffer->unlock(); }