Exemple #1
0
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();


    }