How to keep Texture mapping result

Thanks, @DavidEranen. I added issue to YouTrack with a mini plug-in and instructions: https://mcneel.myjetbrains.com/youtrack/issue/RH-46753

Hi @Jussi_Aaltonen

Yes, I run my command in Raytraced display mode, it is OK.
But, when I change to Rendered display mode, the texture mapping disappear, and I change to Raytraced display mode, the texture mapping still disappear.

Hi @Jussi_Aaltonen

About “custom render mesh provider”, I have other question.

When I load my plug-in with include DES_RenderMeshRMP.zip (2.6 KB)
and use

  RhRdkCustomRenderMeshManager().Add(new CDES_RenderMeshRMP())    

I open Rhino file, it has problem in the Rendered display mode, but , it is ok in the Raytraced display mode.

When I load my plug-in with include SampleRMP_h.zip (1.4 KB) in my plug-in,
and use

  RhRdkCustomRenderMeshManager().Add(new CSampleRMP())    

I open Rhino file, it is ok in the Rendered display mode.

Could you help me check what’s problem in the “DES_RenderMeshRMP”?

Thanks~

@angelwang I don’t know exact reason for why the object disappears but these are the differences causing it:

  1. IsViewDependent should return false in your case
  2. IsPreviewAndStandardSameMesh should return true in your case

Hi @Jussi_Aaltonen

Thank you very much for your reply.
Now it is OK~

1 Like

Hi @Jussi_Aaltonen

After running

  RhRdkCustomRenderMeshManager().Add(new CDES_RenderMeshRMP())    

I open a file

and run trim, but the trim result is NG.

Could you help me to check what happen?

Thanks~

Hi @Jussi_Aaltonen

DESSample_New.zip (49.0 KB) is my sample.

I run

  RhRdkCustomRenderMeshManager().Add(new CDES_RenderMeshRMP())    

in my sample, but I have problem as following description.

How to use

  RhRdkCustomRenderMeshManager().Add(new CDES_RenderMeshRMP())    

to make the render mesh moving immediately?

Thanks~

@angelwang You need to tell custom render mesh manager to ask for new meshes when objects are modified. Detecting modifications is easy using event watchers. You can simply subclass CRhinoEventWatcher and create one instance when your plug-in is loaded. In your event watcher subclass you can then override OnReplaceObject to inform custom render mesh manager about the modification like this:

void ExampleEventWatcher::OnReplaceObject(
  CRhinoDoc& doc,
  CRhinoObject& old_object,
  CRhinoObject& new_object)
{
  // Tell custom render mesh manager that an object has been modifed.
  // This causes custom render mesh manager to ask for updated custom
  // render meshes from all custom render mesh providers.
  // Note: use old_object when id of new_object is not set yet.
  ::RhRdkCustomRenderMeshManager().OnRhinoObjectChanged(doc, new_object.Attributes().m_uuid == ON_nil_uuid ? &old_object : &new_object);
}

You can call the same OnRhinoObjectChanged from your command to tell that the custom render meshes need to be updated. But your custom render mesh provider also needs to know how much to offset the meshes. I would use object user data to pass that information, see https://developer.rhino3d.com/guides/cpp/user-data/ for details.

@Jussi_Aaltonen
Thank you for your reply.

In my program
I select an object and then click the option " Increase".
When I click “Increase”, it calls a function which name is “RunMove”.

void CCommandcmdDES_MeshMove::RunMove(ON_SimpleArray<const CRhinoObject*> group_members, double dis)
{
  for (int i = 0; i < group_members.Count(); i++)
  {
    const CRhinoObject* pObject = *group_members.At(i);
    const ON_Brep* Brep = ON_Brep::Cast(pObject->Geometry());
    if (!Brep) return ;
    for (int j = 0; j < Brep->m_F.Count(); j++)
    {
      ON_BrepFace* F = Brep->Face(j);
      const ON_Surface* Sur = *Brep->m_S.At(j);
      ON_MeshParameters RhinosMeshParms = RhinoApp().ActiveDoc()->Properties().RenderMeshParameters();
      ON_Mesh* pMesh = F->CreateMesh(RhinosMeshParms);
      bool b = const_cast<ON_BrepFace*>(F)->SetMesh(ON::mesh_type::render_mesh, pMesh);

      if (nullptr != pMesh)
      {
        //pMesh->Transform(ON_Xform::TranslationTransformation(1.5 * ON_3dVector::ZAxis));
        //Move Vertex positoin
        ON_3fPointArray Vertex = pMesh->m_V;
        ON_2dPointArray pars = pMesh->m_S;
        for (int i = 0; i < Vertex.Count(); i++)
        {
          ON_3fPoint* p3f = Vertex.At(i);
          ON_2dPoint par = *pars.At(i);
          //ON_3dVector vec = ON_zaxis;
          ON_3dVector vec = Sur->NormalAt(par.x, par.y);
          //vec.Unitize(); vec = vec * 1.5;
          vec.Unitize(); vec = vec * dis;
          p3f->x = p3f->x + float(vec.x);
          p3f->y = p3f->y + float(vec.y);
          p3f->z = p3f->z + float(vec.z);
        }
        pMesh->m_V = Vertex;
      }
    }

  }
  RhRdkCustomRenderMeshManager().Add(new CSampleRMP());
  RhinoApp().ActiveDoc()->Regen();
}

In the function “Run Move”, I don’t know how to use

::RhRdkCustomRenderMeshManager().OnRhinoObjectChanged(doc, new_object.Attributes().m_uuid == ON_nil_uuid ? &amp;old_object : &amp;new_object);

Because in my program, I get object , find the object render mesh and set distance to the ON_Mesh::m_V, so there is no new or old object.

@angelwang You can get the object id using pObject pointer and pass it to the OnRhinoObjectChanged.

@Jussi_Aaltonen

Now I click “Increase”, I can see the render mesh moving immediately.
I modify the program as following

void CCommandcmdDES_MeshMove::RunMove(ON_SimpleArray<const CRhinoObject*> group_members, double dis)
{
  for (int i = 0; i < group_members.Count(); i++)
  {
    const CRhinoObject* pObject = *group_members.At(i);
    const ON_Brep* Brep = ON_Brep::Cast(pObject->Geometry());
    if (!Brep) return ;
    for (int j = 0; j < Brep->m_F.Count(); j++)
    {
      ON_BrepFace* F = Brep->Face(j);
      const ON_Surface* Sur = *Brep->m_S.At(j);
      ON_MeshParameters RhinosMeshParms = RhinoApp().ActiveDoc()->Properties().RenderMeshParameters();
      ON_Mesh* pMesh = F->CreateMesh(RhinosMeshParms);
      bool b = const_cast<ON_BrepFace*>(F)->SetMesh(ON::mesh_type::render_mesh, pMesh);

      if (nullptr != pMesh)
      {
        //pMesh->Transform(ON_Xform::TranslationTransformation(1.5 * ON_3dVector::ZAxis));
        //Move Vertex positoin
        ON_3fPointArray Vertex = pMesh->m_V;
        ON_2dPointArray pars = pMesh->m_S;
        for (int i = 0; i < Vertex.Count(); i++)
        {
          ON_3fPoint* p3f = Vertex.At(i);
          ON_2dPoint par = *pars.At(i);
          //ON_3dVector vec = ON_zaxis;
          ON_3dVector vec = Sur->NormalAt(par.x, par.y);
          //vec.Unitize(); vec = vec * 1.5;
          vec.Unitize(); vec = vec * dis;
          p3f->x = p3f->x + float(vec.x);
          p3f->y = p3f->y + float(vec.y);
          p3f->z = p3f->z + float(vec.z);
        }
        pMesh->m_V = Vertex;
      }
    }
   ::RhRdkCustomRenderMeshManager().OnRhinoObjectChanged(*pObject->Document(), pObject);
  }
  RhRdkCustomRenderMeshManager().Add(new CSampleRMP());
  RhinoApp().ActiveDoc()->Regen();
}
void CSampleRhinoEventWatcher::OnReplaceObject(CRhinoDoc& doc, CRhinoObject& old_object, CRhinoObject& new_object)
{
  ::RhRdkCustomRenderMeshManager().OnRhinoObjectChanged(doc, new_object.Attributes().m_uuid == ON_nil_uuid ? &old_object : &new_object);
}

When I run trim, it has trim result, but the render mesh disappear.
How to solve the problem?

You said I can use object user data to pass information to CRhRdkCustomRenderMeshProvider::BuildCustomMeshes, but I offset meshes in the “Run Move” function.

Run offset meshes in the “Run Move” function, is it wrong?

@angelwang You are asking good questions :slight_smile: I’m now writing a sample plug-in to answer them. It should be available within the next 24 hours.

You should not change the meshes on brep object. That has undefined behavior and will cause other problems. So don’t call ON_BrepFace::SetMesh. In general you should not use const_cast on Rhino objects or geometry.

Instead you need to get your “dis” parameter to your CRMP (custom render mesh provider). Your CRMP will get called when Rhino needs a render or preview mesh for an object. And at that point your CRMP needs to know the “dis” so it can do the correct amount of displacement. Good way to pass needed information to CRMP is to attach it to Rhino object as user data.

One more thing is that you only need to add your CRMP to Rhino once. This bit of code does that:

RhRdkCustomRenderMeshManager().Add(new CSampleRMP());

One good place for it is in OnLoadPlugIn.

All of this will be covered in the sample plug-in.

I’ve added SampleCustomRenderMesh project to c++ samples:

Hi @Jussi_Aaltonen

Thank you for your kindly reply. :slightly_smiling_face:

I try the “SampleCustomRenderMesh”, I found when I set Amount and I can see render mesh moving, but when I press Enter, render mesh disappear.

Could you check the sample again?

Hi @angelwang, Thanks for testing! I could not get the mesh to disappear but I saw pressing enter did not apply the current amount setting. That’s fixed now. If you still encounter some oddness please report your Rhino version (output from the _SystemInfo command in Rhino).

Hi @Jussi_Aaltonen

About my display deformation render meshes problem, it almost solves.
Thank you very much :rofl:

Once the RH-46753 get fixed and if it test OK, I’ll release our Plugin for Rhino6.

1 Like

Hi @angelwang
Super great to hear I was able to help you :smiley:

@angelwang I have just fixed RH-46753. It should work find in the next release candidate of SR8 - due out on Wednesday

Hi @andy

Today I found the new version for Rhino6 SDK is 6.7.18199.22081, does this version have fixed RH-46753?