讀取 VRML (WRL) 文件,提取幾何頂點、索引、紋理座標,重構場景並實現頂點波動動畫。使用 Coin3D(Open Inventor 開源實現)庫。
// 全局緩衝區
int numOfCoord, numOfTexCoord, numOfIndex;
float (*tempCoord)[3]; // 頂點位置 [numOfCoord][3]
float (*tempTexCoord)[2]; // 紋理座標 [numOfTexCoord][2]
int *tempIndex; // 面索引 [numOfIndex]
SoInput::openFile()SoDB::readAllVRML() 返回根節點 SoVRMLGroup*SoSearchAction 類型 SoVRMLShapeshape->geometry.getValue() → SoVRMLIndexedFaceSet*indexedFaceSet->coord.getValue() → SoVRMLCoordinate* → point 數組indexedFaceSet->coordIndexindexedFaceSet->texCoord.getValue() → SoTextureCoordinate2*
void readFile(const char *filename) {
SoInput input;
if (!input.openFile(filename)) { /* error */ }
SoVRMLGroup *root = SoDB::readAllVRML(&input);
input.closeFile();
if (!root) { /* error */ }
root->ref();
// 搜索第一個 Shape
SoSearchAction search;
search.setType(SoVRMLShape::getClassTypeId());
search.setInterest(SoSearchAction::FIRST);
search.apply(root);
if (!search.getPath()) { /* error */ }
SoVRMLShape *shape = (SoVRMLShape*)search.getPath()->getTail();
shape->setOverride(TRUE);
// 獲取 IndexedFaceSet
SoVRMLIndexedFaceSet *ifs = (SoVRMLIndexedFaceSet*)shape->geometry.getValue();
// 頂點座標
SoVRMLCoordinate *coord = (SoVRMLCoordinate*)ifs->coord.getValue();
numOfCoord = coord->point.getNum();
tempCoord = new float[numOfCoord][3];
for (int i=0; ipoint[i][j];
// 索引
numOfIndex = ifs->coordIndex.getNum();
tempIndex = new int[numOfIndex];
for (int k=0; kcoordIndex[k];
// 紋理座標
SoTextureCoordinate2 *texCoord = (SoTextureCoordinate2*)ifs->texCoord.getValue();
numOfTexCoord = texCoord->point.getNum();
tempTexCoord = new float[numOfTexCoord][2];
for (int n=0; npoint[n][p];
}
將提取數據構建新的 SoIndexedFaceSet 節點:
void drawFace(SoIndexedFaceSet *faceSet) {
SoMFVec3f coords; // 頂點
SoMFInt32 indices; // 索引
SoMFVec2f texCoords; // 紋理
for (int i=0; ivertex = coords;
vp->texCoord = texCoords;
vp->normal.set1Value(0, SbVec3f(0,1,0)); // 簡單法線
vp->normalBinding = SoNormalBinding::OVERALL;
faceSet->coordIndex = indices;
faceSet->vertexProperty.setValue(vp);
}
static void timerCB(void *data, SoSensor *) {
SoIndexedFaceSet *faceSet = (SoIndexedFaceSet*)data;
SoVertexProperty *vp = (SoVertexProperty*)faceSet->vertexProperty.getValue();
SoMFVec3f &coords = vp->vertex;
static float phase = 0;
phase += 0.1f;
for (int i=0; ivertex = coords; // 觸發重繪
}
// 主函數啟動定時器
SoTimerSensor *timer = new SoTimerSensor(timerCB, faceSet);
timer->setInterval(SbTime(1.0/30)); // 30 FPS
timer->schedule();
g++ -std=c++11 main.cpp -o vrml_viewer \
-I/usr/include/Inventor \
-lCoin -lGL -lGLU -lX11
Coin3D 提供完整的 VRML97/X3D 場景圖解析與渲染管線。核心流程:SoInput → SoDB::readAllVRML → SoSearchAction 定位節點 → 提取 SoVRMLIndexedFaceSet 數據 → 重構 SoIndexedFaceSet + SoVertexProperty → 定時器驅動頂點動畫。掌握場景圖遍歷與屬性綁定機制,是進行 3D 文件處理與可視化開發的基礎。