Forums Gallery LOGIN |REGISTER

Community Archive is read-only - Here you can view content recorded up until February 2017. To join the latest discussions visit our new forums


Dynamic Mesh Creation.

Please use this forum for questions on C++, Lua, XML, and any other languages used in CryENGINE development.


 

User avatar sunnlok
Producer
Producer
 
Posts: 1128
Member since: 19.04.2009, 01:21
Location: Germany
Likes: 221

Dynamic Mesh Creation.

Postby sunnlok » 15.06.2014, 20:07

Hey there,
i am currently stuck with creating new geometry during runtime.

Edit: Geometry works now!
Next thing: how to do physics.

Code: Select all
Lang: cpp
//Create a new stat object
      IStatObj *pObject = gEnv->p3DEngine->CreateStatObj();
      pObject->AddRef();


      //Init stuff
      IMaterial* pMaterial = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial("EngineAssets/TextureMsg/DefaultSolids");
      pEntity->SetMaterial(pMaterial);

      pObject->SetMaterial(pMaterial);

      IIndexedMesh *pMesh = pObject->GetIndexedMesh();

      if (pMesh == NULL)
         return;

      //Assign vert counts and stuff
      const size_t numVerts = 3;
      const size_t numTriangles = 1;

      pMesh->SetVertexCount(numVerts);
      pMesh->SetFaceCount(numTriangles);
      pMesh->SetTexCoordCount(numVerts);


      //Get the different mesh streams
      Vec3* const vertices = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::POSITIONS);
      Vec3* const normals = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::NORMALS);
      SMeshTexCoord* const texcoords = pMesh->GetMesh()->GetStreamPtr<SMeshTexCoord>(CMesh::TEXCOORDS);
      SMeshFace* const faces = pMesh->GetMesh()->GetStreamPtr<SMeshFace>(CMesh::FACES);
   

      //Assign stuff
      vertices[0] = Vec3(0.0f, 0.0f, 0.0f);

      texcoords[0].s = 0.0f;
      texcoords[0].t = 0.0f;

      vertices[1] = Vec3(0.0f, 10.0f, 0.0f);

      texcoords[1].s = 0.0f;
      texcoords[1].t = 1.0f;

      vertices[2] = Vec3(10.0f, 0.0f, 0.0f);

      texcoords[2].s = 1.0f;
      texcoords[2].t = 0.0f;

      SMeshFace* const meshface = &faces[0];

      //Vertex indices for the face?
      meshface->v[0] = 2;
      meshface->v[1] = 1;
      meshface->v[2] = 0;

      normals[0] = Vec3(1, 0, 0);
      normals[1] = Vec3(1, 0, 0);
      normals[2] = Vec3(1, 0, 0);

      //Yep.
      meshface->nSubset = 0;
   
      //Probably also does something. So yep.
      pMesh->SetSubSetCount(1);
      pMesh->SetSubsetMaterialId(0, 0);

      //Calc bounding box. then optimize stuff! Whatever that does...
      pMesh->CalcBBox();

      pMesh->Optimize();
      pMesh->RestoreFacesFromIndices();
   
      pObject->Invalidate(true);

      pEntity->Activate(true);
      int slotId = pEntity->SetStatObj(pObject, -1, true);
      pObject->Release();


Also to the person naming variables with one or two undescriptive letters and then adding no comments: I hate you :stare:
Last edited by sunnlok on 16.06.2014, 23:19, edited 2 times in total.
User avatar Rock_Deicide
Intern Dev
Intern Dev
 
Posts: 105
Member since: 16.06.2010, 10:37
Location: Russia, Togliatti
Likes: 9

Re: Dynamic Mesh Creation.

Postby Rock_Deicide » 15.06.2014, 22:14

How do you know that geometry wasn't created? Your code should create invisible geometry, since it doesn't mess with texture coordinates and materials, so it might be created but be invisible. Also, not so sure about bounding box code, it doesn't seem like box would fit this triangle.
User avatar sunnlok
Producer
Producer
 
Posts: 1128
Member since: 19.04.2009, 01:21
Location: Germany
Likes: 221

Re: Dynamic Mesh Creation.

Postby sunnlok » 15.06.2014, 22:25

I assumed that because no RenderMesh was generated, and it should still produce a visible triangle even without texture asignment. And for the AABB i know that the triangle probably doesnt fit in there^^ but i have no idea how to properly generate a fitting one.
User avatar hhildebr
Regular Dev
Regular Dev
 
Posts: 437
Member since: 28.08.2012, 23:09
Location: Berlin, Germany
Likes: 126

Re: Dynamic Mesh Creation.

Postby hhildebr » 15.06.2014, 23:03

Have you tried the opposite (clockwise) winding order for the indices? And (though that won't solve your problem): The triangle seems to lie in the xy plane, shouldn't the normal point upwards (0,0,1)?
User avatar stardidi
Regular Dev
Regular Dev
 
Posts: 579
Member since: 29.03.2013, 18:16
Location: Netherlands
Likes: 107

Re: Dynamic Mesh Creation.

Postby stardidi » 15.06.2014, 23:11

A few things come to mind, first off: winding order. Make sure to check that you aren't looking at the back side of the triangle, that is being culled.
Secondly: the bounding box is probably used for screen space culling, meaning that your triangle might get culled because it would be outside the screen according to your bounding box. There is likey a function to generate it, otherwise just use ons of the same dimensions as your triangle.
Your triangle also has no height, it might be easier if it were upright.

You also don't mention what this is in, so make sure your entity is where you think it is.
Although I haven't tried myself, I'm pretty sure you shouldn't release your statobj...
Programmer / game designer at World War III Online
Check out CryBlend
Remember to leave a like if someone helped you ;)
User avatar sunnlok
Producer
Producer
 
Posts: 1128
Member since: 19.04.2009, 01:21
Location: Germany
Likes: 221

Re: Dynamic Mesh Creation.

Postby sunnlok » 15.06.2014, 23:33

Size of the AABB didnt make a difference. The render mesh (the thing you see) doesnt exsist when i check next frame.
And the Release only decreases the reference counter and i do this since i added a reference to it at the beginning of the codeblock. Thats a smart pointer thing. It will only get deletet if all references are 0.
User avatar Rock_Deicide
Intern Dev
Intern Dev
 
Posts: 105
Member since: 16.06.2010, 10:37
Location: Russia, Togliatti
Likes: 9

Re: Dynamic Mesh Creation.

Postby Rock_Deicide » 16.06.2014, 06:04

If you can, try calling Invalidate function from static object itself, since it is a static object that is supposed to host both indexed and render meshes.
User avatar Blue
Junior Dev
Junior Dev
 
Posts: 328
Member since: 18.02.2009, 10:55
Likes: 22

Re: Dynamic Mesh Creation.

Postby Blue » 16.06.2014, 10:01

Without a texture you cant see what you have done. That be said, i made a flownode some time ago to create a mesh and bind it to the player pos (was just for test purposes ^^).

I may look later for it and post it here.


Best regards,

Blue
User avatar sunnlok
Producer
Producer
 
Posts: 1128
Member since: 19.04.2009, 01:21
Location: Germany
Likes: 221

Re: Dynamic Mesh Creation.

Postby sunnlok » 16.06.2014, 23:15

This works.

Code: Select all
//Create a new stat object
      IStatObj *pObject = gEnv->p3DEngine->CreateStatObj();
      pObject->AddRef();


      //Init stuff
      IMaterial* pMaterial = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial("EngineAssets/TextureMsg/DefaultSolids");
      pEntity->SetMaterial(pMaterial);

      pObject->SetMaterial(pMaterial);

      IIndexedMesh *pMesh = pObject->GetIndexedMesh();

      if (pMesh == NULL)
         return;

      //Assign vert counts and stuff
      const size_t numVerts = 3;
      const size_t numTriangles = 1;

      pMesh->SetVertexCount(numVerts);
      pMesh->SetFaceCount(numTriangles);
      pMesh->SetTexCoordCount(numVerts);


      //Get the different mesh streams
      Vec3* const vertices = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::POSITIONS);
      Vec3* const normals = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::NORMALS);
      SMeshTexCoord* const texcoords = pMesh->GetMesh()->GetStreamPtr<SMeshTexCoord>(CMesh::TEXCOORDS);
      SMeshFace* const faces = pMesh->GetMesh()->GetStreamPtr<SMeshFace>(CMesh::FACES);
   

      //Assign stuff
      vertices[0] = Vec3(0.0f, 0.0f, 0.0f);

      texcoords[0].s = 0.0f;
      texcoords[0].t = 0.0f;

      vertices[1] = Vec3(0.0f, 10.0f, 0.0f);

      texcoords[1].s = 0.0f;
      texcoords[1].t = 1.0f;

      vertices[2] = Vec3(10.0f, 0.0f, 0.0f);

      texcoords[2].s = 1.0f;
      texcoords[2].t = 0.0f;

      SMeshFace* const meshface = &faces[0];

      //Vertex indices for the face?
      meshface->v[0] = 2;
      meshface->v[1] = 1;
      meshface->v[2] = 0;

      normals[0] = Vec3(1, 0, 0);
      normals[1] = Vec3(1, 0, 0);
      normals[2] = Vec3(1, 0, 0);

      //Yep.
      meshface->nSubset = 0;
   
      //Probably also does something. So yep.
      pMesh->SetSubSetCount(1);
      pMesh->SetSubsetMaterialId(0, 0);

      //Calc bounding box. then optimize stuff! Whatever that does...
      pMesh->CalcBBox();

      pMesh->Optimize();
      pMesh->RestoreFacesFromIndices();
   
      pObject->Invalidate(true);

      pEntity->Activate(true);
      int slotId = pEntity->SetStatObj(pObject, -1, true);
      pObject->Release();


Now how to physics! ^^

Oh, and it doesnt need a material. It just defaults to the no material applied one.
User avatar crydevJim
Regular Dev
Regular Dev
 
Posts: 419
Member since: 22.06.2013, 21:46
Likes: 262

Re: Dynamic Mesh Creation.

Postby crydevJim » 18.06.2014, 19:12

sunnlok wrote:This works.

Indeed it does. I really like this procedural geometry stuff. Cool :)

Here is a cube, in case anyone is wondering how to move from a triangle to a solid object:

Code: Select all
   IStatObj *pObject = gEnv->p3DEngine->CreateStatObj();
   pObject->AddRef();

   IIndexedMesh *pMesh = pObject->GetIndexedMesh();

   if (pMesh == NULL)
      return;

   const size_t numVerts = 8;
   const size_t numTriangles = 12;

   pMesh->SetVertexCount(numVerts);
   pMesh->SetFaceCount(numTriangles);
   pMesh->SetTexCoordCount(numVerts);

   Vec3* const vertices = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::POSITIONS);
   Vec3* const normals = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::NORMALS);
   SMeshTexCoord* const texcoords = pMesh->GetMesh()->GetStreamPtr<SMeshTexCoord>(CMesh::TEXCOORDS);
   SMeshFace* const faces = pMesh->GetMesh()->GetStreamPtr<SMeshFace>(CMesh::FACES);

   vertices[0] = Vec3(0.0f, 0.0f, 0.0f);
   vertices[1] = Vec3(0.0f, 10.0f, 0.0f);
   vertices[2] = Vec3(0.0f, 0.0f, 10.0f);
   vertices[3] = Vec3(0.0f, 10.0f, 10.0f);
   vertices[4] = Vec3(10.0f, 10.0f, 0.0f);
   vertices[5] = Vec3(10.0f, 10.0f, 10.0f);
   vertices[6] = Vec3(10.0f, 0.0f, 0.0f);
   vertices[7] = Vec3(10.0f, 0.0f, 10.0f);

   SMeshFace* meshface = &faces[0];

   meshface->v[0] = 0;
   meshface->v[1] = 2;
   meshface->v[2] = 1;


   meshface = &faces[1];

   meshface->v[0] = 1;
   meshface->v[1] = 2;
   meshface->v[2] = 3;

   meshface = &faces[2];

   meshface->v[0] = 1;
   meshface->v[1] = 3;
   meshface->v[2] = 4;

   meshface = &faces[3];

   meshface->v[0] = 4;
   meshface->v[1] = 3;
   meshface->v[2] = 5;

   meshface = &faces[4];

   meshface->v[0] = 2;
   meshface->v[1] = 0;
   meshface->v[2] = 6;

   meshface = &faces[5];

   meshface->v[0] = 2;
   meshface->v[1] = 6;
   meshface->v[2] = 7;

   meshface = &faces[6];

   meshface->v[0] = 4;
   meshface->v[1] = 5;
   meshface->v[2] = 6;

   meshface = &faces[7];

   meshface->v[0] = 6;
   meshface->v[1] = 5;
   meshface->v[2] = 7;

   meshface = &faces[8];

   meshface->v[0] = 1;
   meshface->v[1] = 4;
   meshface->v[2] = 6;

   meshface = &faces[9];

   meshface->v[0] = 6;
   meshface->v[1] = 0;
   meshface->v[2] = 1;

   meshface = &faces[10];

   meshface->v[0] = 3;
   meshface->v[1] = 2;
   meshface->v[2] = 5;

   meshface = &faces[11];

   meshface->v[0] = 5;
   meshface->v[1] = 2;
   meshface->v[2] = 7;


(Edit: Updated to use just one pointer to SMeshFace )

sunnlok wrote:Now how to physics!


This seems to be enough to physicalize it:

Code: Select all
   
   SEntityPhysicalizeParams entityPhysParams;
   entityPhysParams.type = PE_RIGID;
   entityPhysParams.mass = 0;
   GetEntity()->Physicalize(entityPhysParams);
Last edited by crydevJim on 18.06.2014, 23:39, edited 1 time in total.
User avatar sunnlok
Producer
Producer
 
Posts: 1128
Member since: 19.04.2009, 01:21
Location: Germany
Likes: 221

Re: Dynamic Mesh Creation.

Postby sunnlok » 18.06.2014, 22:52

Whyyyy would you create a new variable for every mesh face o.0 . Its a help pointer. Just override it.
User avatar crydevJim
Regular Dev
Regular Dev
 
Posts: 419
Member since: 22.06.2013, 21:46
Likes: 262

Re: Dynamic Mesh Creation.

Postby crydevJim » 18.06.2014, 23:41

Good point, corrected. :)

I was more focused on the winding order etc. and to help people see how to get from one triangle to a surface. It wasn't that obvious to me at first. And to answer your question about how to physicalize the geometry.

Thanks for bringing this topic up again on the forums :)
User avatar avrudoi
Just getting started
Just getting started
 
Posts: 14
Member since: 16.06.2014, 19:30
Likes: 0

Re: Dynamic Mesh Creation.

Postby avrudoi » 20.06.2014, 21:53

still a question as to compile.
User avatar crydevJim
Regular Dev
Regular Dev
 
Posts: 419
Member since: 22.06.2013, 21:46
Likes: 262

Re: Dynamic Mesh Creation.

Postby crydevJim » 20.06.2014, 22:07

avrudoi wrote:still a question as to compile.

If it's the cube you mean, and if you just want a simple way to test the code, go into PlayerInput.cpp and replace these 2 lines:

Code: Select all
bool CPlayerInput::OnActionJump(EntityId entityId, const ActionId& actionId, int activationMode, float value)
{


with this code:

Code: Select all
void buildCube(Vec3 playerPos)
{
   IStatObj *pObject = gEnv->p3DEngine->CreateStatObj();
   pObject->AddRef();

   IMaterial* pMaterial = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial("EngineAssets/TextureMsg/DefaultSolids");

   pObject->SetMaterial(pMaterial);

   IIndexedMesh *pMesh = pObject->GetIndexedMesh();

   if (pMesh == NULL)
      return;

   const size_t numVerts = 8;
   const size_t numTriangles = 12;

   pMesh->SetVertexCount(numVerts);
   pMesh->SetFaceCount(numTriangles);
   pMesh->SetTexCoordCount(numVerts);

   Vec3* const vertices = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::POSITIONS);
   Vec3* const normals = pMesh->GetMesh()->GetStreamPtr<Vec3>(CMesh::NORMALS);
   SMeshTexCoord* const texcoords = pMesh->GetMesh()->GetStreamPtr<SMeshTexCoord>(CMesh::TEXCOORDS);
   SMeshFace* const faces = pMesh->GetMesh()->GetStreamPtr<SMeshFace>(CMesh::FACES);

   vertices[0] = Vec3(0.0f, 0.0f, 0.0f);
   vertices[1] = Vec3(0.0f, 10.0f, 0.0f);
   vertices[2] = Vec3(0.0f, 0.0f, 10.0f);
   vertices[3] = Vec3(0.0f, 10.0f, 10.0f);
   vertices[4] = Vec3(10.0f, 10.0f, 0.0f);
   vertices[5] = Vec3(10.0f, 10.0f, 10.0f);
   vertices[6] = Vec3(10.0f, 0.0f, 0.0f);
   vertices[7] = Vec3(10.0f, 0.0f, 10.0f);

   SMeshFace* meshface = &faces[0];

   meshface->v[0] = 0;
   meshface->v[1] = 2;
   meshface->v[2] = 1;

   meshface = &faces[1];

   meshface->v[0] = 1;
   meshface->v[1] = 2;
   meshface->v[2] = 3;

   meshface = &faces[2];

   meshface->v[0] = 1;
   meshface->v[1] = 3;
   meshface->v[2] = 4;

   meshface = &faces[3];

   meshface->v[0] = 4;
   meshface->v[1] = 3;
   meshface->v[2] = 5;

   meshface = &faces[4];

   meshface->v[0] = 2;
   meshface->v[1] = 0;
   meshface->v[2] = 6;

   meshface = &faces[5];

   meshface->v[0] = 2;
   meshface->v[1] = 6;
   meshface->v[2] = 7;

   meshface = &faces[6];

   meshface->v[0] = 4;
   meshface->v[1] = 5;
   meshface->v[2] = 6;

   meshface = &faces[7];

   meshface->v[0] = 6;
   meshface->v[1] = 5;
   meshface->v[2] = 7;

   meshface = &faces[8];

   meshface->v[0] = 1;
   meshface->v[1] = 4;
   meshface->v[2] = 6;

   meshface = &faces[9];

   meshface->v[0] = 6;
   meshface->v[1] = 0;
   meshface->v[2] = 1;

   meshface = &faces[10];

   meshface->v[0] = 3;
   meshface->v[1] = 2;
   meshface->v[2] = 5;

   meshface = &faces[11];

   meshface->v[0] = 5;
   meshface->v[1] = 2;
   meshface->v[2] = 7;

   meshface->nSubset = 0;

   pMesh->SetSubSetCount(1);
   pMesh->SetSubsetMaterialId(0, 0);

   pMesh->CalcBBox();

   pMesh->Optimize();
   pMesh->RestoreFacesFromIndices();

   pObject->Invalidate(true);

   SEntitySpawnParams spawnParams;
   spawnParams.pClass = gEnv->pEntitySystem->GetClassRegistry()->GetDefaultClass();

   IEntity *myEntity = gEnv->pEntitySystem->SpawnEntity(spawnParams);

   myEntity->SetPos(playerPos + Vec3(3, 3, 3));//Move it away slightly frmo the player

   myEntity->SetMaterial(pMaterial);

   SEntityPhysicalizeParams entityPhysParams;
   entityPhysParams.type = PE_RIGID;
   entityPhysParams.mass = 0;
   myEntity->Physicalize(entityPhysParams);

   myEntity->Activate(true);
   int slotId = myEntity->SetStatObj(pObject, 0, true);
   pObject->Release();
}


bool CPlayerInput::OnActionJump(EntityId entityId, const ActionId& actionId, int activationMode, float value)
{

   IEntity * pPlayer = g_pGame->GetIGameFramework()->GetClientActor()->GetEntity();

   if (activationMode == eAAM_OnPress)
      buildCube(pPlayer->GetPos());


And put this #include at the top of that file:

Code: Select all
#include "IIndexedMesh.h"


Then compile that (F7) and start a debugging session (F5) and open any level you want. Go into game mode (Ctrl-G) and then press the space bar to "jump". You should then see a cube like this:

cube.jpg

Hope that helps.
User avatar avrudoi
Just getting started
Just getting started
 
Posts: 14
Member since: 16.06.2014, 19:30
Likes: 0

Re: Dynamic Mesh Creation.

Postby avrudoi » 20.06.2014, 22:15

tell me how to compile the project in visual studio, I can not find proctitis in folders.