كيفية استخدام heightmaps 16BIT مع Ogre3d وفسإكس
سؤال
وأنا باستخدام Ogre3D وفسإكس.
وعندما كنت تحميل التضاريس من مخطط ارتفاع 8bit، فإنه يبدو طبيعيا على Visual المصحح.
وانظروا الى الصورة الأولى: http://img44.imageshack.us/gal.php؟g=44927650. JPG
ولكن عندما حفظ خريطة ارتفاع كصورة 16BIT، وأحصل على ما تراه على الصورة الثانية.
وهنا هو رمز، أن يكون يعمل وضعها الطبيعي مع 8bit PNG:
mSceneMgr->setWorldGeometry("terrain.cfg" );
mTSM=static_cast<TerrainSceneManager*>(sceneMgr);
TerrainOptions mTerrainOptions = mTSM->getOptions();
//load heihgtmap
Image mImage;
mImage.load("isl_h_ph.png", ResourceGroupManager::getSingleton().getWorldResourceGroupName()); //load image
//write image buffer to pOrigSrc
const uchar* pOrigSrc = mImage.getData();
const uchar* pSrc;
// image size to mPageSize
size_t mPageSize = mTerrainOptions.pageSize;
NxActorDesc ActorDesc;
//set number of segments
heightFieldDesc = new NxHeightFieldDesc;
heightFieldDesc->nbColumns = mPageSize;
heightFieldDesc->nbRows = mPageSize;
heightFieldDesc->verticalExtent = -1000;
heightFieldDesc->convexEdgeThreshold = 0;
heightFieldDesc->samples = new NxU32[mPageSize*mPageSize]; //constructor for every sample?
heightFieldDesc->sampleStride = sizeof(NxU32); //some sample step = number of samples
pSrc = pOrigSrc;
char* currentByte = (char*)heightFieldDesc->samples; //current sample mb?
LogManager::getSingletonPtr()->logMessage("+++Heightmap---");
for (NxU32 row = 0; row < mPageSize; row++)
{
for (NxU32 column = 0; column < mPageSize; column++) //cycle around samples
{
pSrc = pOrigSrc + column*mPageSize +row;
//NxReal s = NxReal(row) / NxReal(mPageSize);
//NxReal t = NxReal(column) / NxReal(mPageSize);
NxI16 height = (NxI32)(*pSrc++);
NxU32 matrixOffset = (row % gMatrixSize) * gMatrixSize + (column % gMatrixSize);
//LogManager::getSingletonPtr()->logMessage(Ogre::StringConverter::toString(height));
NxHeightFieldSample* currentSample = (NxHeightFieldSample*)currentByte;
currentSample->height = height;
currentSample->materialIndex0 = gMatrix[matrixOffset][1];
currentSample->materialIndex1 = gMatrix[matrixOffset][2];
currentSample->tessFlag = gMatrix[matrixOffset][0];
currentByte += heightFieldDesc->sampleStride;
}
}
heightField = mScene->getPhysicsSDK().createHeightField(*heightFieldDesc);
NxHeightFieldShapeDesc heightFieldShapeDesc;
heightFieldShapeDesc.heightField = heightField;
heightFieldShapeDesc.shapeFlags = NX_SF_FEATURE_INDICES | NX_SF_VISUALIZATION;
heightFieldShapeDesc.group = 1;
heightFieldShapeDesc.heightScale = 18.8f;//1 в Physx = 255 в огре
heightFieldShapeDesc.rowScale = mTerrainOptions.scale.x;
heightFieldShapeDesc.columnScale = mTerrainOptions.scale.z;
heightFieldShapeDesc.meshFlags = NX_MESH_SMOOTH_SPHERE_COLLISIONS;
heightFieldShapeDesc.materialIndexHighBits = 0;
heightFieldShapeDesc.holeMaterial = 2;
ActorDesc.shapes.pushBack(&heightFieldShapeDesc);
وماذا يجب علي أن أغير للحصول على 16BIT أو صورة تحميل أعلى العمل؟
وP.S: آسف لسوء الانجليزية
المحلول
وpOrigSrc الخاص بك هو على uchar، الذي هو 8 بت، لذلك كنت لا تحصل على الصحيح تعويض عند القيام بذلك:
pSrc = pOrigSrc + column*mPageSize +row;
ويمكنك تصحيح هذا عن طريق الاستيلاء على أول خطوة من الصور الخاصة بك قبل الحلقات الخاصة بك، شيئا من هذا القبيل:
int imageStride = mImage.getBPP() / 8;
ومن ثم مضاعفة الخاص احتساب يقابله خطوة، شيء من هذا القبيل:
pSrc = pOrigSrc + (column*mPageSize +row)*imageStride;
وهذا يجب أن تسمح لك لاستخدام كل الخرائط ارتفاع 8 بت و 16 بت. فسإكس يعتمد فقط الخرائط ارتفاع 16 بت، لذلك لا يمكن أن تذهب أعلى من ذلك.
نصائح أخرى
وجميع من حرف في التعليمات البرمجية تحتاج إلى أن تكون الآن السراويل، وتحتاج إلى اجتياز ملف 2 بايت في كل مرة، لا 1. لأن 8 بت هو بايت واحد (حجم شار أو uchar)، و 16 بت هي وحدتي بايت، وحجم قصيرة قصيرة أو غير موقعة.