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.
Found 9 posts.
Search results Show results as topic list.
Technical Discussion » Increase resolution of a field in DOP
- Kostra
- 9 posts
- Offline
HOULY Daily Challenge » Day 9 | Motion: Growth
- Kostra
- 9 posts
- Offline
Technical Discussion » HDK: How to use GA_BlobData?
- Kostra
- 9 posts
- Offline
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
The result should be:
Not sure about the lifetime of attachments here, but I'm frustrated when they disappear. Thus the code in plain text
BlobDataTest.h
BlobDataTest.cpp
CMakeLists.txt
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
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 )
Technical Discussion » HDK: How to use GA_BlobData?
- Kostra
- 9 posts
- Offline
I would like to create a custom attribute with HDK. There is `GA_BlobData` for this purpose as explained in the documentation [www.sidefx.com]. I have basically copy&pasted the code in the linked part of documentation, but the code keeps crashing
The code is not complete as it is, GA_BlobData requires also implementation of `getMemoryUsage` and `countMemory`
I not really sure what the implementation should be, I just return `sizeof(*this) + myString.getMemoryUsage()` for the first and do nothing for the second one i.e. `{}`.
How to use `GA_BlobData` properly? Is there a full working example?
Related question(not very usefull) [www.sidefx.com]
Crash report:
The code is not complete as it is, GA_BlobData requires also implementation of `getMemoryUsage` and `countMemory`
virtual int64 getMemoryUsage (bool inclusive) const =0 virtual void countMemory (UT_MemoryCounter &counter, bool inclusive) const =0
How to use `GA_BlobData` properly? Is there a full working example?
Related question(not very usefull) [www.sidefx.com]
Crash report:
Crash report from tskrivan; Houdini FX Version 17.0.352 [linux-x86_64-gcc6.3] Uptime 111 seconds Wed Aug 21 19:47:02 2019 Caught signal 11 Traceback from 7572 ThreadId=0x7f4a2a356cc0 AP_Interface::coreDumpChaser(UTsignalHandlerArg) <libHoudiniUI.so> AP_Interface::si_CrashHandler::chaser(UTsignalHandlerArg) <libHoudiniUI.so> signalCallback(UTsignalHandlerArg) <libHoudiniUT.so> UT_Signal::UT_ComboSignalHandler::operator()(int, siginfo_t*, void*) const <libHoudiniUT.so> UT_Signal::processSignal(int, siginfo_t*, void*) <libHoudiniUT.so> __funlockfile <libpthread.so.0> GA_BlobContainer::getMemoryUsage(bool) const <libHoudiniGEO.so> GA_ATIBlob::getMemoryUsage(bool) const <libHoudiniGEO.so> GA_AttributeProxy::getMemoryUsage(bool) const <libHoudiniGEO.so> GA_AttributeSet::getMemoryUsage(bool) const <libHoudiniGEO.so> GA_Detail::getMemoryUsage(bool) const <libHoudiniGEO.so> GEO_Detail::getMemoryUsage(bool) const <libHoudiniGEO.so> GU_Detail::getMemoryUsage(bool) const <libHoudiniGEO.so> SOP_Node::getLoadedMemoryUsage() const <libHoudiniOP2.so> SOP_CacheManager::alertCookEndSOP(SOP_Node*) <libHoudiniOP2.so> SOP_Node::cookMe(OP_Context&) <libHoudiniOP2.so> OP_Node::cook(OP_Context&)::{lambda()#1}::operator()() const <libHoudiniPRM.so> OP_Node::cook(OP_Context&) <libHoudiniPRM.so> OP_Node::internalCookInput(OP_Context&, int, OP_Node&) <libHoudiniPRM.so> OP_Node::lockInput(unsigned int, OP_Context&) <libHoudiniPRM.so> SOP_Node::lockInput(unsigned int, OP_Context&) <libHoudiniOP2.so> SOP_Output::cookMySop(OP_Context&) <libHoudiniOP2.so> SOP_Node::cookMe(OP_Context&) <libHoudiniOP2.so> OP_Node::cook(OP_Context&)::{lambda()#1}::operator()() const <libHoudiniPRM.so> OP_Node::cook(OP_Context&) <libHoudiniPRM.so> SOP_Node::getCookedGeoHandle(OP_Context&, int)::{lambda()#1}::operator()() const <libHoudiniOP2.so> SOP_Node::getCookedGeoHandle(OP_Context&, int) <libHoudiniOP2.so> SOP_SubNet::cookMySop(OP_Context&) <libHoudiniOP2.so> SOP_Node::cookMe(OP_Context&) <libHoudiniOP2.so> OP_Node::cook(OP_Context&)::{lambda()#1}::operator()() const <libHoudiniPRM.so> OP_Node::cook(OP_Context&) <libHoudiniPRM.so> SOP_Node::getCookedGeoHandle(OP_Context&, int)::{lambda()#1}::operator()() const <libHoudiniOP2.so> SOP_Node::getCookedGeoHandle(OP_Context&, int) <libHoudiniOP2.so> OBJ_Node::getDisplayGeometryHandle(OP_Context&, int, OP_Node**) <libHoudiniOP3.so> JEDI_View::opuiUpdateNodeInfo(OH_NodeInfo*) <libHoudiniAPPS3.so> OH_OpHandler::opuiUpdateData() <libHoudiniUI.so> OP3D_View::doUpdate() <libHoudiniAPPS3.so> tbb::interface7::internal::task_arena_base::internal_execute(tbb::interface7::internal::delegate_base&) const (arena.cpp:899) TBBPROXY_TaskArenaExecute <libTBBPROXY.so> JEDI_View::opuiUpdateData() <libHoudiniAPPS3.so> OH_OpHandler::trigger() <libHoudiniUI.so> UI_Queue::processNextEvent() <libHoudiniUI.so> UI_Queue::drain() <libHoudiniUI.so> UI_Queue::eventLoop() <libHoudiniUI.so> main <libHoudiniUI.so> __libc_start_main (libc-start.c:291) main <houdini-bin>
Work in Progress » C++ Wrangle Node
- Kostra
- 9 posts
- Offline
Hey,
I have created C++ Wrangle Node, it is based on animatrix's C++ Wrangle SOP [vimeo.com]. You can download it from its github page [github.com].
I took it a step further and tried to make the use of C++ as close to VEX as possible. Therefore, you do not need to be familiar with HDK and still write C++ code inside of Houdini. Of course, I have not implemented all VEX functions, I'm adding them along the way as I need them for my work. However, it is usually very easy, you just have to look up appropriate HDK function and wrap it in VEX like function.
I also provide functions to load and save mesh attributes as Eigen matrices, such that you can easily do some linear algebra operations on them.
Last but not least, there are also some basic finite element operations for triangular meshes, like computing mass and stiffness matrices. In the example scene, you can find how to use these to compute minimal surface or geodesic distance using the heat method [www.cs.cmu.edu].
The whole thing is quite experimental and will probably change a lot in the future. Thus, I do not really want to write some extensive documentation which will become obsolete anyway. Hopefully the provided examples are enough to get you started. If something is unclear, just ask here or file and issue on github.
Any feedback is welcome and I hope you will find it useful!
I have created C++ Wrangle Node, it is based on animatrix's C++ Wrangle SOP [vimeo.com]. You can download it from its github page [github.com].
I took it a step further and tried to make the use of C++ as close to VEX as possible. Therefore, you do not need to be familiar with HDK and still write C++ code inside of Houdini. Of course, I have not implemented all VEX functions, I'm adding them along the way as I need them for my work. However, it is usually very easy, you just have to look up appropriate HDK function and wrap it in VEX like function.
I also provide functions to load and save mesh attributes as Eigen matrices, such that you can easily do some linear algebra operations on them.
Last but not least, there are also some basic finite element operations for triangular meshes, like computing mass and stiffness matrices. In the example scene, you can find how to use these to compute minimal surface or geodesic distance using the heat method [www.cs.cmu.edu].
The whole thing is quite experimental and will probably change a lot in the future. Thus, I do not really want to write some extensive documentation which will become obsolete anyway. Hopefully the provided examples are enough to get you started. If something is unclear, just ask here or file and issue on github.
Any feedback is welcome and I hope you will find it useful!
Technical Discussion » Matrix multiplication confusion
- Kostra
- 9 posts
- Offline
I really want to multiply matrix by a vector from the right side, e.g. multiply a matrix 2x2 by a column vector 2x1. If I understand it correctly, Houdini considers vectors as row vectors, e.g. 1x2, thus I should transpose the vector to convert it to a column vector, e.g. 2x1. However, calling the function `transpose` gives and error that a matrix is expected as an input.
This is really stupid…
This is really stupid…
Technical Discussion » Matrix multiplication confusion
- Kostra
- 9 posts
- Offline
I'm little bit confused with matrix multiplication, I think I understand what is going on but I would like to double check.
Consider following two matrices and a vector
The source of all problems is that is does not matter if I multiply a matrix by a vector from right or left, i.e.
It always gives answer as if I multiply the matrix from the left. Thus vex code `A*v` is equivalent to mathematical `transpose(v)*A`. However, multiplication between matrices works fine and there is a difference between `A*B` and `B*A`.
This leads to an absurd fact that multiplication is not associative, i.e.
If I always keep vector on the left side then there is no problem, i.e.
Do I understand the problem fully or is there an additional catch? Am I safe if I always multiply matrices by a vector from the left side?
Consider following two matrices and a vector
matrix2 A = {{1,1}, {-1,1}}; matrix2 B = {{1,2}, { 0,1}}; vector2 v = {1,0};
The source of all problems is that is does not matter if I multiply a matrix by a vector from right or left, i.e.
A*v == v*A
This leads to an absurd fact that multiplication is not associative, i.e.
A*B*v == (A*B)*v != A*(B*v)
If I always keep vector on the left side then there is no problem, i.e.
v*A*B == (v*A)*B == v*(A*B)
Do I understand the problem fully or is there an additional catch? Am I safe if I always multiply matrices by a vector from the left side?
Technical Discussion » Problem with using PolyFrame output in PointWrangle
- Kostra
- 9 posts
- Offline
So I have to specify a type of variable when I want to use it? Wow, I have never seen that in any other programming language and I find it pretty stupid.
Anyway, thanks a lot!
Anyway, thanks a lot!
Technical Discussion » Problem with using PolyFrame output in PointWrangle
- Kostra
- 9 posts
- Offline
I'm experiencing different behavior of Point Wrangle and Point VOP when they should be doing the same thing. In particular, I create a curve and using PolyFrame I create its tangent vector. Then I want to move each point of the curve by its tangent vector, when I do this with Point VOP it works as expected but when using Point Wrangle I get some garbage.
I have attached an example scene and I'm using Houdini Apprentice 16.5.439
I have attached an example scene and I'm using Houdini Apprentice 16.5.439
-
- Quick Links