Working on morph targets
This commit is contained in:
9
morph/CMakeLists.txt
Normal file
9
morph/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
project(morph)
|
||||
add_executable(MorphTargetsResearch MorphTargetsResearch.cpp)
|
||||
target_link_libraries(MorphTargetsResearch OgreBites OgreBullet OgrePaging ${BULLET_DYNAMICS_LIBRARY} ${BULLET_COLLISION_LIBRARY} ${BULLET_MATH_LIBRARY} ${ASSIMP_LIBRARIES}
|
||||
-Wl,--as-needed
|
||||
)
|
||||
if(OGRE_STATIC)
|
||||
target_link_options(MorphTargetsResearch PRIVATE -static-libstdc++ -static-libgcc)
|
||||
endif()
|
||||
add_dependencies(MorphTargetsResearch stage_files import_vrm)
|
||||
641
morph/MorphTargetsResearch.cpp
Normal file
641
morph/MorphTargetsResearch.cpp
Normal file
@@ -0,0 +1,641 @@
|
||||
#include <iostream>
|
||||
#include <Ogre.h>
|
||||
#include <OgreApplicationContext.h>
|
||||
|
||||
class App;
|
||||
|
||||
static void getSubmeshNormals(const Ogre::Mesh *mesh,
|
||||
const Ogre::SubMesh *submesh,
|
||||
std::vector<Ogre::Vector3> &normals)
|
||||
{
|
||||
int j;
|
||||
float *pReal;
|
||||
int vertex_count = 0;
|
||||
if (submesh->useSharedVertices)
|
||||
vertex_count += mesh->sharedVertexData->vertexCount;
|
||||
else
|
||||
vertex_count += submesh->vertexData->vertexCount;
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf;
|
||||
Ogre::VertexData *vertex_data = submesh->useSharedVertices ?
|
||||
mesh->sharedVertexData :
|
||||
submesh->vertexData;
|
||||
const Ogre::VertexElement *normalsElem =
|
||||
vertex_data->vertexDeclaration->findElementBySemantic(
|
||||
Ogre::VES_NORMAL);
|
||||
if (!normalsElem)
|
||||
return;
|
||||
OgreAssert(normals.size() == 0 || normals.size() == vertex_count,
|
||||
"bad vertex count");
|
||||
normals.resize(vertex_count);
|
||||
vbuf = vertex_data->vertexBufferBinding->getBuffer(
|
||||
normalsElem->getSource());
|
||||
unsigned char *vertex = static_cast<unsigned char *>(
|
||||
vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
||||
for (j = 0; j < vertex_data->vertexCount;
|
||||
++j, vertex += vbuf->getVertexSize()) {
|
||||
normalsElem->baseVertexPointerToElement(vertex, &pReal);
|
||||
normals[j] = Ogre::Vector3(pReal[0], pReal[1], pReal[2]);
|
||||
}
|
||||
vbuf->unlock();
|
||||
}
|
||||
static void getSubmeshUVs(const Ogre::Mesh *mesh, const Ogre::SubMesh *submesh,
|
||||
std::vector<Ogre::Vector2> &uvs, int index)
|
||||
{
|
||||
int j;
|
||||
float *pReal;
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf;
|
||||
Ogre::VertexData *vertex_data = submesh->useSharedVertices ?
|
||||
mesh->sharedVertexData :
|
||||
submesh->vertexData;
|
||||
const Ogre::VertexElement *uvElem =
|
||||
vertex_data->vertexDeclaration->findElementBySemantic(
|
||||
Ogre::VES_TEXTURE_COORDINATES, index);
|
||||
int vertex_count = 0;
|
||||
if (submesh->useSharedVertices)
|
||||
vertex_count += mesh->sharedVertexData->vertexCount;
|
||||
else
|
||||
vertex_count += submesh->vertexData->vertexCount;
|
||||
if (!uvElem)
|
||||
return;
|
||||
OgreAssert(uvs.size() == 0 || uvs.size() == vertex_count,
|
||||
"bad vertex count");
|
||||
uvs.resize(vertex_count);
|
||||
vbuf = vertex_data->vertexBufferBinding->getBuffer(uvElem->getSource());
|
||||
unsigned char *uv = static_cast<unsigned char *>(
|
||||
vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
||||
for (j = 0; j < vertex_data->vertexCount; ++j) {
|
||||
uvElem->baseVertexPointerToElement(uv, &pReal);
|
||||
uvs[j] = Ogre::Vector2(pReal[0], pReal[1]);
|
||||
uv += vbuf->getVertexSize();
|
||||
}
|
||||
vbuf->unlock();
|
||||
}
|
||||
static void getSubmeshVertices(const Ogre::Mesh *mesh,
|
||||
const Ogre::SubMesh *submesh,
|
||||
std::vector<Ogre::Vector3> &vertices)
|
||||
{
|
||||
int j;
|
||||
float *pReal;
|
||||
int vertex_count = 0;
|
||||
if (submesh->useSharedVertices)
|
||||
vertex_count += mesh->sharedVertexData->vertexCount;
|
||||
else
|
||||
vertex_count += submesh->vertexData->vertexCount;
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf;
|
||||
Ogre::VertexData *vertex_data = submesh->useSharedVertices ?
|
||||
mesh->sharedVertexData :
|
||||
submesh->vertexData;
|
||||
const Ogre::VertexElement *posElem =
|
||||
vertex_data->vertexDeclaration->findElementBySemantic(
|
||||
Ogre::VES_POSITION);
|
||||
if (!posElem)
|
||||
return;
|
||||
OgreAssert(vertices.size() == 0 || vertices.size() == vertex_count,
|
||||
"bad vertex count");
|
||||
vertices.resize(vertex_count);
|
||||
vbuf = vertex_data->vertexBufferBinding->getBuffer(
|
||||
posElem->getSource());
|
||||
unsigned char *vertex = static_cast<unsigned char *>(
|
||||
vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
||||
for (j = 0; j < vertex_data->vertexCount;
|
||||
++j, vertex += vbuf->getVertexSize()) {
|
||||
posElem->baseVertexPointerToElement(vertex, &pReal);
|
||||
vertices[j] = Ogre::Vector3(pReal[0], pReal[1], pReal[2]);
|
||||
}
|
||||
vbuf->unlock();
|
||||
}
|
||||
static void getSubmeshIndices(const Ogre::Mesh *mesh,
|
||||
const Ogre::SubMesh *submesh,
|
||||
std::vector<unsigned long> &indices)
|
||||
{
|
||||
int index_count = 0;
|
||||
index_count += submesh->indexData->indexCount;
|
||||
int index_offset = 0;
|
||||
indices.resize(index_count);
|
||||
Ogre::IndexData *index_data = submesh->indexData;
|
||||
size_t numTris = index_data->indexCount / 3;
|
||||
Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
|
||||
|
||||
bool use32bitindexes =
|
||||
(ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
|
||||
|
||||
unsigned long *pLong = static_cast<unsigned long *>(
|
||||
ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
|
||||
unsigned short *pShort = reinterpret_cast<unsigned short *>(pLong);
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
if (use32bitindexes) {
|
||||
for (size_t k = 0; k < numTris * 3; ++k) {
|
||||
indices[index_offset++] =
|
||||
pLong[k] + static_cast<unsigned long>(offset);
|
||||
}
|
||||
} else {
|
||||
for (size_t k = 0; k < numTris * 3; ++k) {
|
||||
indices[index_offset++] =
|
||||
static_cast<unsigned long>(pShort[k]) +
|
||||
static_cast<unsigned long>(offset);
|
||||
}
|
||||
}
|
||||
|
||||
ibuf->unlock();
|
||||
}
|
||||
struct SubMeshInformation {
|
||||
Ogre::String materialName;
|
||||
bool sharedVertices;
|
||||
std::vector<Ogre::Vector3> vertices;
|
||||
std::vector<Ogre::Vector3> normals;
|
||||
std::vector<Ogre::Vector2> uvs;
|
||||
std::vector<Ogre::Vector2> uv2s;
|
||||
std::vector<unsigned long> indices;
|
||||
Ogre::SubMesh::LODFaceList lodFaceList;
|
||||
Ogre::Mesh::VertexBoneAssignmentList boneList;
|
||||
void createSubmesh(Ogre::Mesh *mesh)
|
||||
{
|
||||
int i;
|
||||
Ogre::SubMesh *out = mesh->createSubMesh();
|
||||
out->useSharedVertices = false;
|
||||
out->vertexData = new Ogre::VertexData();
|
||||
size_t currOffset = 0;
|
||||
Ogre::VertexDeclaration *vertexDecl =
|
||||
out->vertexData->vertexDeclaration;
|
||||
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3,
|
||||
Ogre::VES_POSITION);
|
||||
currOffset +=
|
||||
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
|
||||
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3,
|
||||
Ogre::VES_NORMAL);
|
||||
currOffset +=
|
||||
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3);
|
||||
vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2,
|
||||
Ogre::VES_TEXTURE_COORDINATES, 0);
|
||||
currOffset +=
|
||||
Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
|
||||
out->vertexData->vertexCount = vertices.size();
|
||||
Ogre::HardwareVertexBufferSharedPtr vbuf =
|
||||
Ogre::HardwareBufferManager::getSingleton()
|
||||
.createVertexBuffer(
|
||||
vertexDecl->getVertexSize(0),
|
||||
out->vertexData->vertexCount,
|
||||
Ogre::HardwareBuffer::
|
||||
HBU_STATIC_WRITE_ONLY, // only GPU side
|
||||
false);
|
||||
Ogre::VertexBufferBinding *binding =
|
||||
out->vertexData->vertexBufferBinding;
|
||||
binding->setBinding(0, vbuf);
|
||||
float *pvertex = static_cast<float *>(
|
||||
vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
|
||||
out->indexData->indexCount = indices.size();
|
||||
out->indexData->indexBuffer =
|
||||
Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(
|
||||
vertices.size() < 32768 ?
|
||||
Ogre::HardwareIndexBuffer::IT_16BIT :
|
||||
Ogre::HardwareIndexBuffer::IT_32BIT,
|
||||
out->indexData->indexCount,
|
||||
Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY,
|
||||
false);
|
||||
OgreAssert(normals.size() == vertices.size(), "bad normals");
|
||||
for (i = 0; i < vertices.size(); i++) {
|
||||
*pvertex++ = vertices[i].x;
|
||||
*pvertex++ = vertices[i].y;
|
||||
*pvertex++ = vertices[i].z;
|
||||
if (normals.size() > 0) {
|
||||
*pvertex++ = normals[i].x;
|
||||
*pvertex++ = normals[i].y;
|
||||
*pvertex++ = normals[i].z;
|
||||
} else {
|
||||
*pvertex++ = 0.0f;
|
||||
*pvertex++ = 1.0f;
|
||||
*pvertex++ = 0.0f;
|
||||
}
|
||||
if (uvs.size() > 0) {
|
||||
*pvertex++ = uvs[i].x;
|
||||
*pvertex++ = uvs[i].y;
|
||||
} else {
|
||||
*pvertex++ = 0.0f;
|
||||
*pvertex++ = 1.0f;
|
||||
}
|
||||
}
|
||||
vbuf->unlock();
|
||||
Ogre::HardwareIndexBufferSharedPtr ibuf =
|
||||
out->indexData->indexBuffer;
|
||||
if (vertices.size() < 32768) {
|
||||
unsigned short *pindices =
|
||||
static_cast<unsigned short *>(ibuf->lock(
|
||||
Ogre::HardwareBuffer::HBL_DISCARD));
|
||||
for (i = 0; i < indices.size(); i++)
|
||||
*pindices++ = (unsigned short)indices[i];
|
||||
ibuf->unlock();
|
||||
} else {
|
||||
unsigned long *pindices = static_cast<unsigned long *>(
|
||||
ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
|
||||
for (i = 0; i < indices.size(); i++)
|
||||
*pindices++ = indices[i];
|
||||
ibuf->unlock();
|
||||
}
|
||||
out->clearBoneAssignments();
|
||||
auto vbass_it = boneList.begin();
|
||||
while (vbass_it != boneList.end()) {
|
||||
out->addBoneAssignment(vbass_it->second);
|
||||
vbass_it++;
|
||||
}
|
||||
out->setMaterialName(materialName);
|
||||
}
|
||||
};
|
||||
|
||||
static void getSubMeshInformation(const Ogre::Mesh *mesh,
|
||||
const Ogre::SubMesh *submesh,
|
||||
struct SubMeshInformation *info)
|
||||
{
|
||||
info->materialName = submesh->getMaterialName();
|
||||
info->sharedVertices = submesh->useSharedVertices;
|
||||
info->lodFaceList = submesh->mLodFaceList;
|
||||
info->boneList = submesh->getBoneAssignments();
|
||||
getSubmeshIndices(mesh, submesh, info->indices);
|
||||
getSubmeshVertices(mesh, submesh, info->vertices);
|
||||
getSubmeshNormals(mesh, submesh, info->normals);
|
||||
getSubmeshUVs(mesh, submesh, info->uvs, 0);
|
||||
getSubmeshUVs(mesh, submesh, info->uv2s, 1);
|
||||
}
|
||||
|
||||
struct MeshInformation {
|
||||
struct MeshMorphTarget {
|
||||
Ogre::SkeletonPtr skelp;
|
||||
struct DataChange {
|
||||
int index;
|
||||
int submesh;
|
||||
Ogre::Vector3 vertex;
|
||||
Ogre::Vector3 normal;
|
||||
};
|
||||
std::vector<DataChange> vertices;
|
||||
float weight;
|
||||
};
|
||||
std::map<Ogre::String, struct MeshMorphTarget> targets;
|
||||
std::vector<struct SubMeshInformation> submesh;
|
||||
Ogre::SkeletonPtr skelp;
|
||||
Ogre::String skelName;
|
||||
MeshInformation(Ogre::Mesh *prototype)
|
||||
{
|
||||
int i;
|
||||
skelName = prototype->getSkeletonName();
|
||||
skelp = Ogre::SkeletonManager::getSingleton().getByName(
|
||||
prototype->getSkeletonName(), "Characters");
|
||||
OgreAssert(skelp, "Could not load skeleton " +
|
||||
prototype->getSkeletonName());
|
||||
submesh.resize(prototype->getNumSubMeshes());
|
||||
for (i = 0; i < submesh.size(); i++) {
|
||||
getSubMeshInformation(prototype,
|
||||
prototype->getSubMesh(i),
|
||||
&submesh[i]);
|
||||
std::cout << i << " " << "mesh material name: "
|
||||
<< submesh[i].materialName << std::endl;
|
||||
std::cout << i << " "
|
||||
<< "shared: " << submesh[i].sharedVertices
|
||||
<< std::endl;
|
||||
std::cout << i << " " << "vertex_count: "
|
||||
<< submesh[i].vertices.size() << std::endl;
|
||||
std::cout << i << " " << "index_count: "
|
||||
<< submesh[i].indices.size() << std::endl;
|
||||
}
|
||||
}
|
||||
Ogre::MeshPtr create(const Ogre::String &meshName)
|
||||
{
|
||||
int j;
|
||||
Ogre::MeshPtr baseMesh =
|
||||
Ogre::MeshManager::getSingleton().createManual(
|
||||
meshName, Ogre::ResourceGroupManager::
|
||||
DEFAULT_RESOURCE_GROUP_NAME);
|
||||
applyMorphTargets();
|
||||
for (j = 0; j < submesh.size(); j++)
|
||||
submesh[j].createSubmesh(baseMesh.get());
|
||||
//define a extreme boundary values
|
||||
Ogre::Real max_x = -1e+8;
|
||||
Ogre::Real min_x = 1e+8;
|
||||
Ogre::Real max_y = -1e+8;
|
||||
Ogre::Real min_y = 1e+8;
|
||||
Ogre::Real max_z = -1e+8;
|
||||
Ogre::Real min_z = +1e+8;
|
||||
// Setting bounding box
|
||||
Ogre::Mesh::SubMeshList mlist = baseMesh->getSubMeshes();
|
||||
for (j = 0; j < mlist.size(); j++) {
|
||||
Ogre::SubMesh *in = mlist[j];
|
||||
Ogre::VertexData *vertex_data = in->vertexData;
|
||||
const Ogre::VertexElement *posElem =
|
||||
vertex_data->vertexDeclaration
|
||||
->findElementBySemantic(
|
||||
Ogre::VES_POSITION);
|
||||
Ogre::HardwareVertexBufferSharedPtr hwvb =
|
||||
in->vertexData->vertexBufferBinding->getBuffer(
|
||||
posElem->getSource());
|
||||
unsigned char *hbuff =
|
||||
static_cast<unsigned char *>(hwvb->lock(
|
||||
Ogre::HardwareBuffer::HBL_READ_ONLY));
|
||||
Ogre::Real *pValue;
|
||||
Ogre::Real value;
|
||||
|
||||
for (size_t idx = 0; idx < vertex_data->vertexCount;
|
||||
++idx, hbuff += hwvb->getVertexSize()) {
|
||||
posElem->baseVertexPointerToElement(hbuff,
|
||||
&pValue);
|
||||
value = (*pValue++);
|
||||
if (value > max_x)
|
||||
max_x = value;
|
||||
if (value < min_x)
|
||||
min_x = value;
|
||||
value = (*pValue++);
|
||||
|
||||
if (value > max_y)
|
||||
max_y = value;
|
||||
if (value < min_y)
|
||||
min_y = value;
|
||||
value = (*pValue++);
|
||||
|
||||
if (value > max_z)
|
||||
max_z = value;
|
||||
if (value < min_z)
|
||||
min_z = value;
|
||||
}
|
||||
hwvb->unlock();
|
||||
}
|
||||
baseMesh->setSkeletonName(skelName);
|
||||
baseMesh->_setBounds(Ogre::AxisAlignedBox(min_x, min_y, min_z,
|
||||
max_x, max_y, max_z));
|
||||
return baseMesh;
|
||||
}
|
||||
void createTarget(const Ogre::String &targetName,
|
||||
const Ogre::Mesh *target)
|
||||
{
|
||||
MeshMorphTarget mtarget;
|
||||
int i, j, k, l;
|
||||
std::vector<SubMeshInformation> targetInfo;
|
||||
mtarget.skelp = Ogre::SkeletonManager::getSingleton().getByName(
|
||||
target->getSkeletonName(), "Characters");
|
||||
targetInfo.resize(target->getNumSubMeshes());
|
||||
for (i = 0; i < target->getNumSubMeshes(); i++) {
|
||||
getSubMeshInformation(target, target->getSubMesh(i),
|
||||
&targetInfo[i]);
|
||||
}
|
||||
std::vector<Ogre::Vector3> vertices;
|
||||
std::vector<Ogre::Vector3> normals;
|
||||
std::vector<Ogre::Vector2> uvs;
|
||||
std::vector<int> uv_submeshes;
|
||||
std::vector<int> uv_indices;
|
||||
std::vector<Ogre::Vector2> change_uvs;
|
||||
std::vector<MeshMorphTarget::DataChange> changes;
|
||||
for (i = 0; i < targetInfo.size(); i++) {
|
||||
const std::vector<Ogre::Vector2> &puv =
|
||||
targetInfo[i].uvs;
|
||||
const std::vector<Ogre::Vector3> &pvertices =
|
||||
targetInfo[i].vertices;
|
||||
const std::vector<Ogre::Vector3> &pnormals =
|
||||
targetInfo[i].normals;
|
||||
for (j = 0; j < pvertices.size(); j++) {
|
||||
MeshMorphTarget::DataChange dc;
|
||||
dc.index = -1;
|
||||
dc.submesh = -1;
|
||||
change_uvs.push_back(puv[j]);
|
||||
dc.normal = pnormals[j];
|
||||
dc.vertex = pvertices[j];
|
||||
changes.push_back(dc);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < submesh.size(); i++) {
|
||||
int submesh_id = i;
|
||||
for (j = 0; j < submesh[i].vertices.size(); j++) {
|
||||
int index_id = j;
|
||||
const Ogre::Vector2 &xuv = submesh[i].uvs[j];
|
||||
uvs.push_back(xuv);
|
||||
uv_submeshes.push_back(submesh_id);
|
||||
uv_indices.push_back(index_id);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < changes.size(); i++) {
|
||||
float l = 1.0f;
|
||||
int sub = -1, index = -1;
|
||||
for (j = 0; j < uvs.size(); j++) {
|
||||
float xl =
|
||||
change_uvs[i].squaredDistance(uvs[j]);
|
||||
if (xl < l) {
|
||||
l = xl;
|
||||
sub = uv_submeshes[j];
|
||||
index = uv_indices[j];
|
||||
}
|
||||
}
|
||||
OgreAssert(sub >= 0 && index >= 0, "Indexing error");
|
||||
if (l < 0.000000005f) {
|
||||
changes[i].submesh = sub;
|
||||
changes[i].index = index;
|
||||
}
|
||||
}
|
||||
mtarget.vertices = changes;
|
||||
|
||||
mtarget.weight = 0.0f;
|
||||
targets[targetName] = mtarget;
|
||||
}
|
||||
void setTargetWeight(const Ogre::String &targetName, float weight)
|
||||
{
|
||||
if (targets.find(targetName) == targets.end())
|
||||
return;
|
||||
targets[targetName].weight = weight;
|
||||
}
|
||||
void applyMorphTargets()
|
||||
{
|
||||
auto it = targets.begin();
|
||||
float sum = 0.0f;
|
||||
while (it != targets.end()) {
|
||||
sum += it->second.weight;
|
||||
it++;
|
||||
}
|
||||
if (sum > 1.0f) {
|
||||
it = targets.begin();
|
||||
while (it != targets.end()) {
|
||||
it->second.weight = it->second.weight / sum;
|
||||
it++;
|
||||
}
|
||||
}
|
||||
it = targets.begin();
|
||||
while (it != targets.end()) {
|
||||
if (it->second.weight > 0.001f) {
|
||||
int i;
|
||||
for (i = 0; i < it->second.vertices.size();
|
||||
i++) {
|
||||
int sub_id =
|
||||
it->second.vertices[i].submesh;
|
||||
int index_id =
|
||||
it->second.vertices[i].index;
|
||||
if (sub_id < 0 || index_id < 0)
|
||||
continue;
|
||||
Ogre::Vector3 orig_vertex =
|
||||
submesh[sub_id]
|
||||
.vertices[index_id];
|
||||
Ogre::Vector3 new_vertex =
|
||||
it->second.vertices[i].vertex;
|
||||
Ogre::Vector3 vertex_update =
|
||||
Ogre::Math::lerp(
|
||||
orig_vertex, new_vertex,
|
||||
it->second.weight);
|
||||
Ogre::Vector3 orig_normal =
|
||||
submesh[sub_id]
|
||||
.normals[index_id];
|
||||
Ogre::Vector3 new_normal =
|
||||
it->second.vertices[i].normal;
|
||||
Ogre::Vector3 normal_update =
|
||||
Ogre::Math::lerp(
|
||||
orig_normal, new_normal,
|
||||
it->second.weight);
|
||||
submesh[sub_id].vertices[index_id] =
|
||||
vertex_update;
|
||||
submesh[sub_id].normals[index_id] =
|
||||
normal_update;
|
||||
}
|
||||
}
|
||||
it++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct SimpleListener : public OgreBites::InputListener {
|
||||
App *mApp;
|
||||
SimpleListener(App *app)
|
||||
: mApp(app)
|
||||
{
|
||||
}
|
||||
void frameRendered(const Ogre::FrameEvent &evt) override;
|
||||
};
|
||||
|
||||
class App : public OgreBites::ApplicationContext {
|
||||
public:
|
||||
App()
|
||||
: OgreBites::ApplicationContext("MorphTargetsResearch")
|
||||
{
|
||||
}
|
||||
void locateResources() override
|
||||
{
|
||||
Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
|
||||
"Characters", true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"./characters", "FileSystem", "Characters", true, true);
|
||||
Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
|
||||
"../characters", "FileSystem", "Characters", true,
|
||||
true);
|
||||
OgreBites::ApplicationContext::locateResources();
|
||||
}
|
||||
void loadResources() override
|
||||
{
|
||||
}
|
||||
void meshProcessing()
|
||||
{
|
||||
int i;
|
||||
//code to test and create entity based off of sub-meshes
|
||||
|
||||
//vector of meshes
|
||||
std::vector<Ogre::MeshPtr> m_Meshes;
|
||||
|
||||
//define meshes
|
||||
Ogre::MeshPtr base = Ogre::MeshManager::getSingleton().load(
|
||||
"male/normal-male.glb", "Characters");
|
||||
m_Meshes.push_back(base);
|
||||
Ogre::MeshPtr shape = Ogre::MeshManager::getSingleton().load(
|
||||
"shapes/male/edited-shape-test-male.glb", "Characters");
|
||||
OgreAssert(shape, "no shape");
|
||||
MeshInformation meshinfo(base.get());
|
||||
std::string m_ModelId = "MergedMesh";
|
||||
meshinfo.createTarget("shape", shape.get());
|
||||
meshinfo.setTargetWeight("shape", 1.0f);
|
||||
Ogre::MeshPtr m_BaseMesh = meshinfo.create(m_ModelId);
|
||||
Ogre::Entity *ent =
|
||||
mScnMgr->createEntity("entName", m_BaseMesh->getName());
|
||||
// ent->setMaterialName("TestMat");
|
||||
|
||||
//code here is temporary and only ment as a test for the modelers
|
||||
//Entity* testEntity = mSceneMgr->createEntity("cc", source->getName());
|
||||
//testEntity->setMaterialName("TestMat");
|
||||
Ogre::SceneNode *thisSceneNode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
// thisSceneNode->setPosition(100, 100, 100);
|
||||
thisSceneNode->attachObject(ent);
|
||||
mIdle = ent->getAnimationState("idle");
|
||||
mIdle->setEnabled(true);
|
||||
mIdle->setLoop(true);
|
||||
mIdle->setWeight(1.0f);
|
||||
}
|
||||
|
||||
void setup() override
|
||||
{
|
||||
OgreBites::ApplicationContext::setup();
|
||||
Ogre::Root *root = getRoot();
|
||||
Ogre::SceneManager *scnMgr = root->createSceneManager();
|
||||
Ogre::RTShader::ShaderGenerator *shadergen =
|
||||
Ogre::RTShader::ShaderGenerator::getSingletonPtr();
|
||||
shadergen->addSceneManager(scnMgr);
|
||||
// also need to tell where we are
|
||||
mScnMgr.reset(scnMgr);
|
||||
mCameraNode.reset(
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode());
|
||||
mCameraNode->setPosition(0, 2, 3);
|
||||
mCameraNode->lookAt(Ogre::Vector3(0, 1, -1),
|
||||
Ogre::Node::TS_PARENT);
|
||||
|
||||
Ogre::Light *light = mScnMgr->createLight("MainLight");
|
||||
Ogre::SceneNode *lightNode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode();
|
||||
// lightNode->setPosition(0, 10, 15);
|
||||
lightNode->setDirection(
|
||||
Ogre::Vector3(0.55, -0.3, 0.75).normalisedCopy());
|
||||
lightNode->attachObject(light);
|
||||
light->setType(Ogre::Light::LT_DIRECTIONAL);
|
||||
light->setDiffuseColour(Ogre::ColourValue::White);
|
||||
light->setSpecularColour(Ogre::ColourValue(0.4, 0.4, 0.4));
|
||||
|
||||
mScnMgr->setAmbientLight(
|
||||
Ogre::ColourValue(0.5f, 0.5f, 0.5f, 1.0f));
|
||||
|
||||
// create the camera
|
||||
Ogre::Camera *cam = mScnMgr->createCamera("normal_camera");
|
||||
cam->setNearClipDistance(0.1f); // specific to this sample
|
||||
cam->setAutoAspectRatio(true);
|
||||
mCameraNode->attachObject(cam);
|
||||
mCamera.reset(cam);
|
||||
|
||||
// and tell it to render into the main window
|
||||
getRenderWindow()->addViewport(cam);
|
||||
meshProcessing();
|
||||
#if 0
|
||||
Ogre::Entity *ent_base =
|
||||
mScnMgr->createEntity("male/normal-male.glb");
|
||||
Ogre::Entity *ent_shape = mScnMgr->createEntity(
|
||||
"shapes/male/chibi/vroid-normal-male-chibi.glb");
|
||||
Ogre::SceneNode *characterNode =
|
||||
mScnMgr->getRootSceneNode()->createChildSceneNode("ch");
|
||||
characterNode->attachObject(ent_base);
|
||||
#endif
|
||||
addInputListener(OGRE_NEW SimpleListener(this));
|
||||
}
|
||||
void animationTime(float time)
|
||||
{
|
||||
mIdle->addTime(time);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ogre::SceneNode> mCameraNode;
|
||||
std::unique_ptr<Ogre::Camera> mCamera;
|
||||
std::unique_ptr<Ogre::SceneManager> mScnMgr;
|
||||
Ogre::AnimationState *mIdle;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
App ctx;
|
||||
ctx.initApp();
|
||||
ctx.setWindowGrab(true);
|
||||
|
||||
ctx.getRoot()->startRendering();
|
||||
ctx.setWindowGrab(false);
|
||||
ctx.closeApp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SimpleListener::frameRendered(const Ogre::FrameEvent &evt)
|
||||
{
|
||||
mApp->animationTime(evt.timeSinceLastFrame);
|
||||
}
|
||||
Reference in New Issue
Block a user