Hi,
thanks for the explanation. Yes, just simple mesh, the most complex will be later a sphere. I would like to create some rudimentary hils on a sphere.
I will keep the policy thing in mind!
For now, thought, I create a more basic scenario: Having a case.mesh (cube), with texture etc. as Ogre::Item (originalItem).
From that, I read all the vertex data via getDetailedMeshInformation2 function.
Then I create a manual and the dynamicVertexBuffer for manipulation.
But after that step, the create manual is crap (just 2 black triangles). Here is the to read out information and set datablock and replace the original item with the manual:
Code: Select all
MathHelper::getInstance()->getDetailedMeshInformation2(originalItem->getMesh(), this->originalVertexCount, this->originalVertices, this->originalNormals, this->originalTextureCoordinates,
this->originalIndexCount, this->originalIndices, originalItem->getParentNode()->_getDerivedPositionUpdated(),
originalItem->getParentNode()->_getDerivedOrientationUpdated(),
originalItem->getParentNode()->getScale(), isVET_HALF4, isIndices32);
this->createDynamicMesh(isVET_HALF4, isIndices32);
// Just one subitem is allowed for now, getNumSubItems will be just 1
Ogre::Item* itemToModify = this->gameObjectPtr->getSceneManager()->createItem(this->meshToModify, this->gameObjectPtr->isDynamic() ? Ogre::SCENE_DYNAMIC : Ogre::SCENE_STATIC);
for (size_t i = 0; i < originalItem->getNumSubItems(); i++)
{
auto sourceDataBlock = dynamic_cast<Ogre::HlmsPbsDatablock*>(originalItem->getSubItem(i)->getDatablock());
if (nullptr != sourceDataBlock)
{
itemToModify->getSubItem(i)->setDatablock(sourceDataBlock);
// sourceDataBlock->mShadowConstantBias = 0.0001f;
// Deactivate fresnel by default, because it looks ugly
if (sourceDataBlock->getWorkflow() != Ogre::HlmsPbsDatablock::SpecularAsFresnelWorkflow && sourceDataBlock->getWorkflow() != Ogre::HlmsPbsDatablock::MetallicWorkflow)
{
sourceDataBlock->setFresnel(Ogre::Vector3(0.01f, 0.01f, 0.01f), false);
}
}
}
this->gameObjectPtr->getSceneNode()->createChildSceneNode(Ogre::SCENE_DYNAMIC);
this->gameObjectPtr->getSceneNode()->attachObject(itemToModify);
this->gameObjectPtr->init(itemToModify);
Here the createDynamicMeshFunction:
Code: Select all
void MeshModifyComponent::createDynamicMesh(bool isVET_HALF4, bool isIndices32)
{
Ogre::Item* originalItem = this->gameObjectPtr->getMovableObject<Ogre::Item>();
// Transform back from global to local, both: transform and normals
// Get the world transformation matrix of the entity
Ogre::Matrix4 worldMatrix = originalItem->getParentNode()->_getFullTransform();
// Inverse the world matrix to get object space transformation
Ogre::Matrix4 invWorldMatrix = worldMatrix.inverse();
// Get the rotation part of the inverse world matrix for normals
Ogre::Matrix3 invWorldRotation;
invWorldMatrix.extract3x3Matrix(invWorldRotation);
// Transform vertices and normals from world space to object space - do this only ONCE
for (size_t i = 0; i < this->originalVertexCount; ++i)
{
// Transform each vertex by applying the inverse of the world matrix
this->originalVertices[i] = invWorldMatrix * this->originalVertices[i];
this->originalNormals[i] = invWorldRotation * this->originalNormals[i];
// Normalize the normal after transformation
this->originalNormals[i].normalise();
}
Ogre::RenderSystem* renderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem();
Ogre::VaoManager* vaoManager = renderSystem->getVaoManager();
// Create manual mesh
this->meshToModify = Ogre::MeshManager::getSingletonPtr()->createManual(this->gameObjectPtr->getName() + "_dynamic", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
Ogre::SubMesh* subMesh = this->meshToModify->createSubMesh();
// Define vertex elements - use correct formats
Ogre::VertexElement2Vec vertexElements;
if (false == isVET_HALF4)
{
vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3, Ogre::VES_POSITION));
vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT3, Ogre::VES_NORMAL));
}
else
{
vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT4, Ogre::VES_POSITION));
vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT4, Ogre::VES_NORMAL));
}
vertexElements.push_back(Ogre::VertexElement2(Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES));
// Create interleaved vertex data
size_t vertexSize = 0;
if (isVET_HALF4)
{
vertexSize = sizeof(float) * 4 + sizeof(float) * 4 + sizeof(float) * 2; // pos(4) + normal(4) + texcoord(2)
}
else
{
vertexSize = sizeof(float) * 3 + sizeof(float) * 3 + sizeof(float) * 2; // pos(3) + normal(3) + texcoord(2)
}
// Allocate memory for interleaved data - using byte count, not element count
uint8_t* interleavedData = (uint8_t*)OGRE_MALLOC_SIMD(vertexSize * this->originalVertexCount, Ogre::MEMCATEGORY_GEOMETRY);
float* pData = (float*)interleavedData;
// Fill the interleaved data
for (size_t i = 0; i < this->originalVertexCount; ++i)
{
// Position
*pData++ = this->originalVertices[i].x;
*pData++ = this->originalVertices[i].y;
*pData++ = this->originalVertices[i].z;
if (isVET_HALF4)
{
*pData++ = 1.0f; // w component for VET_FLOAT4
}
// Normal
*pData++ = this->originalNormals[i].x;
*pData++ = this->originalNormals[i].y;
*pData++ = this->originalNormals[i].z;
if (isVET_HALF4)
{
*pData++ = 0.0f; // w component for VET_FLOAT4
}
// Texture coordinates - no need for a separate count variable
if (this->originalTextureCoordinates)
{
*pData++ = this->originalTextureCoordinates[i].x;
*pData++ = this->originalTextureCoordinates[i].y;
}
else
{
// Fallback if texture coordinates aren't available
*pData++ = 0.0f;
*pData++ = 0.0f;
}
}
try
{
// Create vertex buffer with interleaved data
this->dynamicVertexBuffer = vaoManager->createVertexBuffer(vertexElements, this->originalVertexCount, Ogre::BT_DYNAMIC_PERSISTENT, interleavedData, false);
}
catch (Ogre::Exception& e)
{
OGRE_FREE_SIMD(interleavedData, Ogre::MEMCATEGORY_GEOMETRY);
return;
}
Ogre::IndexBufferPacked::IndexType indexType = Ogre::IndexBufferPacked::IT_32BIT;
if (false == isIndices32)
{
indexType = Ogre::IndexBufferPacked::IT_16BIT;
}
// Create index buffer with original indices
try
{
this->dynamicIndexBuffer = vaoManager->createIndexBuffer(indexType, this->originalIndexCount, Ogre::BT_DYNAMIC_PERSISTENT, this->originalIndices, false);
}
catch (Ogre::Exception& e)
{
OGRE_FREE_SIMD(this->originalIndices, Ogre::MEMCATEGORY_GEOMETRY);
return;
}
// Create VAO
Ogre::VertexBufferPackedVec vertexBuffers;
vertexBuffers.push_back(this->dynamicVertexBuffer);
Ogre::VertexArrayObject* vao = vaoManager->createVertexArrayObject(vertexBuffers, this->dynamicIndexBuffer, Ogre::OT_TRIANGLE_LIST);
subMesh->mVao[Ogre::VpNormal].push_back(vao);
subMesh->mVao[Ogre::VpShadow].push_back(vao);
// Set bounds (same as originalItem)
Ogre::Aabb originalBounds = originalItem->getMesh()->getAabb();
this->meshToModify->_setBounds(originalBounds, false);
this->meshToModify->_setBoundingSphereRadius(originalItem->getMesh()->getBoundingSphereRadius());
}
The values get from the mesh information function, are correct. I debugged it, but something seems to be totally wrong. I also make global space vertex values to local space.
What is missing here, or is the order wrong?
Best Regards
Lax