创建各顶点颜色不同的网格元素(Creating Vertex-Colored Mesh)


不知您是否在MicroStation中看到过如下的彩色Mesh元素?它每个顶点可以被赋以不同的颜色,这种应用可扩展到专题显示样式(Thematic Display Style)中。

下面这段代码就是用来创建图一所示的彩色Mesh元素的。

    void createVertexColoredMesh()
    {
                          // index= 1,                2,                     3,                      4,               
    DPoint3d  xyzPts[] = { { -577350, 0, -816497 }, { -577350, 0, 816497 }, { 577350, -816497, 0 }, { 577350, 816497, 0 } };
              //Face= 1,        2,       3,       4
    int indices[] = { 1, 2, 4,  2, 3, 4, 3, 2, 1, 1, 4, 3 };
    int vertexClrs[] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255), RGB(255, 255, 0) };

    EmbeddedIntArray *pIndices = jmdlEmbeddedIntArray_grab();
    jmdlEmbeddedIntArray_addIntArray(pIndices, indices, sizeof(indices) / sizeof(int));
    EmbeddedDPoint3dArray *pXYZArray = jmdlEmbeddedDPoint3dArray_grab();
    jmdlEmbeddedDPoint3dArray_addDPoint3dArray(pXYZArray, xyzPts, sizeof(xyzPts) / sizeof(DPoint3d));
    EmbeddedIntArray *pClrArray = jmdlEmbeddedIntArray_grab();
    jmdlEmbeddedIntArray_addIntArray(pClrArray, vertexClrs, sizeof(vertexClrs) / sizeof(int));

    MSElementDescrP meshP = NULL;        
    mdlMesh_newPolyfaceFromEmbeddedArraysExt(&meshP, NULL, pIndices, 3, pXYZArray, NULL, NULL, NULL, NULL,
                                             pIndices, pClrArray, NULL, NULL, FALSE, TRUE);
    if (NULL != meshP)
        {
        mdlElmdscr_add(meshP);
        mdlElmdscr_freeAll(&meshP);
        }
    jmdlEmbeddedIntArray_drop(pIndices);
    jmdlEmbeddedDPoint3dArray_drop(pXYZArray);
    jmdlEmbeddedIntArray_drop(pClrArray);
    }

下面对以上代码做简单的介绍:

1、首先做数据准备,在xyzPts数组中指定四面体的四个坐标点,然后在vertexClrs数组中指定每个顶点的颜色。

2、关键在于定义indices。Mesh元素的每个面可以说固定顶点个数的也可以是不定个数的,我们这里采用了固定个数(每个面由三个点组成)。所以,在indices中定义了12个数,每三个数定义了四面体的一个面的索引。如Face1的索引为1,2,4,那它的三个坐标点就是xyzPts[0]、xyzPts[1]和xyzPts[3],对应的颜色就是vertexClrs[0]、vertexClrs[1]和vertexClrs[3]。这是因为Mesh的索引要从1开始计数,0作为特殊含义(每个面不固定个数顶点时要以0作为索引的分隔)的索引。

3、由于mdlMesh_newPolyfaceFromEmbeddedArraysExt函数需要传入动态数组,所以,接下来调用了jmdlEmbedded类函数将xyzPts、vertexClrs和indices分别转换为了pXYZArray、pClrArray和pIndices。

4、调用函数mdlMesh_newPolyfaceFromEmbeddedArraysExt创建彩色Mesh,并将其添加到模型中。

5、调用jmdlEmbeddedXXXArray_drop函数释放pXYZArray、pClrArray和pIndices占用的内存。

————————————————————————————————————————————————————

以上代码是在MicroStation V8i下用C++编写而成的。随着MicroStation CE版的流行,下面是用C++最新的面向对象方法重写的代码:

#define RGB(r,g,b)     ((r)|((g)<<8)|((b)<<16))
void meshCreateFixedIndex(WCharCP  unparsed)
    {
                  // index= 1,                    2,                    3,                    4,               
    DPoint3d  xyzPts[] = { { -57735, 0, -81649 }, { -57735, 0, 81649 }, { 57735, -81649, 0 }, { 57735, 81649, 0 } };
              //Face= 1,       2,       3,       4
    int indices[] = { 1, 2, 4, 2, 3, 4, 3, 2, 1, 1, 4, 3 };
	int vertexClrs[] = { RGB(255, 0, 0), RGB(0, 255, 0), RGB(0, 0, 255), RGB(255, 255, 0) };
    
    PolyfaceHeaderPtr pMesh = PolyfaceHeader::CreateFixedBlockIndexed(3);
    pMesh->Point().insert(pMesh->Point().begin(), xyzPts, xyzPts + sizeof(xyzPts) / sizeof(DPoint3d));
    pMesh->Point().SetActive(true);
    pMesh->PointIndex().insert(pMesh->PointIndex().begin(), indices, indices + sizeof(indices) / sizeof(int));
    pMesh->PointIndex().SetActive(true);
	pMesh->IntColor().insert(pMesh->IntColor().begin(), vertexClrs, vertexClrs + sizeof(vertexClrs) / sizeof(int));
	pMesh->IntColor().SetActive(true);
	pMesh->ColorIndex().insert(pMesh->ColorIndex().begin(), indices, indices + sizeof(indices) / sizeof(int));
	pMesh->ColorIndex().SetActive(true);

    EditElementHandle  eeh;
    DgnModelP          pActiveModel = ISessionMgr::GetActiveDgnModelP();
    if (SUCCESS == MeshHeaderHandler::CreateMeshElement(eeh, NULL, *pMesh, true, *pActiveModel))
        {
        eeh.AddToModel();
        }
    }

下面是用CE下的C#重写的代码:

        public static void CreateMesh2()
        {
            PolyfaceHeader polyHeader = new PolyfaceHeader();
            polyHeader.NumberPerFace = 0;

            var pts = new List<DPoint3d>();
            pts.Add(new DPoint3d(-57735, 0, -81649));
            pts.Add(new DPoint3d(-57735, 0, 81649));
            pts.Add(new DPoint3d(57735, -81649, 0));
            pts.Add(new DPoint3d(57735, 81649, 0));
            polyHeader.Point = pts;

            var clrs = new List<uint>();
            clrs.Add(0x000000ff);             // RED
            clrs.Add(0x0000ff00);             // GREEN
            clrs.Add(0x00ff0000);             // BLUE
            clrs.Add(0x0000ffff); 
            polyHeader.IntColor = clrs;

            polyHeader.ActivateVectorsForIndexing(polyHeader);

            var indices = new List<int>();
            indices.Add(1); indices.Add(2); indices.Add(4);  //one-based
            polyHeader.AddIndexedFacet(indices, null, null, indices);
            indices.Clear();
            indices.Add(2); indices.Add(3); indices.Add(4);
            polyHeader.AddIndexedFacet(indices, null, null, indices);
            indices.Clear();
            indices.Add(3); indices.Add(2); indices.Add(1);
            polyHeader.AddIndexedFacet(indices, null, null, indices);
            indices.Clear();
            indices.Add(1); indices.Add(4); indices.Add(3);
            polyHeader.AddIndexedFacet(indices, null, null, indices);

            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            MeshHeaderElement meshElem = new MeshHeaderElement(dgnModel, null, polyHeader);
            meshElem.AddToModel();
        }