[SESI logo]

Houdini Development Toolkit - Version 6.5

Side Effects Software Inc. 2004

Geometry

Loading and Saving Geometry

Loading and saving of geometry is really quite simple. There are four methods in GEO/GEO_Detail.h which will load and save geometry in any supported format.
  • load(const char *filename, int binary=0)
  • load(istream &is, int binary=0)
  • save(const char *filename, int binary=0)
  • save(istream &is, int binary=0)
  • When loading geometry, both methods will try to determine the file type of the load and load using the correct format. When the loader is passed a filename, it attempts to resolve the format by looking at the file extension. If the format doesn't map to any known extensions, a load using .geo or .bgeo format is attempted. Only if this fails, will the load itself fail.

    When saving, the filename extension is also used to determine the format to save to. In the case where the geometry library is only given a stream to save to, it will save in either ASCII or binary format (depending on the binary flag).

    All these methods return 0 on success and -1 on failure.


    Format Conversion

    There are two methods supported by the geometry library for file format conversion. Internal formats are compiled into the library (there is currently no mechanism for extending these through DSO support). External converters are stand alone programs which read or write a different format as well as reading/writing .geo or .bgeo files. These external programs are stored in an ASCII table called the GEOio file.

    Internal formats conversions use a class called GEO_IOTranslator. This simply specifies a method for identifying the format (for loading) and save/load methods. There are currently two internal formats PRISMS (.bpoly, .poly and .d files) and RIB (.rib files). It is possible to access these file converters from within code fragments. For example, the following two fragments perform the same function:

    // listing 1 GEO_Detail *gdp; gdp->save("/tmp/foo.rib"); // listing 2 GEO_Detail *gdp; GEO_IORib rib_output; ofstream os("/tmp/foo.rib"); rib_output.save(gdp, os); os.flush(); Now, the question arises why you would need to use the method in listing 2. However, there are some things you can do with the direct translator that you cannot do with the internal save mechanism.
    1. If you already have a stream which you've been passed, it is impossible to specify the format using GEO_Detail::save.
    2. There may be additional controls in the translator which are not accessible through the GEO_Detail::save method.
    For example, in the current RIB output, there are some methods which can be called before the file save to determine how it deals with outputting geometry:
    Method Description
    setMBGeo This method sets geometry which is used to output deformation motion blur information. If the topologies of the two geometries don't match, then motion blur information will not be output. For example: GEO_Detail *frame1, *frame2; GEO_IORib xlate; xlate.setMBGeo(frame1); xlate.save(frame2, cout);
    setMBParticle Specifies whether particle geometry should be output as motion blurred or not.
    setParticleId If the id passed in is greater than 0, then instead of outputting particle geometry, the RIB output will output an instance statement, instancing the id specified.
    setParticleGeometry In some cases, the geometry for particle instancing is invalid for RIB instancing (i.e. it contains transformed spheres or trim curves). In this case, you can specify a separate gdp which will get output at each particle for replication.


    External Conversion using GEOio

    The GEOio table allows the extension of the geometry load/save formats by specifying a stand alone application which can convert between Houdini format and the new format. The format of the GEOio table is really quite straight-forward. The extension for the format is specified, then a program to read the external format, then a program to save to the external format.

    Here is an example program which saves simple wavefront data... However, it only saves vertex position information, not normals or texture coordinates. It also only saves out polygons.

    #include <stdlib.h> #include <fstream.h> #include <UT/UT_Vector4.h> #include <GU/GU_Detail.h> static void usage() { cerr << "Usage: wavesave savefile.obj\n"; cerr << "This program reads a .geo/.bgeo file on stdin and\n"; cerr << "creates a .obj file as output" << endl; exit(1); } static void saveWave(const GU_Detail &gdp, ostream &os) { int i, j; const UT_Vector4 *pos; const GEO_Primitive *prim; // // First, we save out all our point positions // os << "g\n"; for (i = 0; i < gdp.points().entries(); i++) { pos = &gdp.points()(i)->getPos(); os << "v " << pos->x() << " " << pos->y() << " " << pos->z() << endl; } // // Now, we save out all the polygon data os << "g\n"; for (i = 0; i < gdp.primitives().entries(); i++) { prim = gdp.primitives()(i); if (prim->getPrimitiveId() != GEOPRIMPOLY) continue; os << "f"; for (j = 0; j < prim->getVertexCount(); j++) os << " " << prim->getVertex(j).getPt()->getNum()+1; os << endl; } } int main(int argc, char *argv[]) { GU_Detail gdp; if (argc < 2) usage(); if (gdp.load(cin) < 0) cerr << "Unable to load input geometry" << endl; else { ofstream os(argv[1]); saveWave(gdp, os); } return 0; } The corresponding entry in the GEOio table would look something like this:
    .obj "" "wavesave %s" Since wavesave doesn't load .obj files, we simply leave that entry in the table blank. The %s will get replaced with the actual filename on a save. For example, if someone now saved a geometry file to "foo.obj" from the modeller, the wavesave program would be called to save the geometry out.
    Table of Contents
    Operators | Surface Operations | Particle Operations | Composite Operators | Channel Operators
    Material & Texture | Objects | Command and Expression | Render Output |
    Mantra Shaders | Utility Classes | Geometry Library | Image Library | Clip Library
    Customizing UI | Questions & Answers

    Copyright © 2004 Side Effects Software Inc.
    477 Richmond Street West, Toronto, Ontario, Canada M5V 3E7