Solved 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