Kostra

Kostra

About Me

Connect

LOCATION
Not Specified
WEBSITE

Houdini Skills

Availability

Not Specified

Recent Forum Posts

Increase resolution of a field in DOP Aug. 2, 2020, 2:18 p.m.

Is there an easy way to increase resolution of a field in DOP? Example: I have `surface` field with resolution and I would like to increase it to while keeping field's size and position.

I expected that `Gas Resize Field` would be able to do this, but I have not figured how.

Day 9 | Motion: Growth July 9, 2020, 5:57 p.m.

My crystal growth solver.

HDK: How to use GA_BlobData? Aug. 23, 2019, 10:07 a.m.

I do not know what I was doing wrong. It works for me now.

For the future lost souls I'm including a working node with a simple test scene. Download & extract the attached archive somewhere and run the following commands

export CC=gcc-6 
export CXX=g++-6
mkdir build
pushd build
cmake .. -DHOUDINI_ROOT=/opt/hfs17.5/
make -j
popd
./test.py
The result should be:
Stored a string to a blob: "Hello World!"
Finished cooking!
Retrieved a string form a blob: "Hello World!"
Finished cooking!

Not sure about the lifetime of attachments here, but I'm frustrated when they disappear. Thus the code in plain text

BlobDataTest.h
#pragma once

#include <SOP/SOP_Node.h>
#include <UT/UT_MemoryCounter.h>

///////////////// String Blob //////////////////////////////

class StringBlob : public GA_BlobData {
public:
  StringBlob();
  StringBlob(const char *str);
  virtual ~StringBlob();

  virtual uint hash() const;
  virtual bool isEqual(const GA_BlobData &blob) const;

  virtual int64 getMemoryUsage(bool inclusive) const;
  virtual void  countMemory(UT_MemoryCounter &counter, bool inclusive) const;

public:
  UT_String myString;
};

///////////////// String Blob Test Node //////////////////////////////

class SOP_BlobDataTest : public SOP_Node {
public:
  SOP_BlobDataTest(OP_Network *net, const char *name, OP_Operator *op);
  virtual ~SOP_BlobDataTest();

  static PRM_Template myTemplateList[];
  static OP_Node *    myConstructor(OP_Network *, const char *, OP_Operator *);

protected:
  /// Method to cook geometry for the SOP
  virtual OP_ERROR cookMySop(OP_Context &context);

private:
};

BlobDataTest.cpp
#include <iostream>
#include <string>

#include <GA/GA_AIFBlob.h>
#include <GU/GU_Detail.h>
#include <OP/OP_AutoLockInputs.h>
#include <OP/OP_Director.h>
#include <OP/OP_Operator.h>
#include <OP/OP_OperatorTable.h>
#include <PRM/PRM_Include.h>
#include <UT/UT_DSOVersion.h>

#include "BlobDataTest.h"

///////////////// String Blob //////////////////////////////

StringBlob::StringBlob() : myString() {}

StringBlob::StringBlob(const char *str)
    : myString(UT_String::ALWAYS_DEEP, str) {}

StringBlob::~StringBlob() {}

// Implementation of methods on GA_Blob
uint StringBlob::hash() const { return myString.hash(); }

bool StringBlob::isEqual(const GA_BlobData &blob) const {
  const StringBlob *s;
  s = dynamic_cast<const StringBlob *>(&blob);
  return s && (s->myString == myString);
}

int64 StringBlob::getMemoryUsage(bool inclusive) const {
  int64 mem = inclusive ? sizeof(*this) : 0;
  mem += myString.getMemoryUsage();
  return mem;
}

void StringBlob::countMemory(UT_MemoryCounter &counter, bool inclusive) const {
  if (counter.mustCountUnshared()) {
    counter.countUnshared(getMemoryUsage(inclusive));
  }
}

///////////////// String Blob Test Node ////////////////////////

void newSopOperator(OP_OperatorTable *table) {
  table->addOperator(new OP_Operator(
      "blob_data_test_node", "Blob Data Test Node",
      SOP_BlobDataTest::myConstructor, SOP_BlobDataTest::myTemplateList, 0));
}


PRM_Template SOP_BlobDataTest::myTemplateList[] = {
    PRM_Template(),
};

OP_Node *SOP_BlobDataTest::myConstructor(OP_Network *net, const char *name,
                                         OP_Operator *op) {
  return new SOP_BlobDataTest(net, name, op);
}

SOP_BlobDataTest::SOP_BlobDataTest(OP_Network *net, const char *name,
                                   OP_Operator *op)
    : SOP_Node(net, name, op) {
  // Right now I'm assuming that anything can change
  // In fugure, I might bump data IDs base on which attribute handles were
  // created with `getattrib` function

  // mySopFlags.setManagesDataIDs(true);
}

SOP_BlobDataTest::~SOP_BlobDataTest() {}

OP_ERROR
SOP_BlobDataTest::cookMySop(OP_Context &context) {
  // We must lock our inputs before we try to access their geometry.
  // OP_AutoLockInputs will automatically unlock our inputs when we return.
  // NOTE: Don't call unlockInputs yourself when using this!
  OP_AutoLockInputs input_lock_guard(this);
  if (input_lock_guard.lock(context) >= UT_ERROR_ABORT)
    return error();

  // Duplicate incoming geometry
  duplicateSource(0, context);

  flags().setTimeDep(true);

  auto owner          = GA_ATTRIB_DETAIL;
  auto scope          = GA_SCOPE_PUBLIC;
  auto attribute_name = "blob_test";

  GA_RWAttributeRef blob_gah = gdp->findAttribute(owner, scope, attribute_name);

  // Set the blob if does not exists
  // Should be executed in the `test.hipnc/obj/geo1/set_blob` node
  if (!blob_gah) {

    // create attribute
    GA_RWAttributeRef blob_gah = gdp->createAttribute(
        owner, scope, attribute_name, nullptr, nullptr, "blob");

    // create blob
    GA_Attribute *    attr     = blob_gah.getAttribute();
    const GA_AIFBlob *aif      = attr->getAIFBlob();
    StringBlob *      blob_ptr = new StringBlob{"Hello World!"};

    // save blob
    aif->setBlob(attr, blob_ptr, 0);

    std::cout << "Stored a string to a blob: " << blob_ptr->myString
              << std::endl;

  } else {
    // Get the blob if it exists
    // Should be executed in the `test.hipnc/obj/geo1/get_blob` node

    // Retrieve the blob
    GA_Attribute *    attr = blob_gah.getAttribute();
    const GA_AIFBlob *aif  = attr->getAIFBlob();

    GA_BlobRef blob    = aif->getBlob(attr, 0);
    auto       strblob = dynamic_cast<const StringBlob *>(blob.get());

    std::cout << "Retrieved a string form a blob: " << strblob->myString
              << std::endl;
  }

  if (error() >= UT_ERROR_ABORT)
    return error();

  std::cout << "Finished cooking!" << std::endl;

  return error();
}

CMakeLists.txt
# Specify the minimum required version of CMake to build the project.
cmake_minimum_required( VERSION 3.6 )

set(CMAKE_PREFIX_PATH "${HOUDINI_ROOT}/toolkit")

### LIBRARIES ###
find_package(Houdini REQUIRED)
find_package(Eigen3 REQUIRED)

### EXECUTOR ###

# SOP
add_library(BlobDataTest SHARED BlobDataTest.cpp)
target_link_libraries(BlobDataTest Houdini)
houdini_configure_target( BlobDataTest )