Is CalculateVisiblePoints() useable?



  • Hello, I'm trying to find all of the visible points from the point of view of a given BaseDraw. It seems like CalculateVisiblePoints() should be exactly what I need, but I'm not getting results that make any sense to me.

    It seems like the function would do exactly what I'm looking for and a search only turned up a thread about it not being available in Python from years ago. I've seen other threads about getting visible object points, but I wanted to see if CalculateVisiblePoints() would work before moving onto one of those.

    My tests have just involved a polygon cube and rotating around it, but the visible points aren't consistent with the view.

    My current code:

        BaseObject* child =op->GetDown();
        if(child== nullptr ||child->GetType() != Opolygon)
        {
            return;
        }
       
        PolygonObject* polyobj = static_cast<PolygonObject*>(child);
        BaseDraw* bd = doc->GetActiveBaseDraw();
        if(bd==nullptr)
        {
            return;
        }
        Vector* vectors = polyobj->GetPointW();
        UChar* results;
        if (CalculateVisiblePoints(bd, polyobj, vectors, results, TRUE) == FALSE)
        {
            return;
        }
       
        Int32 pointcount =polyobj->GetPointCount();
        for (Int32 x=0; x<pointcount; x++)
        {
            
            if (results[x] ==1)
            {
                ApplicationOutput(String::IntToString(x) + " Visible");
            }
            else if (results[x] ==0)
            {
                ApplicationOutput(String::IntToString(x) + " Not Visible");
            }
            else
            {
                ApplicationOutput("-Empty-");
            }
            
        }
    

    Thanks for any help,
    Dan



  • Hi Daniel, thanks for reaching out us.

    With regard to your issue, the question is what values we are passing to the CalculateVisiblePoints. The function is actually designed to receive an array specifying the world position of points in camera space. On top of this the function is supposed to receive a result array initialized to 1.

    For your convenience the solution should look like:

    	// check passed parameter
    	if (!doc)
    		return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    	
    	// check for an active object
    	BaseObject* op = doc->GetActiveObject();
    	if (!op)
    		return maxon::OK;
    	
    	// check for current BaseDraw
    	BaseDraw* activeBD = doc->GetActiveBaseDraw();
    	if (!activeBD)
    		return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    	
    	// check it's an instance of a Opolygon
    	if (!op->IsInstanceOf(Opolygon))
    		return maxon::OK;
    	
    	// cast active BaseObject in PolygonObject
    	PolygonObject* polyobj = static_cast<PolygonObject*>(op);
    	
    	// get the point count
    	const Int32 pointCount = polyobj->GetPointCount();
    	if (pointCount == 0)
    		return maxon::OK;
    	
    	// get the active object points
    	const Vector* points = (Vector*)polyobj->GetPointR();
    	if (!points)
    		return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    	
    	// allocate a temporary array of points (same count of active object points)
    	Vector* pointFromCam = nullptr;
    	pointFromCam = NewMem(Vector, pointCount) iferr_return;
    	
    	// calculate the a transformation of the active object as seen from the camera
    	Matrix mgObjFromCamera = activeBD->GetMi() * polyobj->GetMg();
    	
    	// fill the temporary array of points with active object points as seen from the camera space
    	for (Int32 p = 0; p < pointCount; p++)
    		pointFromCam[p] = mgObjFromCamera * points[p];
    	
    	// allocate an array to store the result of the visiblity check
    	UChar *pointVisRes = nullptr;
    	pointVisRes = NewMem(UChar, pointCount) iferr_return;
    	
    	// fill the visibility result array with 1
    	FillMemType(UChar, pointVisRes, pointCount, 1);
    	
    	// execute the visibility check
    	Bool res = CalculateVisiblePoints(activeBD, polyobj, pointFromCam, pointVisRes, true);
    	if (!res)
    	{
    		DeleteMem(pointFromCam);
    		DeleteMem(pointVisRes);
    		return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    	}
    	
    	// return the results in a more convenient format
    	maxon::String resString;
    	for (Int i = 0; i < polyobj->GetPointCount(); i++)
    		resString += FormatString(" @"_s, maxon::Int(pointVisRes[i]));
    	
    	// print the output
    	ApplicationOutput("visibility array:"_s + resString);
    	
    	// free the allocated resources
    	DeleteMem(pointFromCam);
    	DeleteMem(pointVisRes);
    	
    	return maxon::OK;
    

    Finally this stuff in Python is:

        if doc is None:
            return
    
        if op is None:
            return
    
        activeBD = doc.GetActiveBaseDraw()
        if activeBD is None:
            return
    
        visres = c4d.utils.CalculateVisiblePoints(activeBD, op, True)
        
        print visres
    

    Best, Riccardo



  • Thank you, Riccardo. That was exactly what I was doing wrong.

    Dan


Log in to reply