Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Rendering a Vertex Map [SOLVED]

    SDK Help
    0
    7
    726
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • H
      Helper
      last edited by

      On 31/08/2016 at 06:10, xxxxxxxx wrote:

      User Information:
      Cinema 4D Version:   14+ 
      Platform:   Windows  ;   Mac OSX  ; 
      Language(s) :     C++  ;

      ---------
      Hello,

      I am trying to create a shader that renders a vertex map according to its weights, similar to the C4D Vertex Map shader.

      In the output of the shader, I am stuck on how to apply the vertex map weights to the shader.

      Here is some code:

        
      if (cd->vd)
      {
      	RayObject* link = cd->vd->op->link;   // get the object to which the shader is applied
        
      	const SReal *weights;
      	for (BaseTag* baseTag = link->GetFirstTag(); baseTag; baseTag = baseTag->GetNext())
      	{
      		if (!baseTag->IsInstanceOf(Tvertexmap)) continue;
      			
      		VertexMapTag *vmapTag = (VertexMapTag * )baseTag;
      		weights = vmapTag ->GetDataAddressR();						// successfully got the weights of the vertex map
        
      		// ..................... how to render these weights????
      					
      	}
      }
        
      
      

      Any help would be greatly appreciated.

      1 Reply Last reply Reply Quote 0
      • H
        Helper
        last edited by

        On 31/08/2016 at 23:29, xxxxxxxx wrote:

        Basically I am looking for a way to get the vertex index, which I would then feed into the weights and get the result.

        I could get the polygon ID with cd->vd->lhit and then GetyPolygon() and extract the vertex IDs out of it, but it renders the result polygon-rigid.

        Anyway to get the vertex index inside the shader Output ?

        1 Reply Last reply Reply Quote 0
        • H
          Helper
          last edited by

          On 01/09/2016 at 01:52, xxxxxxxx wrote:

          Hello,

          as you said, you can get the ID of the hit polygon with GetPolygon(). Also you can get the RayObject that was hit with GetObject().

          Then you can use the polygon ID to access the polygon from the polygon array of the RayObject. The polygon stores the indices of the used vertices. With that vertex indices you can access the data stored in the vertex map.

          Please notice that inside a shader you do not sample a vertex. You sample a point on the surface. This point is inside the polygon that is defined by the vertices. So you have to interpolate the different values of the given vertices to end up with one value for your point. One can easily obtain the needed weights using GetWeights().

          best wishes,
          Sebastian

          1 Reply Last reply Reply Quote 0
          • H
            Helper
            last edited by

            On 01/09/2016 at 02:14, xxxxxxxx wrote:

            I was missing the interpolation with GetWeights()

            Thank you for the hint Sebastian!

            1 Reply Last reply Reply Quote 0
            • H
              Helper
              last edited by

              On 01/09/2016 at 08:19, xxxxxxxx wrote:

              Could you please post the working solution?
              I hate it when people ask questions and then never post the solution.

              Vector MyShader::Output(BaseShader *chn, ChannelData *cd)  
              {  
                Real px = cd->p.x;  
                Real py = cd->p.y;  
                
                Vector outputColor(0.0);  //black  
                
                //This code block runs only while rendering  
                if (cd->vd && cd->vd->op)  
                {  
                    //Get the name of the host object only when scene is rendered  
                    BaseObject *obj = cd->vd->op->link;  
                    //GePrint(obj->GetName());  
                
                    const SReal *weights;  
                    for (BaseTag *baseTag = obj->GetFirstTag(); baseTag; baseTag = baseTag->GetNext())  
                    {  
                        if (!baseTag->IsInstanceOf(Tvertexmap)) continue;  
                
                        VertexMapTag *vmapTag = (VertexMapTag * )baseTag;  
                        weights = vmapTag->GetDataAddressR();  
                
                        LONG count = vmapTag->GetDataCount();  
                        for (LONG i = 0; i<count; i++)  
                        {  
                            GePrint(RealToString(weights[i]));  //Print the weight values in the vmapTag                 
                        }  
                          
                        RayHitID hid = cd->vd->lhit;  
                        RayObject *robj = hid.GetObject(cd->vd);  //The object            
                        LONG poly = hid.GetPolygon();             //The polygons hit by the render rays  
                
                
                        //Now what?  
                
                 
                    }  
                
                }  
                
                return outputColor;
              

              Thanks,
              -ScottA

              1 Reply Last reply Reply Quote 0
              • H
                Helper
                last edited by

                On 01/09/2016 at 10:26, xxxxxxxx wrote:

                Sorry about that. It wasn't intentional.

                Anyway, you are almost there. You just need to calculate the barycentric weights with GetWeights(), like this:

                  
                	PolygonObject* pobj = ToPoly(link);
                	CPolygon *polys = pobj->GetPolygonW();
                  
                	CPolygon poly = polys[polyID]; // polyID is the polygon index
                  
                	// the following is inspired by the SDK documentation
                  
                	RayPolyWeight weight;
                	cd->vd->GetWeights(cd->vd->lhit, cd->vd->p, &weight);
                  
                	Real rWeightA, rWeightB, rWeightC, rWeightD;
                	LONG lIndexA = poly.a;
                	LONG lIndexB = poly.b;
                	LONG lIndexC = poly.c;
                	LONG lIndexD = poly.d; 
                	rWeightA = weights[lIndexA];
                	rWeightB = weights[lIndexB];
                	rWeightC = weights[lIndexC];
                	rWeightD = weights[lIndexD];
                	
                	outputColor = weight.wa * rWeightA + weight.wb * rWeightB + weight.wc * rWeightC + weight.wd * rWeightD;
                  
                
                

                I hope this helps you out.

                1 Reply Last reply Reply Quote 0
                • H
                  Helper
                  last edited by

                  On 01/09/2016 at 11:34, xxxxxxxx wrote:

                  Thanks a lot for the missing pieces. I'm sure it will help other people too. 🍺

                  My working code:

                  //This code maps and renders the color values from a Tvertexmap tag to a specific polygon on an object  
                    
                  Vector MyShader::Output(BaseShader *chn, ChannelData *cd)  
                  {  
                    //These are not used..For reference purposes only  
                    //Real px = cd->p.x;  
                    //Real py = cd->p.y;  
                    
                    //Start out with everything rendered black  
                    Vector outputColor(0);  
                    
                    //This code block runs only while rendering  
                    if (cd->vd && cd->vd->op)  
                    {  
                        //Get the host object only when the scene is rendered  
                        BaseObject *obj = cd->vd->op->link;  
                    
                        //Cast it to a polygon type object  
                        PolygonObject *pobj = ToPoly(obj);  
                    
                        //The specific polygon that we want to apply the vertex map tag's values to  
                        //Change as desired  
                        LONG polyID = 0;  
                        CPolygon *polys = pobj->GetPolygonW();          
                        CPolygon poly = polys[polyID];  
                    
                        //Not used..For reference purposes only          
                        //RayHitID hid = cd->vd->lhit;  
                        //RayObject *robj = hid.GetObject(cd->vd);  //The object            
                        //LONG poly = hid.GetPolygon();             //The polygons hit by the render rays  
                    
                        const SReal *weights;  
                        for (BaseTag *baseTag = obj->GetFirstTag(); baseTag; baseTag = baseTag->GetNext())  
                        {  
                            if (!baseTag->IsInstanceOf(Tvertexmap)) continue;  
                    
                            VertexMapTag *vmapTag = (VertexMapTag * )baseTag;  
                            weights = vmapTag->GetDataAddressR();  
                              
                            RayPolyWeight weight;  
                            cd->vd->GetWeights(cd->vd->lhit, cd->vd->p, &weight);  
                    
                            Real rWeightA, rWeightB, rWeightC, rWeightD;  
                            LONG lIndexA = poly.a;  
                            LONG lIndexB = poly.b;  
                            LONG lIndexC = poly.c;  
                            LONG lIndexD = poly.d;  
                            rWeightA = weights[lIndexA];  
                            rWeightB = weights[lIndexB];  
                            rWeightC = weights[lIndexC];  
                            rWeightD = weights[lIndexD];  
                            outputColor = weight.wa * rWeightA + weight.wb * rWeightB + weight.wc * rWeightC + weight.wd * rWeightD;  
                        }  
                    }  
                    
                    return outputColor;  
                  }
                  

                  -ScottA

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post