Robert White

robert.white

About Me

Expertise
Not Specified
Location
Not Specified
Website

Connect

Recent Forum Posts

HAPI_SetHeightFieldData Sept. 20, 2017, 6:54 p.m.

So I was finally able to get something that worked.

Instead of pushing the data into a sop/heightfield, I created a an input node and gave it a HAPI_PARTTYPE_VOLUME.
The other missing parts seemed to be that I needed a volume visualization node, and that my volume info transforms all had scales of 0, which kind of made it hard to visualize anything.

In case anyone else runs into a similar problem, this is what finally worked.

If there is a smarter / better way to do this please let me know. I'm kind of flailing in the dark with the current examples.

#include <HAPI/HAPI.h>
#include <iostream>
#include <string>
#include <vector>
#include <random>


#define ENSURE_SUCCESS( result ) \
if ( (result) != HAPI_RESULT_SUCCESS ) \
{ \
    std::cout << "Failure at " << __FILE__ << ": " << __LINE__ << std::endl; \
    std::cout << getLastError() << std::endl; \
    exit( 1 ); \
}

static std::string getLastError();
static std::string getString( HAPI_StringHandle stringHandle );

int
main( int argc, char ** argv )
{

	HAPI_CookOptions cookOptions = HAPI_CookOptions_Create();

	HAPI_Session session;

	HAPI_CreateInProcessSession( &session );

	ENSURE_SUCCESS( HAPI_Initialize( &session, &cookOptions, true, -1, nullptr, nullptr, nullptr, nullptr, nullptr ) );
	
	HAPI_NodeId volume_visualization_id = -1;
	HAPI_NodeId height_input_id = -1;
	HAPI_NodeId display_node_id = -1;
	HAPI_NodeInfo volume_visualization_info = HAPI_NodeInfo_Create();
	
	HAPI_ParmId vis_id = -1;
	HAPI_ParmId density_id = -1;
	HAPI_ParmInfo parm_info = HAPI_ParmInfo_Create();

	HAPI_NodeId merge_node_id = -1;
	
	ENSURE_SUCCESS( HAPI_CreateNode( &session, -1, "sop/volumevisualization", "MergeNode", false, &volume_visualization_id ) );

	ENSURE_SUCCESS( HAPI_SetParmIntValue( &session, volume_visualization_id, "vismode", 0, 2 ) );
	ENSURE_SUCCESS( HAPI_GetParmIdFromName( &session, volume_visualization_id, "densityfield", &density_id ) );
	ENSURE_SUCCESS( HAPI_GetParmInfo( &session, volume_visualization_id, density_id, &parm_info ) );
	ENSURE_SUCCESS( HAPI_SetParmStringValue( &session, volume_visualization_id, "height", density_id, 0 ) );
	
	ENSURE_SUCCESS( HAPI_CookNode( &session, volume_visualization_id, nullptr ) );

	display_node_id = volume_visualization_id;
	
	
	char * name = "height";
	int start = 0;
	HAPI_PartId part_id = 0;	
	HAPI_NodeId volume_node_id = -1;
	
	ENSURE_SUCCESS( HAPI_CreateInputNode( &session, &volume_node_id, name ) );
	ENSURE_SUCCESS( HAPI_CookNode( &session, volume_node_id, nullptr) );

	HAPI_GeoInfo volume_geo_info = HAPI_GeoInfo_Create();
	ENSURE_SUCCESS( HAPI_GetDisplayGeoInfo( &session, volume_node_id, &volume_geo_info ) );

	HAPI_Transform transform = HAPI_Transform_Create();

	transform.scale[0] = 1000.0f;
	transform.scale[1] = 1000.0f;
	transform.scale[2] = 1.0f;
	
	HAPI_VolumeInfo heightfield_volume_info = HAPI_VolumeInfo_Create();

	heightfield_volume_info.xLength = 500;
	heightfield_volume_info.yLength = 500;
	heightfield_volume_info.zLength = 1;
	
	heightfield_volume_info.minX = 0;
	heightfield_volume_info.minY = 0;
	heightfield_volume_info.minZ = 0;
	
	heightfield_volume_info.transform = transform;

	heightfield_volume_info.type = HAPI_VOLUMETYPE_HOUDINI;
	heightfield_volume_info.storage = HAPI_STORAGETYPE_FLOAT;
	heightfield_volume_info.tupleSize = 1;
	heightfield_volume_info.tileSize = 1;

	heightfield_volume_info.hasTaper = false;
	heightfield_volume_info.xTaper = 0.0;
	heightfield_volume_info.yTaper = 0.0;
	
	const int totalsize = ( heightfield_volume_info.xLength * heightfield_volume_info.yLength );
	std::vector< float > heightfieldData( totalsize );
	
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_real_distribution<> dis(1, 2);
	for (int n = 0; n < totalsize; ++n)
	{
		heightfieldData[n] = (float)dis(gen);
	}

	HAPI_PartInfo part = HAPI_PartInfo_Create();
	
	part.nameSH = 0;
	part.id = part_id;
	part.attributeCounts[HAPI_ATTROWNER_POINT]  = 0;
	part.attributeCounts[HAPI_ATTROWNER_PRIM]   = 1;
	part.attributeCounts[HAPI_ATTROWNER_VERTEX] = 0;
	part.attributeCounts[HAPI_ATTROWNER_DETAIL] = 0;
	part.pointCount = 0;
	part.vertexCount = 0;
	part.faceCount = 1;
	part.type = HAPI_PARTTYPE_VOLUME;

	ENSURE_SUCCESS( HAPI_SetPartInfo( &session, volume_geo_info.nodeId, part.id, &part ) );

	ENSURE_SUCCESS( HAPI_SetVolumeInfo( &session, volume_geo_info.nodeId, part.id, &heightfield_volume_info ) );

	ENSURE_SUCCESS( HAPI_SetHeightFieldData( &session, volume_geo_info.nodeId, part.id, heightfieldData.data(), start, totalsize, name ) );

	ENSURE_SUCCESS( HAPI_CommitGeo( &session, volume_geo_info.nodeId ) );
	ENSURE_SUCCESS( HAPI_CookNode( &session, volume_geo_info.nodeId, nullptr ) );
	
	// ENSURE_SUCCESS( HAPI_ConnectNodeInput( &session, merge_node_id, 0, volume_geo_info.nodeId ) );

	ENSURE_SUCCESS( HAPI_ConnectNodeInput( &session, volume_visualization_id, 0, volume_geo_info.nodeId ) );
	ENSURE_SUCCESS( HAPI_CookNode( &session, volume_visualization_id, nullptr ) );
	
	ENSURE_SUCCESS( HAPI_SaveHIPFile( &session, "height_field.hip", false ) );
	HAPI_Cleanup( &session );
	
	return 0;
}

static std::string
getLastError()
{
    int bufferLength;
    HAPI_GetStatusStringBufLength( nullptr, HAPI_STATUS_CALL_RESULT, HAPI_STATUSVERBOSITY_ERRORS, &bufferLength );

    char * buffer = new char[ bufferLength ];

    HAPI_GetStatusString( nullptr, HAPI_STATUS_CALL_RESULT, buffer, bufferLength );

    std::string result( buffer );
    delete [] buffer;

    return result;
}
static std::string
getString( HAPI_StringHandle stringHandle )
{
    if ( stringHandle == 0 )
    {
	return "";
    }

    int bufferLength;
    HAPI_GetStringBufLength( nullptr,
				   stringHandle,
				   &bufferLength );

    char * buffer = new char[ bufferLength ];

    HAPI_GetString ( nullptr, stringHandle, buffer, bufferLength );

    std::string result( buffer );
    delete [] buffer;

    return result;
}

HAPI_SetHeightFieldData Sept. 20, 2017, 2:01 p.m.

So I've been struggling with getting just a simple example of HAPI_SetHeightFieldData to work.

I've hacked together a simple example from the documentation, and the provided examples, and while I get a hip file, and it clearly has data in it (just around 1MB), when I open that file the heightfield node is locked and won't render. I also can't use it as an input into another height field nodes with out it triggering an error.

Am I missing a step? Is there no way to actually visualize the results when mucking about with height fields?
Are there any examples of generating a heightfield input from data?

#include <HAPI/HAPI.h>
#include <iostream>
#include <string>
#include <vector>
#include <random>


#define ENSURE_SUCCESS( result ) \
if ( (result) != HAPI_RESULT_SUCCESS ) \
{ \
    std::cout << "Failure at " << __FILE__ << ": " << __LINE__ << std::endl; \
    std::cout << getLastError() << std::endl; \
    exit( 1 ); \
}

static std::string getLastError();

int
main( int argc, char ** argv )
{

	HAPI_CookOptions cookOptions = HAPI_CookOptions_Create();

	HAPI_Session session;

	HAPI_CreateInProcessSession( &session );

	ENSURE_SUCCESS( HAPI_Initialize( &session, &cookOptions, true, -1, nullptr, nullptr, nullptr, nullptr, nullptr ) );
	
	int start = 0;
	int part_id = 0;
	HAPI_NodeId out_node_id = -1;
	ENSURE_SUCCESS( HAPI_CreateNode( &session, -1, "sop/heightfield", nullptr, true, &out_node_id ) );

	HAPI_GeoInfo out_geo_info = HAPI_GeoInfo_Create();
	ENSURE_SUCCESS( HAPI_GetDisplayGeoInfo( &session, out_node_id, &out_geo_info ) );
	
	HAPI_PartInfo out_part_info = HAPI_PartInfo_Create();
	ENSURE_SUCCESS( HAPI_GetPartInfo( &session, out_geo_info.nodeId, part_id, &out_part_info ) );
	
	HAPI_VolumeInfo height_volume_info = HAPI_VolumeInfo_Create();
	ENSURE_SUCCESS( HAPI_GetVolumeInfo( &session, out_geo_info.nodeId, part_id, &height_volume_info ) );

	const int totalsize = ( height_volume_info.xLength * height_volume_info.yLength );
	std::vector< float > heightfieldData( totalsize );
	
	std::random_device rd;
	std::mt19937 gen(rd());
	std::uniform_real_distribution<> dis(1, 2);
	for (int n = 0; n < totalsize; ++n) {
		heightfieldData[n] = (float)dis(gen);
	}
	
	height_volume_info.type = HAPI_VOLUMETYPE_HOUDINI;
	height_volume_info.storage = HAPI_STORAGETYPE_FLOAT;
	height_volume_info.tupleSize = 1;
	height_volume_info.tileSize = 1;
	height_volume_info.zLength = 1;
	height_volume_info.hasTaper = false;
	height_volume_info.xTaper = 0.0;
	height_volume_info.yTaper = 0.0;

	ENSURE_SUCCESS( HAPI_SetVolumeInfo( &session, out_geo_info.nodeId, 0, &height_volume_info ) );

	ENSURE_SUCCESS( HAPI_SetHeightFieldData( &session, out_geo_info.nodeId, 0, heightfieldData.data(), start, totalsize, "height" ) );
	
	ENSURE_SUCCESS( HAPI_CommitGeo( &session, out_geo_info.nodeId ) );
	ENSURE_SUCCESS( HAPI_CookNode( &session, out_geo_info.nodeId, nullptr ) );

	ENSURE_SUCCESS( HAPI_SaveHIPFile( &session, "height_field.hip", false ) );
	HAPI_Cleanup( &session );
	
	return 0;
}

static std::string
getLastError()
{
    int bufferLength;
    HAPI_GetStatusStringBufLength( nullptr, HAPI_STATUS_CALL_RESULT, HAPI_STATUSVERBOSITY_ERRORS, &bufferLength );

    char * buffer = new char[ bufferLength ];

    HAPI_GetStatusString( nullptr, HAPI_STATUS_CALL_RESULT, buffer, bufferLength );

    std::string result( buffer );
    delete [] buffer;

    return result;
}