AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

Houdini18 HDK Offline Test

cmake_minimum_required(VERSION 3.5)

project(Triangle)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# OPENGL
find_package(OpenGL REQUIRED)
include_directories(${OpenGL_INCLUDE_DIRS})
link_directories(${OpenGL_LIBRARY_DIRS})
add_definitions(${OpenGL_DEFINITIONS})

if(NOT OPENGL_FOUND)
    message(ERROR " OPENGL not found!")
endif(NOT OPENGL_FOUND)

# GLEW
set(GLEW_HOME D:/plugin_dev/libs/glew-2.1.0)
include_directories(${GLEW_HOME}/include)
link_directories(${GLEW_HOME}/lib/Release/x64)

# GLFW
set(GLFW_HOME D:/plugin_dev/libs/glfw-3.3.1.bin.WIN64)
include_directories(${GLFW_HOME}/include/)
link_directories(${GLFW_HOME}/lib-vc2019)

# STB
include_directories(D:/plugin_dev/libs/stb)

# GLM
include_directories(D:/plugin_dev/libs/GLM_include)




# ---------------- HOUDINI
if (MSVC)
    # Prevent Boost auto-linking.
    add_definitions(-DBOOST_ALL_NO_LIB )
    add_definitions(-D_SCL_SECURE_NO_WARNINGS
            -D_CRT_SECURE_NO_WARNINGS
            -D_WIN32
            -D_WINSOCK_DEPRECATED_NO_WARNINGS
            -D__x86_64__)

    # HOUDINI :
    add_definitions(-TP
            -Zc:forScope
            -DVERSION="18.0.348"
            -DI386
            -DWIN32
            -DSWAP_BITFIELDS

            -DWINVER=0x0501
            -DNOMINMAX
            -DSTRICT
            -DWIN32_LEAN_AND_MEAN
            -D_USE_MATH_DEFINES
            -D_CRT_SECURE_NO_DEPRECATE
            -D_CRT_NONSTDC_NO_DEPRECATE
            -D_SCL_SECURE_NO_WARNINGS
            -DSESI_LITTLE_ENDIAN
            -DHBOOST_ALL_NO_LIB
            -DEIGEN_MALLOC_ALREADY_ALIGNED=0
            -DFBX_ENABLED=1
            -DOPENCL_ENABLED=1
            -DOPENVDB_ENABLED=1
            -MD
            -EHsc
            -GR
            -DNEED_SPECIALIZATION_STORAGE
            -DAMD64
            -DSIZEOF_VOID_P=8)

endif()


set(HOUDINI_HOME "D:/Program Files/Side Effects Software/Houdini 18.0.348")
include_directories("${HOUDINI_HOME}/toolkit/include")
link_directories("${HOUDINI_HOME}/custom/houdini/dsolib")





# output excutable dir
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build)


# SRC FILE
FILE(
    GLOB
    SRC
    *.cpp *.h
    )

add_executable(Triangle ${SRC})



target_link_libraries(Triangle
    PRIVATE
    libGA.lib
    libGU.lib
    libUT.lib
    libCE.lib
    libLM.lib
    libFS.lib
    libSYS.lib
    libGEO.lib

    )
CMakeLists

HDK Geometry Struct:

Houdini Geometry responsed to this figure:

1, get GLDraw info from this code:

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <iostream>


using namespace std;


int main(){
    GU_Detail gdp;
    gdp.load("geos/box.bgeo");

    cout << "Numpoints:"<<gdp.getNumPoints() <<endl;
    cout << "NumVerticles" << gdp.getNumVertices() << endl;
    cout << "NumFace:" << gdp.getNumPrimitives() << endl;

    // LOOP All face, cout this vertex count
    GEO_Primitive *geoPrim;
    GA_FOR_ALL_PRIMITIVES(&gdp,geoPrim){
         int faceCount = geoPrim->getVertexCount() ;// per face have 3 point


    }

    cout << "------------------ Iterator Face ID & Per face point ID, this can used  GL_DRAW_ELMENTS()----------------\n";
    GA_Iterator primIter(gdp.getPrimitiveRange());
    fpreal start_primtive_num = *primIter;
    cout << "START primtive num:" << start_primtive_num << endl;


    // loop the face(prim)
    for (;!primIter.atEnd();++primIter) {
        GA_Primitive *prim = gdp.getPrimitive(*primIter);


        // iterator face points
        cout <<"this face id :" << *primIter <<"->have vertex count:" <<prim->getVertexCount() << endl;
        GA_Iterator pointIter(prim->getPointRange());
        for(;!pointIter.atEnd();++pointIter){
            cout <<"share point id:" <<*pointIter << endl;
        }

    }


    cout << "------------------  access points Iterator directly not opengl draw indcices----------------\n";
    // Loop the point, direct access the point , not prim vertex shared point
    GA_Iterator pointIter(gdp.getPointRange());
    while(!pointIter.atEnd()){

        int pointNum = *pointIter ;
        GA_Index pointIndex = gdp.pointIndex(*pointIter);
        GA_Offset pointOffset = gdp.pointOffset(pointIndex);

        cout <<"Lookup -> Point id:" <<*pointIter << " Point Index:" << pointIndex
            << " Point offset:" << pointOffset
            << endl;

        GA_OffsetArray orry;
        gdp.getVerticesReferencingPoint(orry,pointOffset);
        cout <<"And this point have "<< orry.size() << " verticles, and the vertex number:" ;
        for(auto &of: orry){
            cout << of << " ";
        }
        cout << endl;
        ++pointIter;
    }







    cin.get();
    return 0;

}
main.cpp

 

The GA_Primitive class is a base class, GEO manipulate 3d  Geometry further .

 一些名词:Attribute Type Implementation (ATI), Each ATI class maintains arrays of data for each element in the geometry.The ATI provides interfaces (AIFs) for accessing the data. 

Some ATIs include GA_ATINumericGA_ATIStringGA_ATIIndexPair. Some AIFs include GA_AIFTupleGA_AIFSharedStringTuple, GA_AIFInterp. Numeric and string attributes can be accessed more easily and directly using the classes in GA_Handle.h (e.g. GA_ROHandleV3, GA_RWHandleS), and GA_PageHandle.h (e.g. GA_RWPageHandleV3).

属性的载体拥有者:

 

 

属性的GA_StorageClass

属性的长度:

GA_Attribute *att;
att->getTupleSize();

1为浮点(GA_StorageClass)的类型属性,

2为长度为2浮点(GA_StorageClass)类型,

3为长度为3的向量(GA_StorageClass)

.....

2,访问属性

GA_Attribute必须要作为参数输入到GA_RWHandle 开始的类对象,然后可以检查属性的可访问性。RW意思代表可以直接改属性到gdp

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <iostream>


using namespace std;


int main(){
    GU_Detail gdp;
    gdp.load("geos/box.bgeo");

    cout << "Numpoints:"<<gdp.getNumPoints() <<endl;
    cout << "NumVerticles" << gdp.getNumVertices() << endl;
    cout << "NumFace:" << gdp.getNumPrimitives() << endl;

    // LOOP All face, cout this vertex count
    GEO_Primitive *geoPrim;
    GA_FOR_ALL_PRIMITIVES(&gdp,geoPrim){
         int faceCount = geoPrim->getVertexCount() ;// per face have 3 point


    }

    cout << "------------------ Iterator Face ID & Per face point ID, this can used  GL_DRAW_ELMENTS()----------------\n";
    GA_Iterator primIter(gdp.getPrimitiveRange());
    fpreal start_primtive_num = *primIter;
    cout << "START primtive num:" << start_primtive_num << endl;


    // loop the face(prim)
    for (;!primIter.atEnd();++primIter) {
        GA_Primitive *prim = gdp.getPrimitive(*primIter);


        // iterator face points
        cout <<"this face id :" << *primIter <<"->have vertex count:" <<prim->getVertexCount() << endl;
        GA_Iterator pointIter(prim->getPointRange());
        for(;!pointIter.atEnd();++pointIter){
            cout <<"share point id:" <<*pointIter << endl;
        }

    }


    cout << "------------------  access points Iterator directly not opengl draw indcices----------------\n";
    cout << "method 1:\n";
    GA_Attribute *att =gdp.findPointAttribute("P");
    cout <<"attribute size:" <<att->getTupleSize() <<endl;
    GA_RWHandleV3 PAttribHandle(att);

    // Loop the point, direct access the point , not prim vertex shared point
    GA_Iterator pointIter(gdp.getPointRange());
    while(!pointIter.atEnd()){

        int pointNum = *pointIter ;     // This is point offset
        GA_Index pointIndex = gdp.pointIndex(*pointIter); // This is point index
        GA_Offset pointOffset = gdp.pointOffset(pointIndex); // This is point offset

        // ------ access the Position attribute ----------
        if(PAttribHandle.isValid()){
            UT_Vector3 P = PAttribHandle.get(pointOffset);
            cout <<"position: "<< P.x() << " " << P.y() << " " << P.z() <<endl;
        }
        else{
            cout << "can not access the Position \n";
        }
        ++pointIter;
    }

    cout << "method 2:\n";
    GA_RWHandleV3 Phandle(&gdp, GA_ATTRIB_POINT, "P");
    if (Phandle.isValid())
    {
        for (GA_Iterator it(gdp.getPointRange()); !it.atEnd(); ++it)
        {
            GA_Offset offset = *it;
            UT_Vector3 P = Phandle.get(offset);
            cout <<"position: "<< P.x() << " " << P.y() << " " << P.z() <<endl;
            P.y()+= 2.0;
            Phandle.set(offset, P);
        }
    }
    
    // save to disk 
    GA_SaveOptions saveOptions;
    gdp.save("change.bgeo",&saveOptions);
    
    
    
    
    cout << "method 3\n";
    GA_Attribute *attrib = gdp.findFloatTuple(GA_ATTRIB_POINT, "N", 3);
    const GA_AIFTuple *tuple = attrib->getAIFTuple();
    if (tuple)
    {
        UT_Vector3 P;
        for (GA_Iterator it(gdp.getPointRange()); !it.atEnd(); it.advance())
        {
            GA_Offset offset = it.getOffset();
            tuple->get(attrib, offset, P.data(), 3);
            
            // change P
            // .....
            tuple->set(attrib, offset, P.data(), 3);
        }
    }
    


    cin.get();
    return 0;

}
View Code

String Attribute:

假设面属性:

 修改后:

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <iostream>


using namespace std;


int main(){
    GU_Detail gdp;
    gdp.load("geos/box.bgeo");

    cout << "Numpoints:"<<gdp.getNumPoints() <<endl;
    cout << "NumVerticles" << gdp.getNumVertices() << endl;
    cout << "NumFace:" << gdp.getNumPrimitives() << endl;



    GA_RWHandleS strAttrib(&gdp,GA_ATTRIB_PRIMITIVE, "mystr");
    if(!strAttrib.isValid()){
        cout << "Can not find primtive attribute\n";
        return 1;
    }
    for(GA_Iterator iter(gdp.getPrimitiveRange()); !iter.atEnd(); ++iter){
        GA_Offset offset = *iter;
        UT_String value(strAttrib.get(offset) );
        value.append("_CPP");
        UT_StringHolder holder(value.c_str());
        strAttrib.set(offset, holder);
        cout << value <<endl;
    }



    // save to disk
    GA_SaveOptions saveOptions;
    gdp.save("change.bgeo",&saveOptions);





    cin.get();
    return 0;

}
View Code

遍历器所有属性,但是始终需要GA_Offset来引导获得真正的属性值:祭出我以前把H17.5的GU_Detail发送给Katana3.2,这样katana可以读取houdini的bgeo

// Copyright (c) 2016 The Foundry Visionmongers, Ltd.
#include <FnGeolib/op/FnGeolibOp.h>
#include <FnAttribute/FnAttribute.h>
#include <GU/GU_Detail.h>
#include <iostream>
#include <FnGeolibServices/FnGeolibCookInterfaceUtilsService.h>
using namespace std;
namespace
{
// "Hello World"-style op that sets a string attribute at the root location.
    class HelloWorldOp : public Foundry::Katana::GeolibOp
    {
    public:
        // Boilerplate that indicates the Op's cook() function is safe to be called
        // concurrently.
        static void setup(Foundry::Katana::GeolibSetupInterface& interface)
        {
            interface.setThreading(
                    Foundry::Katana::GeolibSetupInterface::ThreadModeConcurrent);
        }

        static void cook(Foundry::Katana::GeolibCookInterface& interface)
        {
            FnAttribute::StringAttribute celAttr = interface.getOpArg("CEL");
            if (!celAttr.isValid())
            {
                interface.stopChildTraversal();
                return;
            }
            FnGeolibServices::FnGeolibCookInterfaceUtils::MatchesCELInfo info;
            FnGeolibServices::FnGeolibCookInterfaceUtils::matchesCEL(info,
                interface,
                celAttr);

            if (!info.canMatchChildren)
            {
                interface.stopChildTraversal();
            }

            // If the CEL doesn't match the current location, stop cooking
            if (!info.matches)
            {
                return;
            }
            FnAttribute::StringAttribute bgeoFileAttr =
                interface.getOpArg("bgeoFile");
            if (!bgeoFileAttr.isValid()) {
                cout << "Can not find bgeoFile attribute in param\n";
                return;
            }
            string bgeoStr = bgeoFileAttr.getValue();

            interface.setAttr("type", FnAttribute::StringAttribute("pointcloud"));
            GU_Detail gdp;
            gdp.load(bgeoStr.c_str());
            uint64 numpt = gdp.getNumPoints();
            GA_Iterator iter(gdp.getPointRange());
            fpreal start_point_num = *iter;

            for (GA_AttributeDict::iterator it = gdp.getAttributeDict(GA_ATTRIB_POINT).begin(GA_SCOPE_PUBLIC); !it.atEnd(); ++it)
            {
                GA_Attribute *attrib = it.attrib();
                UT_String attribName (attrib->getName());
                int attSize = attrib->getTupleSize();
                GA_StorageClass storage = attrib->getStorageClass();
                cout << "loop attribute " << attribName << endl;
                if (attSize == 1) {
                    
                    if (storage == GA_STORECLASS_FLOAT) {
                        // FLOAT Attribute
                        float * floatValues = new float[numpt];
                        GA_RWHandleF handle(attrib);
                        for (uint64 i = start_point_num; i < numpt + start_point_num; i++) {    
                            uint64 KTNStride = i - start_point_num;
                            // set Houdini attribute for mem
                            floatValues[KTNStride] = handle.get(i);
                        }
                        // Attribute for arbitrary value
                        string katanaAttributeName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".value");
                        string scopeAttribName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".scope");


                        // Set the scope attribute
                        interface.setAttr(scopeAttribName.c_str(), FnAttribute::StringAttribute("point"), false);

                        // create KATANA attribute for interface
                        FnAttribute::FloatAttribute KTNAttribute(floatValues, numpt, 1);

                        // create KATANA attribute for interface values
                        interface.setAttr(katanaAttributeName.c_str(), KTNAttribute, false);

                        // Release mem
                        delete []floatValues;
                    }

                    if (storage == GA_STORECLASS_INT) {
                        // INT Attribute
                        int * intValues = new int[numpt];
                        GA_RWHandleI handle(attrib);
                        for (uint64 i = start_point_num; i < numpt + start_point_num; i++) {
                            uint64 KTNStride = i - start_point_num;
                            // set Houdini attribute for mem
                            intValues[KTNStride] = handle.get(i);
                        }
                        // Attribute for arbitrary value
                        string katanaAttributeName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".value");
                        string scopeAttribName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".scope");

                        // Set the scope attribute
                        interface.setAttr(scopeAttribName.c_str(), FnAttribute::StringAttribute("point"), false);

                        // create KATANA attribute for interface values
                        FnAttribute::IntAttribute KTNAttribute(intValues, numpt, 1);
                        interface.setAttr(katanaAttributeName.c_str(), KTNAttribute, false);
                        // Release mem
                        delete[]intValues;
                    }
                    

                }
                else if (attSize == 3) {
                    cout << "Vector attribute:" << attribName << endl;

                    float * newPoints = new float[numpt * 3];
                    GA_RWHandleV3 handle(attrib); 
                    for (uint64 i = start_point_num; i < numpt + start_point_num; i++) {

                        float x = float(handle.get(i).x());
                        float y = float(handle.get(i).y());
                        float z = float(handle.get(i).z());
                        // KTN index
                        uint64 KTNStride = i - start_point_num;
                        uint64 xIndex = KTNStride * 3;
                        uint64 yIndex = KTNStride * 3 + 1;
                        uint64 zIndex = KTNStride * 3 + 2;

                        // set Houdini attribute for mem
                        newPoints[xIndex] = x;
                        newPoints[yIndex] = y;
                        newPoints[zIndex] = z;

                    }
                    string katanaAttributeName;
                    
                    if (attribName == "P" || attribName == "v") {
                        katanaAttributeName = string("geometry.point.") + string(attribName.c_str());
                        // create KATANA attribute for interface
                    }
                    else {
                        katanaAttributeName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".value");
                        // SCOPE NAME FOR arnold AI_UserData_RGB
                        string scopeAttribName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".scope");
                        string inputTypeAttribName = string("geometry.arbitrary.") + string(attribName.c_str()) + string(".inputType");
                        interface.setAttr(scopeAttribName.c_str(), FnAttribute::StringAttribute("point"), false);
                        interface.setAttr(inputTypeAttribName.c_str(), FnAttribute::StringAttribute("vector3"), false);
                    }


                    FnAttribute::FloatAttribute vectorAttribute(newPoints, numpt * 3, 3);
                    interface.setAttr(katanaAttributeName.c_str(), vectorAttribute, false);

                    // Release mem
                    delete[]newPoints;




                }
                else if (attSize == 4) {
                    
                }
                else {
                    cout << " do not support this the attribute:" << attribName << endl;;
                }

            }

        }
    };
    DEFINE_GEOLIBOP_PLUGIN(HelloWorldOp)
}  // namespace

void registerPlugins()
{
    REGISTER_PLUGIN(HelloWorldOp, "HelloWorld", 0, 1);
}
View Code

官网也说的清:

//Each GA_AttributeOwner has its own dictionary of attributes that can be searched or traversed independently. Aside from the public attributes, a dictionary can contain private and group attributes, so be careful about scope during traversal.

//For example, to traverse all the public primitive attributes in an undefined order:

for (GA_AttributeDict::iterator it = gdp->getAttributeDict(GA_ATTRIB_PRIMITIVE).begin(GA_SCOPE_PUBLIC); !it.atEnd(); it.advance())
{
    GA_Attribute *attrib = it.attrib();
    ...
}
//To traverse all the public primitive attributes in a well-defined (alpabetic) order:

for (GA_AttributeDict::ordered_iterator it = gdp->getAttributeDict(GA_ATTRIB_PRIMITIVE).obegin(GA_SCOPE_PUBLIC); !it.atEnd(); it.advance())
{
    GA_Attribute *attrib = it.attrib();
    ...
}

当然也可以使用 GA/GA_GBMacros.h 提供的宏函数:

GA_Attribute *Patt = gdp.findPointAttribute("P");
GA_RWHandleV3 Phandle(Patt);
GA_Offset ptoff;
GA_FOR_ALL_PTOFF(&gdp,ptoff){
    UT_Vector3 P = Phandle.get(ptoff);
    P.y()+=1.0f;
    Phandle.set(ptoff,P );
}

当然:Handle的构造也可以直接从gdp构造,不用GA_Attribute,假设你不想知道 属性的信息。

// Read only, from named attribute
GA_ROHandleV3       vel_h(const_gdp, GEO_POINT_DICT, "v");
// Read write, from a named attribute, but must be at least 2 floats
GA_RWHandleF        life_h(gdp, GEO_POINT_DICT, "life", 2);
// From an existing const GA_Attribute *
GA_ROHandleI        id_h(const_attribute);
// From a GA_AttributeRef, (common when interfacing with legacy code)
GA_RWAttributeRef   scale_gah(gdp->findFloatTuple(GEO_POINT_DICT, "pscale"));
GA_RWHandleF        scale_h(scale_gah.getAttribute());

3,并行访问设置属性

cmake_minimum_required(VERSION 3.5)

project(Triangle)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# OPENGL
find_package(OpenGL REQUIRED)
include_directories(${OpenGL_INCLUDE_DIRS})
link_directories(${OpenGL_LIBRARY_DIRS})
add_definitions(${OpenGL_DEFINITIONS})

if(NOT OPENGL_FOUND)
    message(ERROR " OPENGL not found!")
endif(NOT OPENGL_FOUND)

# GLEW
set(GLEW_HOME D:/plugin_dev/libs/glew-2.1.0)
include_directories(${GLEW_HOME}/include)
link_directories(${GLEW_HOME}/lib/Release/x64)

# GLFW
set(GLFW_HOME D:/plugin_dev/libs/glfw-3.3.1.bin.WIN64)
include_directories(${GLFW_HOME}/include/)
link_directories(${GLFW_HOME}/lib-vc2019)

# STB
include_directories(D:/plugin_dev/libs/stb)

# GLM
include_directories(D:/plugin_dev/libs/GLM_include)


# openmp
find_package(OpenMP)
if (OPENMP_FOUND)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
    set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}")
endif()



# ---------------- HOUDINI
if (MSVC)
    # Prevent Boost auto-linking.
    add_definitions(-DBOOST_ALL_NO_LIB )
    add_definitions(-D_SCL_SECURE_NO_WARNINGS
            -D_CRT_SECURE_NO_WARNINGS
            -D_WIN32
            -D_WINSOCK_DEPRECATED_NO_WARNINGS
            -D__x86_64__)

    # HOUDINI :
    add_definitions(-TP
            -Zc:forScope
            -DVERSION="18.0.348"
            -DI386
            -DWIN32
            -DSWAP_BITFIELDS

            -DWINVER=0x0501
            -DNOMINMAX
            -DSTRICT
            -DWIN32_LEAN_AND_MEAN
            -D_USE_MATH_DEFINES
            -D_CRT_SECURE_NO_DEPRECATE
            -D_CRT_NONSTDC_NO_DEPRECATE
            -D_SCL_SECURE_NO_WARNINGS
            -DSESI_LITTLE_ENDIAN
            -DHBOOST_ALL_NO_LIB
            -DEIGEN_MALLOC_ALREADY_ALIGNED=0
            -DFBX_ENABLED=1
            -DOPENCL_ENABLED=1
            -DOPENVDB_ENABLED=1
            -MD
            -EHsc
            -GR
            -DNEED_SPECIALIZATION_STORAGE
            -DAMD64
            -DSIZEOF_VOID_P=8)

endif()


set(HOUDINI_HOME "D:/Program Files/Side Effects Software/Houdini 18.0.348")
include_directories("${HOUDINI_HOME}/toolkit/include")
link_directories("${HOUDINI_HOME}/custom/houdini/dsolib")





# output excutable dir
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/build)


# SRC FILE
FILE(
    GLOB
    SRC
    *.cpp *.h
    )

add_executable(Triangle ${SRC})



target_link_libraries(Triangle
    PRIVATE
    libGA.lib
    libGU.lib
    libUT.lib
    libCE.lib
    libLM.lib
    libFS.lib
    libSYS.lib
    libGEO.lib

    )
CMakeLists With OMP

Add life attribute, then set value parallel:

1 >> 没有用GA_RWHandleF,因为我测试后是线程不安全。如果用GA_RWPageHandleF 将是线程安全。

 // or iterate using a GA_PageIterator - this gives contiguous blocks
    GA_Attribute *LifeAtt = gdp.addFloatTuple(GA_ATTRIB_POINT,GA_SCOPE_PUBLIC,"life",1);
    GA_RWPageHandleF Life_pageHandle(LifeAtt);
    GA_Offset block_start, block_end;
    for (GA_Iterator pageI(gdp.getPointRange()); pageI.blockAdvance(block_start, block_end); )
    {
        Life_pageHandle.setPage(block_start);
        
        #pragma omp parallel for
        for (int ptoff = block_start; ptoff < block_end; ++ptoff){
            Life_pageHandle.value(ptoff) = ptoff; // direct data access
        }
    }

上面的指示把每一个page里的点并行了,不是并行的page,page相当于TBB的block.我觉得这个方式可能会出问题。相当于block是串行,block里面的东西并行。

所以属性可以直接作为Page的默认参数,也可以直接从gdp获取:

GA_ROPageHandleV3   v_ph(gdp, GEO_POINT_DICT, "v");
GA_RWPageHandleV3   p_ph(gdp->getP());

 

2 >> 使用UTparallelFor()来制作并行处理,实际上是TBB那套。TBB这套必须分Block,每个block有多大。有多少个Block(每个block都是相互独立并行),在houdini我觉得对应Page id(每个Page都是相互独立并行)

图示:

做了个20* 20 * 20的立方体共:2168个点,每个block/page 的大小为1024,总共能分三块:

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <GA/GA_PageHandle.h>
#include <GA/GA_GBMacros.h>
#include <GA/GA_AttributeRefMap.h>
#include <UT/UT_ThreadedAlgorithm.h>
#include <UT/UT_ParallelUtil.h>
#include <GA/GA_PageIterator.h>
#include <GA/GA_Range.h>

#include <iostream>
#include <omp.h>

using namespace std;

struct MoveY{

    MoveY(const GA_RWAttributeRef &attRef):rwAttrRef(attRef){

    }

    void operator()(const GA_SplittableRange &r) const
    {
        GA_RWPageHandleV3 pageHandle(rwAttrRef.getAttribute()); // Use Page Handle to point attribute


        // Iterate over pages in the range
        for (GA_PageIterator pit = r.beginPages(); !pit.atEnd(); ++pit)
        {
            GA_Offset       start, end;
            // iterate over the elements in the page.
            for (GA_Iterator it(pit.begin()); it.blockAdvance(start, end); )
            {
                // Perform any per-page setup required, then
                pageHandle.setPage(start);
                cerr <<" --------------PAGE:" <<start <<"----------------------"<<endl;
                for (GA_Offset i = start; i < end; ++i)
                {
                    UT_Vector3  P = pageHandle.get(i);
                    P.y()+=5;
                    pageHandle.set(i, P);
                }
            }
        } // page iter
    }

    GA_RWAttributeRef rwAttrRef;

};

void
DoMove(const GA_Range &range, const GA_RWAttributeRef &attRef)
{
    // Create a GA_SplittableRange from the original range
    UTparallelFor(GA_SplittableRange(range), MoveY(attRef));
}




int main(){
    GU_Detail gdp;
    gdp.load("geos/box.bgeo");


    GA_RWAttributeRef attRef(gdp.findPointAttribute("P"));
    GA_Range range = gdp.getPointRange();


    if(!attRef.isValid())
        cout << "can not change P\n";
    else{
        DoMove(range,attRef);
    }

    // save to disk
    GA_SaveOptions saveOptions;
    gdp.save("geos/change.bgeo.sc",&saveOptions);



    cout << "ret end\n";
    cin.get();
    return 0;

}
View Code

从返回结果看是没问题的。每个块独立。

 

3>>还有一种方案,只不过对GA_Offset稍微麻烦点,如果单纯的bgeo直接操作属性,不用管这个事情

这里还有一个问题是page.setPage()不知道性能消耗大不,我将每个offset 对到 page上:

class MoveY2 {
public:
    MoveY2(GA_Attribute  *att) : attrib(att) {}

    void operator()(const UT_BlockedRange<int64> &range) const
    {
        GA_RWPageHandleV3  myPageHandle(attrib);
        for (int64 i = range.begin(); i != range.end(); ++i)
        {
            myPageHandle.setPage(i);
            UT_Vector3 &value = myPageHandle.value(i);
            value.y()+= 5.0f;
        }
    }
    GA_Attribute *attrib;

};

void
DoMove2(GA_Attribute *attrib, int64 length)
{
    UTparallelFor(UT_BlockedRange<int64>(0, length), MoveY2(attrib));
}
View Code

C++11 Thread构建块我也做过,根据线程数目分块

 

 

 

 

 

4, add attribute

1,GA_Attribute&GA_RWHandleF,GA_RWHandleV3,  Basis add point number to the age attribute and for normal <0,1,0>

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <iostream>


using namespace std;


int main(){
    GU_Detail gdp;
    gdp.load("geos/box.bgeo");

    // add float attribute
    GA_Attribute *ageAttribute = gdp.addFloatTuple(GA_ATTRIB_POINT,GA_SCOPE_PUBLIC,"age",1);
    GA_RWHandleF ageHandle(ageAttribute);
    for(GA_Iterator it(gdp.getPointRange()) ; !it.atEnd(); it.advance()) {
        GA_Offset offset = *it;
        ageHandle.set(offset,*it);
    }


    // add vector N attribute
    GA_Attribute *normalAttribute = gdp.addFloatTuple(GA_ATTRIB_POINT, GA_SCOPE_PUBLIC, "N", 3);
    GA_RWHandleV3 NHandle(normalAttribute);
    if (!NHandle.isValid() ) {
        cout << "can not change N attribute\n";
        return 0;
    }
    for(GA_Iterator it(gdp.getPointRange()) ; !it.atEnd(); it.advance()) {
        GA_Offset offset = *it;
        NHandle.set(offset,UT_Vector3(0.f,1.0f,0.0f));
    }


    // save to disk
    GA_SaveOptions saveOptions;
    gdp.save("geos/change.bgeo",&saveOptions);




    cout << "ret end\n";
    cin.get();
    return 0;

}
View Code

GU_Detail的添加属性方法重载比较多,最常用的添加public属性:

GA_Attribute *att = gdp.addFloatTuple(GA_ATTRIB_POINT,"attname",3);                  // float vector attribute
GA_Attribute *att = gdp.addFloatTuple(GA_ATTRIB_POINT,GA_SCOPE_PUBLIC, "attname",3); // float vector attribute

 

5,选择一部分属性,执行线性插值:

GA_AttributeRefMap

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <GA/GA_PageHandle.h>
#include <GA/GA_GBMacros.h>
#include <GA/GA_AttributeRefMap.h>
#include <iostream>
#include <omp.h>

using namespace std;


int main(){
    GU_Detail gdp;
    gdp.load("geos/line.bgeo");

    GA_Iterator iter(gdp.getPointRange()) ;
    GA_Offset pt0 = *iter;
    GA_Offset pt1 = pt0 + 1;

    GA_Offset new_pt = gdp.appendPoint();
    GA_AttributeRefMap  hmap(gdp);
    // Append all point & vertex attributes (including "P")
    hmap.append(GA_AttributeFilter::selectNumeric(), GA_ATTRIB_POINT);

    // Perform linear interpolation, writing to new_vtx
    hmap.lerpValue(GA_ATTRIB_POINT, new_pt, GA_ATTRIB_POINT, pt0, pt1 , .5);

    // save to disk
    GA_SaveOptions saveOptions;
    gdp.save("geos/change.bgeo.sc",&saveOptions);

    cout << "ret end\n";
    cin.get();
    return 0;

}
View Code

中间生成的点,把所有的点属性都插值,包括P,Cd。这里按照0.5的bias

 

6, Read the binary .Bgeo. from python

try:
    # Try for ASCII/binary support
    import hjson
    json = hjson
except:
    # Fall back to only ASCII support
    import simplejson
    json = simplejson

fileName = "D:/line.bgeo"
geo = json.load(open(fileName, 'rb'))
print json.dumps(geo, binary=False, indent=4)

剩下的可以按照geo[]来取值。hjson文档说是python的高性能使用方法

 

7,Eliminating GEO_Point,Do Not USE GEO_Point:

The GA library doesn't store point (GEO_Point) or vertex (GEO_Vertex) objects,然而你依然可以获取GB方式的GEO_Point:

GEO_Point   *ppt = gdp->getGBPoint();

Rather than using GEO_Point objects, try to use the GA_Offset of the point. 访问GEO_Point属于间接方式,不是直接方式。GA Keep memory usage lower (no persistent objects)

 

8,Create Geometry

colsed polygon

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <GA/GA_PageHandle.h>
#include <GA/GA_GBMacros.h>
#include <GA/GA_AttributeRefMap.h>
#include <UT/UT_ThreadedAlgorithm.h>
#include <UT/UT_ParallelUtil.h>
#include <GA/GA_PageIterator.h>
#include <GA/GA_Range.h>

#include <iostream>
#include <omp.h>

using namespace std;





const int npoints = 3;


int main(){
    GU_Detail gdp;
    //gdp.load("geos/box.bgeo");

    gdp.clearAndDestroy();
    GA_Offset start_vtxoff;
    GA_Offset start_ptoff ;

    // @arg1 = GA_PRIMPOLY
    // @arg2 = nprimitives
    // @arg3 = nvertices_each
    // @arg4 = vertex_block_start
    // @arg5 = close polygon
    gdp.appendPrimitivesAndVertices(GA_PRIMPOLY, 1, npoints, start_vtxoff, true);

    // Create the right number of points, as a contiguous block
    start_ptoff = gdp.appendPointBlock(npoints);
    // Wire the vertices to the points.
    for (exint i = 0; i < npoints; ++i)
    {
        gdp.getTopology().wireVertexPoint(start_vtxoff+i,start_ptoff+i);
    }


    // We added points, vertices, and primitives,
    // so this will bump all topology attribute data IDs,
    // P's data ID, and the primitive list data ID.
    gdp.bumpDataIdsForAddOrRemove(true, true, true);


    UT_Vector3 Ps[3] = {
        UT_Vector3(-1,0,0),
        UT_Vector3(1,0,0),
        UT_Vector3(0,1,0) };


    for(int i =0; i< npoints;i++){
        GA_Offset offset = i+ start_ptoff;
        gdp.setPos3(offset, Ps[i]);
    }


    // save to disk
    GA_SaveOptions saveOptions;
    gdp.save("geos/change.bgeo.sc",&saveOptions);



    cout << "ret end\n";
    cin.get();
    return 0;

}
View Code

 

9:TBN Matrix

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <GA/GA_PageHandle.h>
#include <GA/GA_GBMacros.h>
#include <GA/GA_AttributeRefMap.h>
#include <UT/UT_ThreadedAlgorithm.h>
#include <UT/UT_ParallelUtil.h>
#include <GA/GA_PageIterator.h>
#include <GA/GA_Range.h>
#include <GU/GU_DetailHandle.h>
#include <GU/GU_PackedGeometry.h>
#include <GU/GU_PrimPacked.h>
#include <GU/GU_PolyFrame.h>


#include <iostream>
#include <omp.h>

using namespace std;



int main(){

    UT_Options option;
    GU_Detail *gdp = new GU_Detail;

    GU_Detail::IOStatus stat = gdp->load("geos/grid.bgeo");
    if(! stat.success() ){
        cout << "load file error\n";
    }

    cout << gdp->getNumPoints() << endl;

    GU_PolyFrame polyframe(gdp);
    GU_PolyFrameParms polyframeParms;
    polyframeParms.style = GU_POLYFRAME_TEXTURE;
    polyframeParms.left_handed = false;
    polyframeParms.orthogonal = true;
    polyframeParms.which = GU_POLYFRAME_NORMAL | GU_POLYFRAME_BITANGENT | GU_POLYFRAME_TANGENT ;
    polyframeParms.uv_name = "uv";
    polyframeParms.names[0] = "T";
    polyframeParms.names[1] = "B";
    polyframeParms.names[2] = "N";
    polyframe.computeFrames(polyframeParms);
    
    GA_SaveOptions save_option;
    gdp->save("geos/grid_pf.bgeo",&save_option);


    delete gdp;
    cin.get();
    return 0;

}
View Code

 

10:GU_PrimPacked Packed GEOMETRY:

操作pack首选GU_PrimPacked,从类关系看应该是最全的。

REF:tookit->samples->SOP_CopyPacked.C

 

#include <GU/GU_Detail.h>
#include <GEO/GEO_Primitive.h>
#include <GEO/GEO_PrimPoly.h>
#include <GA/GA_Primitive.h>
#include <GA/GA_Iterator.h>
#include <GA/GA_SaveOptions.h>
#include <GEO/GEO_AttributeHandle.h>
#include <GA/GA_PageHandle.h>
#include <GA/GA_GBMacros.h>
#include <GA/GA_AttributeRefMap.h>
#include <UT/UT_ThreadedAlgorithm.h>
#include <UT/UT_ParallelUtil.h>
#include <GA/GA_PageIterator.h>
#include <GA/GA_Range.h>
#include <GU/GU_DetailHandle.h>
#include <GU/GU_PackedGeometry.h>
#include <GU/GU_PrimPacked.h>
#include <GU/GU_PolyFrame.h>
#include <GA/GA_LoadOptions.h>

#include <iostream>
#include <omp.h>

using namespace std;



int main(){

    GA_LoadOptions load_option;
    GU_Detail *gdp = new GU_Detail;
    gdp->loadIODSOs(); // make sure can load packed geo


    GU_Detail::IOStatus stat = gdp->load("geos/packed.bgeo",&load_option);
    if(! stat.success() ){
        cout << "load file error\n";
    }

    cout << "static method->Has packed prim:"<<GU_PrimPacked::hasPackedPrimitives(*gdp) << endl;
    cout << "static method->Has packed num of prim:" << GU_PrimPacked::countPackedPrimitives(*gdp) << endl;
    cout << "Num points:"<<gdp->getNumPoints() << endl;
    cout << "Num Prims:"<<gdp->getNumPrimitives() << endl;


    GA_RWHandleS pathAttribHandle(gdp,GA_ATTRIB_PRIMITIVE,"path");
    for(GA_Iterator it(gdp->getPrimitiveRange()); !it.atEnd(); it.advance()){
        GA_Primitive *prim = gdp->getPrimitive(*it);
        GU_PrimPacked *pack_prim = static_cast<GU_PrimPacked*>(prim);

        cout << pathAttribHandle.get(*it) << endl;

    }



    //GA_SaveOptions save_option;
    //gdp->save("geos/grid_pf.bgeo",&save_option);


    delete gdp;
    cin.get();
    return 0;

}
View Code

 

 11, NOT TESTED

 https://www.sidefx.com/docs/hdk/class_g_a___attribute_ref_map.html

// Compute the average value of the P attribute and store in a
// global attribute "averageP".
GA_WeightedSum              sum;
GA_AttributeRefMap          map(gdp);
GA_AttributeRefMap::Handle  gah(map);
int                         npts;
map.append( detail.findGlobalAttribute("averageP"),
            detail.findPointAttribute("P") );
gah.setGlobal();    // Write to global attributes
gah.startSum(sum);
for (GA_Iterator it = gdp.getPointRange(); !it.atEnd(); ++it)
    gah.sumPoint(sum, it.getOffset(), 1);
npts = gdp.getNumPoints();
gah.finishSum(sum, npts ? 1./npts : 0);

 

 

 

REF:https://www.sidefx.com/docs/hdk/index.html

GA User Guide:https://www.sidefx.com/docs/hdk/_h_d_k__g_a__using.html#HDK_GA_Using_GEO_Point 讲解的非常详细GA/GB的各种操作

GA Porting Guide:https://www.sidefx.com/docs/hdk/_h_d_k__g_a__porting.html#HDK_GA_PortingCookbook_Simple_Name_Translation 各种GA的案例,必须删除点,删除未使用面....

posted on 2020-04-30 14:32  gearslogy  阅读(996)  评论(2编辑  收藏  举报