Logo Search packages:      
Sourcecode: k3d version File versions

rib_reader.cpp

Go to the documentation of this file.
// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
            \brief Implements the RIBReader K-3D object, which reads RenderMan .rib files
            \author Romain Behar (romainbehar@yahoo.com)
*/

#include <k3dsdk/algebra.h>
#include <k3dsdk/classes.h>
#include <k3dsdk/color.h>
#include <k3dsdk/file_helpers.h>
#include <k3dsdk/idag.h>
#include <k3dsdk/ideletable.h>
#include <k3dsdk/idocument.h>
#include <k3dsdk/idocument_plugin_factory.h>
#include <k3dsdk/ifile_format.h>
#include <k3dsdk/igeometry_read_format.h>
#include <k3dsdk/imaterial.h>
#include <k3dsdk/imaterial_collection.h>
#include <k3dsdk/iobject.h>
#include <k3dsdk/iobject_collection.h>
#include <k3dsdk/irenderman.h>
#include <k3dsdk/itransform_sink.h>
#include <k3dsdk/itransform_source.h>
#include <k3dsdk/material.h>
#include <k3dsdk/mesh.h>
#include <k3dsdk/module.h>
#include <k3dsdk/plugins.h>
#include <k3dsdk/property.h>
#include <k3dsdk/result.h>
#include <k3dsdk/selection.h>
#include <k3dsdk/string_modifiers.h>
#include <k3dsdk/utility.h>
#include <k3dsdk/vectors.h>

#include "helpers.h"

#include <Hapy/Parser.h>
#include <Hapy/Rules.h>

#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/path.hpp>

#include <iostream>
#include <map>
#include <stack>

namespace libk3dgeometry
{

using namespace Hapy;

Rule rtint;
Rule rtfloat;
Rule rtstring;
Rule rtint_array;
Rule rtfloat_array;
Rule rtstring_array;

Rule rtpair;
Rule rtparameters;

Rule version;
Rule file;
Rule request_property;
Rule request_object;
Rule request;

Rule camera;
Rule frame;
Rule world;
Rule transform;
Rule attribute;
Rule solid;
Rule object;
Rule motion;
Rule shader;
Rule geometry;
Rule transformation;
Rule errors;
Rule textures;

Rule comment;
Rule comment_body;

static bool hapy_rib_parser = false;

void create_parser()
{
      if(hapy_rib_parser)
            return;

      hapy_rib_parser = true;

      rtint = !char_r('-') >> +digit_r;
      rtint.leaf(true);
      rtint.verbatim(true);
      rtint.committed(true);

      // Make sure rtfloat does not match empty string or '.' but does match 1e2
      rtfloat = !char_r('-') >> (+digit_r >> '.' >> *digit_r | !char_r('.') >> +digit_r) >> !('e' >> rtint);
      rtfloat.leaf(true);
      rtfloat.verbatim(true);
      rtfloat.committed(true);

      rtstring = quoted_r(anychar_r, '"');
      rtstring.leaf(true);
      rtstring.verbatim(true);
      rtstring.committed(true);

      rtint_array = quoted_r(rtint, '[', ']');
      rtfloat_array = quoted_r(rtfloat, '[', ']');
      rtstring_array = quoted_r(rtstring, '[', ']');

      rtpair = rtstring >> rtint
            | rtstring >> rtint_array
            | rtstring >> rtfloat
            | rtstring >> rtfloat_array
            | rtstring >> rtstring
            | rtstring >> rtstring_array
            ;

      rtparameters = *rtpair;

      version = "version" >> rtfloat;

      file = *comment >> !version >> *request;


      request_property =
            "Attribute" >> rtstring >> rtparameters
            | "Bound" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "Color" >> ((rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "ColorSamples" >> rtfloat_array >> rtfloat_array
            | "Declare" >> rtstring >> rtstring
            | "DetailRange" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "Detail" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "Display" >> rtstring >> rtstring >> rtstring >> rtparameters
            | "GeometricApproximation" >> rtstring >> (rtfloat | rtfloat_array)
            | "Illuminate" >> rtint >> rtint
            | "Matte" >> rtint
            | "ObjectInstance" >> rtint
            | "Opacity" >> ((rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "Option" >> rtstring >> rtparameters
            | "Orientation" >> rtstring
            | "RelativeDetail" >> rtfloat
            | "ReverseOrientation"
            | "Sides" >> rtint
            | "TextureCoordinates" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            ;

      request_object = comment
            | attribute
            | camera
            | errors
            | frame
            | geometry
            | motion
            | object
            | shader
            | solid
            | transform
            | transformation
            | world
            ;

      request = request_property | request_object;
      // HAPY : cannot commit request because Points is a prefix of PointsPolygons
      // a "better" grammar would terminate every command/request with ';'
      // or equivalent so that commands can be isolated
      //request.committed(true);

      camera = "Clipping" >> rtfloat >> rtfloat
            | "CropWindow" >> rtfloat >> rtfloat >> rtfloat >> rtfloat
            | "DepthOfField" >> rtfloat >> rtfloat >> rtfloat
            | "Exposure" >> rtfloat >> rtfloat
            | "Format" >> rtint >> rtint >> rtfloat
            | "FrameAspectRatio" >> rtfloat
            | "Hider" >> rtstring >> rtparameters
            | "PixelFilter" >> rtstring >> rtfloat >> rtfloat
            | "PixelSamples" >> rtfloat >> rtfloat
            | "PixelVariance" >> rtfloat
            | "Projection" >> rtstring >> rtparameters
            | "Quantize" >> rtstring >> rtint >> rtint >> rtint >> rtfloat
            | "ScreenWindow" >> rtfloat >> rtfloat >> rtfloat >> rtfloat
            | "ShadingInterpolation" >> rtstring
            | "ShadingRate" >> rtfloat
            | "Shutter" >> rtfloat >> rtfloat
            ;

      frame = "FrameBegin" >> rtint
            | "FrameEnd"
            ;

      world = "WorldBegin" >> *request >> "WorldEnd"
            ;

      transform = "TransformBegin" >> *request >> "TransformEnd"
            ;

      attribute = "AttributeBegin" >> *request >> "AttributeEnd"
            ;

      solid = "SolidBegin" >> rtstring
            | "SolidEnd"
            ;

      object = "ObjectBegin" >> rtint
            | "ObjectEnd"
            ;

      motion = "MotionBegin" >> rtfloat_array
            | "MotionEnd"
            ;

      shader = "AreaLightSource" >> rtstring >> rtint >> rtparameters
            | "Atmosphere" >> rtstring >> rtparameters
            | "Deformation" >> rtstring >> rtparameters
            | "Displacement" >> rtstring >> rtparameters
            | "Exterior" >> rtstring >> rtparameters
            | "Imager" >> rtstring >> rtparameters
            | "Interior" >> rtstring >> rtparameters
            | "LightSource" >> rtstring >> rtint >> rtparameters
            | "Surface" >> rtstring >> rtparameters
            ;

      geometry = "Polygon" >> rtparameters
            | "GeneralPolygon" >> rtint_array >> rtparameters
            | "Curves" >> rtstring >> rtint_array >> rtstring >> rtparameters
            | "Blobby" >> rtint >> rtint_array >> rtfloat_array >> rtstring_array >> rtparameters
            | "Procedural" >> rtstring >> rtstring >> rtfloat_array >> rtparameters
            | "Points" >> rtparameters
            | "PointsPolygons" >> rtint_array >> rtint_array >> rtparameters
            | "PointsGeneralPolygons" >> rtint_array >> rtint_array >> rtint_array >> rtparameters
            // TODO RiBasis
            | "Patch" >> rtstring >> rtparameters
            | "PatchMesh" >> rtstring >> rtint >> rtstring >> rtint >> rtstring >> rtparameters
            | "NuPatch" >> rtint >> rtint >> rtfloat_array >> rtfloat >> rtfloat >> rtint >> rtint >> rtfloat_array >> rtfloat >> rtfloat >> rtparameters
            | "TrimCurve" >> rtint_array >> rtint_array >> rtfloat_array >> rtfloat_array >> rtfloat_array >> rtint_array >> rtfloat_array >> rtfloat_array >> rtfloat_array
            | "Sphere" >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Cone" >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Cylinder" >>  rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Hyperboloid" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array) >> rtparameters
            | "Paraboloid" >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Disk" >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Torus" >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtparameters
            | "Geometry" >> rtstring >> rtparameters
            | "SubdivisionMesh" >> ( rtstring >> rtint_array >> rtint_array | rtstring >> rtint_array >> rtint_array >> rtstring_array >> rtint_array >> rtint_array >> rtfloat_array) >> rtparameters
            ;

      transformation = "Identity"
            | "Transform" >> rtfloat_array
            | "ConcatTransform" >> rtfloat_array
            | "Perspective" >> rtfloat
            | "Translate" >> rtfloat >> rtfloat >> rtfloat
            | "Rotate" >> rtfloat >> rtfloat >> rtfloat >> rtfloat
            | "Scale" >> rtfloat >> rtfloat >> rtfloat
            | "Skew" >> ((rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat >> rtfloat) | rtfloat_array)
            | "CoordinateSystem" >> rtstring
            | "CoordSysTransform" >> rtstring
            | "TransformPoints"
            ;

      errors = "ErrorHandler" >> rtstring
            | "ErrorIgnore"
            | "ErrorPrint"
            | "ErrorAbort"
            ;

      textures = "MakeTexture" >> *rtstring >> rtfloat >> rtfloat >> rtparameters
            | "MakeBump" >> *rtstring >> rtfloat >> rtfloat >> rtparameters
            | "MakeLatLongEnvironment" >> *rtstring >> rtfloat >> rtfloat >> rtparameters
            | "MakeCubeFaceEnvironment" >> *rtstring >> rtfloat >> rtstring >> rtfloat >> rtfloat >> rtparameters
            | "MakeShadow" >> rtstring >> rtstring >> rtparameters
            ;

      // Comment without backtracking
      //comment = quoted_r(anychar_r, '#', eol_r);
      comment = '#' >> comment_body >> eol_r;
      comment_body = *(anychar_r - eol_r);
      comment_body.committed(true);
      comment.verbatim(true);
}

// Helper functions
const std::string no_quotes(const std::string& s)
{
      if(s[0] == '"' && s[s.size() - 1] == '"')
            return std::string(s.begin() + 1, s.end() - 1);

      return s;
}

k3d::vector3 mult_scales(const k3d::vector3& v1, const k3d::vector3& v2)
{
      return k3d::vector3(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
}

typedef std::vector<k3d::vector3> coordinates_t;

bool create_polygon(coordinates_t& points, k3d::mesh* mesh)
{
      return_val_if_fail(mesh, false);

      k3d::polyhedron::edges_t edges;
      coordinates_t::const_iterator point = points.begin();
      for(; point != points.end(); point++)
            {
                  k3d::point* new_point = new k3d::point(*point);
                  return_val_if_fail(new_point, false);

                  mesh->points.push_back(new_point);
                  edges.push_back(new k3d::split_edge(new_point));
            }

      k3d::loop_edges(edges.begin(), edges.end());

      k3d::polyhedron* polyhedron = new k3d::polyhedron();
      return_val_if_fail(polyhedron, false);

      polyhedron->edges.insert(polyhedron->edges.end(), edges.begin(), edges.end());

      k3d::face* const face = new k3d::face(*edges.begin());
      return_val_if_fail(face, false);

      polyhedron->faces.push_back(face);
      mesh->polyhedra.push_back(polyhedron);

      return true;
}

/////////////////////////////////////////////////////////////////////////////
// rib_reader_implementation

class rib_reader_implementation :
      public k3d::ifile_format,
      public k3d::igeometry_read_format,
      public k3d::ideletable
{
public:
      rib_reader_implementation()
      {
            m_inside_world = false;

            m_current_mesh = 0;
            m_current_polyhedron = 0;
            m_current_linear_curve_group = 0;

            m_is_solid = false;

            m_transform_number = 0;

            // Init parser ...
            create_parser();
            file.trim(*Hapy::space_r);
            parser.grammar(file);
      }

      unsigned long priority()
      {
            return 0;
      }

      bool query_can_handle(const boost::filesystem::path& FilePath)
      {
            return "rib" == k3d::file_extension(FilePath);
      }

      bool pre_read(k3d::idocument& Document, const boost::filesystem::path& FilePath)
      {
            return true;
      }

      bool read_options(k3d::idocument& Document, const boost::filesystem::path& FilePath)
      {
            return true;
      }

      bool read_file(k3d::idocument& Document, const boost::filesystem::path& FilePath);

      k3d::iplugin_factory& factory()
      {
            return get_factory();
      }

      static k3d::iplugin_factory& get_factory()
      {
            static k3d::plugin_factory<k3d::application_plugin<rib_reader_implementation>, k3d::interface_list<k3d::igeometry_read_format> > factory(
                  k3d::uuid(0x9a392c01, 0x50234b23, 0xa61245ff, 0x9345ce15),
                  "RIBReader",
                  "RenderMan ( .rib )",
                  "");

            return factory;
      }

private:
      // Parser
      Hapy::Parser parser;

      std::map<std::string, k3d::imaterial*> m_materials;

      // Properties
      std::map<std::string, std::string> m_declarations;
      k3d::color m_current_color;
      k3d::color m_current_opacity;
      k3d::ri::integer m_current_matte;

      // Frame parameters
      bool m_inside_world;
      k3d::matrix4 frame_transformation;
      k3d::vector3 frame_translation;
      k3d::matrix4 frame_rotation;
      k3d::vector3 frame_scaling;

      // Transformation stacks
      unsigned long m_transform_number;
      std::stack<std::string> begin_end_stack;
      std::vector<k3d::matrix4> m_transformations;
      std::vector<k3d::vector3> m_translations;
      std::vector<k3d::matrix4> m_rotations;
      std::vector<k3d::vector3> m_scalings;

      bool m_is_solid;
      std::string m_solid_type;

      // Mesh variables and functions
      std::stack<k3d::iobject*> m_transform_objects;
      k3d::mesh* m_current_mesh;
      std::string m_current_name;
      k3d::iobject* m_current_mesh_object;
      k3d::iobject* m_current_mesh_instance;
      k3d::nupatch* m_current_nupatch;
      k3d::bilinear_patch* m_current_bilinear_patch;
      k3d::polyhedron* m_current_polyhedron;
      k3d::linear_curve_group* m_current_linear_curve_group;
      k3d::iobject* m_current_material;
      k3d::iobject* m_current_shader;

      bool create_mesh(k3d::idocument& Document)
      {
            // Create document object ...
            k3d::mesh* const mesh = detail::create_mesh(Document, "RIB mesh", m_current_mesh_object, m_current_mesh_instance);
            return_val_if_fail(mesh, false);
            m_current_mesh = mesh;

            return true;
      }

      bool create_nupatch(k3d::idocument& Document)
      {
            return_val_if_fail(create_mesh(Document), false);

            k3d::nupatch* nupatch = new k3d::nupatch();
            return_val_if_fail(nupatch, false);

            m_current_mesh->nupatches.push_back(nupatch);

            m_current_nupatch = nupatch;

            return true;
      }

      bool create_polyhedron(k3d::idocument& Document)
      {
            return_val_if_fail(create_mesh(Document), false);

            k3d::polyhedron* polyhedron = new k3d::polyhedron();
            return_val_if_fail(polyhedron, false);

            m_current_mesh->polyhedra.push_back(polyhedron);

            m_current_polyhedron = polyhedron;

            return true;
      }

      bool create_bilinear_patch(k3d::idocument& Document)
      {
            return_val_if_fail(create_mesh(Document), false);

            k3d::bilinear_patch* bpatch = new k3d::bilinear_patch();
            return_val_if_fail(bpatch, false);

            m_current_mesh->bilinear_patches.push_back(bpatch);

            m_current_bilinear_patch = bpatch;

            return true;
      }

      bool create_linear_curve_group(k3d::idocument& Document)
      {
            return_val_if_fail(create_mesh(Document), false);

            k3d::linear_curve_group* const curve_group = new k3d::linear_curve_group();
            return_val_if_fail(curve_group, false);

            m_current_mesh->linear_curve_groups.push_back(curve_group);

            m_current_linear_curve_group = curve_group;

            return true;
      }

      bool create_transform(k3d::idocument& Document)
      {
            k3d::iobject* const transform = k3d::create_document_plugin(k3d::classes::Transform(), Document);
            return_val_if_fail(transform, false);

            transform->set_name("Transform " + k3d::to_string(++m_transform_number));
            connect_transforms(transform, Document);
            m_transform_objects.push(transform);

            return true;
      }

      bool connect_transforms(k3d::iobject* Object, k3d::idocument& Document)
      {
            if(m_transform_objects.empty())
                  return false;

            k3d::iobject* const last_transform = m_transform_objects.top();
            k3d::itransform_source* const transform_source = dynamic_cast<k3d::itransform_source*>(last_transform);
            return_val_if_fail(transform_source, false);

            k3d::itransform_sink* const transform_sink = dynamic_cast<k3d::itransform_sink*>(Object);
            return_val_if_fail(transform_sink, false);

            k3d::idag::dependencies_t dependencies;
            dependencies.insert(std::make_pair(&transform_sink->transform_sink_input(), &transform_source->transform_source_output()));
            Document.dag().set_dependencies(dependencies);

            return true;
      }

      k3d::imaterial* assign_current_material(k3d::idocument& Document)
      {
            if(m_current_material)
                  {
                        k3d::imaterial* current = dynamic_cast<k3d::imaterial*>(m_current_material);
                        if(current)
                              return current;
                  }

            k3d::imaterial* default_material = dynamic_cast<k3d::imaterial*>(k3d::default_material(Document));
            return default_material;
      }

      void parse_subpree(const Hapy::Pree& Node, k3d::idocument& Document);

      void get_rtint_array(const Hapy::Pree& IntArray, std::vector<unsigned long>& Ints)
      {
            assert_warning(IntArray.rid() == rtint_array.id());

            for(Hapy::Pree::const_iterator node = IntArray.begin(); node != IntArray.end(); node++)
            {
                  if(node->image() == "[" || node->image() == "]")
                        continue;

                  for(Hapy::Pree::const_iterator i = (*node).begin(); i != (*node).end(); i++)
                        Ints.push_back(k3d::from_string<unsigned long>(i->image(), 0));
            }
      }

      void get_rtfloat_array(const Hapy::Pree& FloatArray, std::vector<double>& Floats)
      {
            assert_warning(FloatArray.rid() == rtfloat_array.id());

            for(Hapy::Pree::const_iterator node = FloatArray.begin(); node != FloatArray.end(); node++)
            {
                  if(node->image() == "[" || node->image() == "]")
                        continue;

                  for(Hapy::Pree::const_iterator i = (*node).begin(); i != (*node).end(); i++)
                        Floats.push_back(k3d::from_string<double>(i->image(), 0));
            }
      }

      void get_rtfloat_array(const Hapy::Pree& FloatArray, coordinates_t& Points)
      {
            assert_warning(FloatArray.rid() == rtfloat_array.id() || FloatArray.rid() == rtint_array.id());

            double x;
            double y;
            unsigned long n = 0;;
            for(Hapy::Pree::const_iterator node = FloatArray.begin(); node != FloatArray.end(); node++)
            {
                  if(node->image() == "[" || node->image() == "]")
                        continue;

                  for(Hapy::Pree::const_iterator i = (*node).begin(); i != (*node).end(); i++)
                        {
                              double value = k3d::from_string<double>(i->image(), 0);
                              if(n == 0)
                                    x = value;
                              else if(n == 1)
                                    y = value;
                              else
                                    Points.push_back(k3d::vector3(x, y, value));

                              n = (n + 1) % 3;
                        }
            }

            assert_warning(n == 0);
      }

      void get_rtfloat_matrix(const Hapy::Pree& FloatArray, k3d::matrix4& Matrix)
      {
            std::vector<double> v;
            get_rtfloat_array(FloatArray, v);

            Matrix = k3d::matrix4(
                  k3d::vector4(v[0], v[1], v[2], v[3]),
                  k3d::vector4(v[4], v[5], v[6], v[7]),
                  k3d::vector4(v[8], v[9], v[10], v[11]),
                  k3d::vector4(v[12], v[13], v[14], v[15]));

            Matrix = Matrix.Transpose();
      }

      void set_current_transformations(k3d::iobject* Object)
      {
            assert_warning(k3d::set_property_value(*Object, "position", k3d::vector3(*m_translations.rbegin() + extractTranslation(*m_transformations.rbegin()))));
            assert_warning(k3d::set_property_value(*Object, "orientation", k3d::angle_axis(k3d::rotation3D(*m_rotations.rbegin() * *m_transformations.rbegin()))));
            assert_warning(k3d::set_property_value(*Object, "scale", k3d::vector3(mult_scales(*m_scalings.rbegin(), k3d::extractScaling(*m_transformations.rbegin())))));
      }

      void rib_stack_push(const std::string& name, k3d::idocument& Document)
      {
            // Save object type and stack a generic object ...
            begin_end_stack.push(name);

            if(name == "Frame")
                  {
                        frame_translation = k3d::vector3(0, 0, 0);
                        frame_rotation = k3d::identity3D();
                        frame_scaling = k3d::vector3(1, 1, 1);
                        m_inside_world = false;
                  }
            else if(name == "World")
                  {
                        m_inside_world = true;

                        m_transformations.push_back(k3d::identity3D());
                        m_translations.push_back(k3d::vector3(0, 0, 0));
                        m_rotations.push_back(k3d::identity3D());
                        m_scalings.push_back(k3d::vector3(1, 1, 1));
                  }

            if(m_inside_world)
                  {
                        // Save current transformation ...
                        if(m_transform_objects.size())
                              set_current_transformations(m_transform_objects.top());

                        // Push new transformation ...
                        create_transform(Document);

                        m_transformations.push_back(k3d::identity3D());
                        m_translations.push_back(k3d::vector3(0, 0, 0));
                        m_rotations.push_back(k3d::identity3D());
                        m_scalings.push_back(k3d::vector3(1, 1, 1));
                  }
      }

      void rib_stack_pop(const std::string& name)
      {
            assert_warning(begin_end_stack.top() == name);
            begin_end_stack.pop();

            if(m_inside_world)
                  {
                        m_transformations.pop_back();
                        m_translations.pop_back();
                        m_rotations.pop_back();
                        m_scalings.pop_back();

                        m_transform_objects.pop();
                  }

            if(name == "World")
                  m_inside_world = false;
      }

      void set_object_properties(k3d::iobject* Object, const std::string& Name, k3d::idocument& Document)
      {
            assert_warning(Object);

            // Set name, parent transformer and current transformations
            Object->set_name(m_current_name + "  " + Name);
            connect_transforms(Object, Document);
            set_current_transformations(Object);
      }

      k3d::matrix4 get_blobby_matrix(std::vector<double>::iterator First)
      {
            k3d::matrix4 m;

            m[0] = k3d::vector4(First[0], First[1], First[2], First[3]);
            First += 4;
            m[1] = k3d::vector4(First[0], First[1], First[2], First[3]);
            First += 4;
            m[2] = k3d::vector4(First[0], First[1], First[2], First[3]);
            First += 4;
            m[3] = k3d::vector4(First[0], First[1], First[2], First[3]);

            return m.Transpose();
      }

      // Debug
      void Childs(const Hapy::Pree& Node)
      {
            for(Hapy::Pree::const_iterator node = Node.begin(); node != Node.end(); node++)
                  std::cerr << debug << "Node child : " << node->rid() << " -> " << node->image() << std::endl;
      }
};

void rib_reader_implementation::parse_subpree(const Hapy::Pree& Node, k3d::idocument& Document)
{
      if(Node.begin() == Node.end())
            return;

      if(Node[0].rid() == request_property.id())
      {
            Hapy::Pree::const_iterator content_node = (Node[0]).begin();
            if(content_node->image() == "ReverseOrientation")
            {
            }
            else
            {
                  content_node = content_node->begin();
                  if(content_node->image() == "Attribute")
                  {
                        ++content_node;
                        if(content_node->image() == "\"identifier\"")
                        {
                              ++content_node;
                              // rtparameters
                              content_node = content_node->begin();
                              // rtpair
                              content_node = content_node->begin();
                              // string + string
                              content_node = content_node->begin();
                              if(content_node->image() == "\"name\"")
                              {
                                    ++content_node;
                                    // string array
                                    content_node = content_node->begin();
                                    ++content_node;
                                    m_current_name = content_node->image();
                              }
                        }
                  }
                  else
                  if(content_node->image() == "Color")
                  {
                        ++content_node;
                        if(content_node->begin()->rid() == rtfloat_array.id())
                              content_node = content_node->begin()->begin() + 1;

                        m_current_color = k3d::from_string<k3d::color>(content_node->image(), k3d::color(0, 0, 0));
                  }
                  else
                  if(content_node->image() == "Declare")
                  {
                        ++content_node;
                        assert_warning(content_node->rid() == rtstring.id());
                        std::string variable = content_node->image();
                        ++content_node;
                        assert_warning(content_node->rid() == rtstring.id());
                        m_declarations[no_quotes(variable)] = no_quotes(content_node->image());
                  }
                  else
                  if(content_node->image() == "Matte")
                  {
                        ++content_node;
                        m_current_matte = k3d::from_string<k3d::ri::integer>(content_node->image(), 0);
                  }
                  else
                  if(content_node->image() == "Opacity")
                  {
                        ++content_node;
                        if(content_node->begin()->rid() == rtfloat_array.id())
                              content_node = content_node->begin()->begin() + 1;

                        m_current_opacity = k3d::from_string<k3d::color>(content_node->image(), k3d::color(0, 0, 0));
                  }
            }
      }
      else
      if(Node[0].rid() == frame.id())
      {
            Hapy::Pree::const_iterator frame_node = (Node[0]).begin();
            if(frame_node->image() == "FrameEnd")
            {
            }
            else
            {
                  frame_node = frame_node->begin();
                  assert_warning(frame_node->image() == "FrameBegin");

                  rib_stack_push("Frame", Document);

                  frame_node++;
                  assert_warning(frame_node->rid() == rtint.id());
                  k3d::from_string<k3d::ri::integer>(frame_node->image(), 0);
            }
      }
      else
      if(Node[0].rid() == world.id())
      {
            Hapy::Pree::const_iterator world_node = (Node[0]).begin();
            assert_warning(world_node->image() == "WorldBegin");

            rib_stack_push("World", Document);

            world_node++;
            parse_subpree(*world_node, Document);

            rib_stack_pop("World");

            world_node++;
            assert_warning(world_node->image() == "WorldEnd");
      }
      else
      if(Node[0].rid() == transform.id())
      {
            Hapy::Pree::const_iterator transform_node = (Node[0]).begin();
            assert_warning(transform_node->image() == "TransformBegin");

            rib_stack_push("Transform", Document);

            transform_node++;
            parse_subpree(*transform_node, Document);

            rib_stack_pop("Transform");

            transform_node++;
            assert_warning(transform_node->image() == "TransformEnd");
      }
      else
      if(Node[0].rid() == attribute.id())
      {
            Hapy::Pree::const_iterator attribute_node = (Node[0]).begin();
            assert_warning(attribute_node->image() == "AttributeBegin");

            rib_stack_push("Attribute", Document);

            attribute_node++;
            parse_subpree(*attribute_node, Document);

            rib_stack_pop("Attribute");

            attribute_node++;
            assert_warning(attribute_node->image() == "AttributeEnd");
      }
      else
      if(Node[0].rid() == solid.id())
      {
            Hapy::Pree::const_iterator solid_node = (Node[0]).begin();
            if(solid_node->image() == "SolidEnd")
            {
                  m_is_solid = false;
            }
            else
            {
                  solid_node = solid_node->begin();
                  assert_warning(solid_node->image() == "SolidBegin");

                  solid_node++;
                  assert_warning(solid_node->rid() == rtstring.id());
                  m_solid_type = no_quotes(solid_node->image());

                  m_is_solid = true;
                  //m_current_object_group = create_object_group(Document);
            }
      }
      else
      if(Node[0].rid() == object.id())
      {
            Hapy::Pree::const_iterator object_node = (Node[0]).begin();
            if(object_node->image() == "ObjectEnd")
            {
            }
            else
            {
                  object_node = object_node->begin();
                  assert_warning(object_node->image() == "ObjectBegin");

                  object_node++;
                  assert_warning(object_node->rid() == rtint.id());

                  k3d::from_string<k3d::ri::integer>(object_node->image(), 0);
            }
      }
      else
      if(Node[0].rid() == motion.id())
      {
            Hapy::Pree::const_iterator motion_node = (Node[0]).begin();
            if(motion_node->image() == "MotionEnd")
            {
            }
            else
            {
                  motion_node = motion_node->begin();
                  assert_warning(motion_node->image() == "MotionBegin");

                  motion_node++;
                  assert_warning(motion_node->rid() == rtfloat_array.id());

            }
      }
      else
      if(Node[0].rid() == geometry.id())
      {
            Hapy::Pree::const_iterator pi = (Node[0]).begin();
            for(; pi != (Node[0]).end(); pi++)
            {
                  Hapy::Pree f = (*pi);
                  Hapy::Pree::const_iterator pir = f.begin();
                  if("NuPatch" == (*pir).image())
                  {
                        k3d::from_string<long>((++pir)->image(), 0); // long u_npoints
                        long u_order = k3d::from_string<long>((++pir)->image(), 0);
                        const Hapy::Pree& u_knot_pree = *++pir;
                        assert_warning(u_knot_pree.rid() == rtfloat_array.id());
                        k3d::from_string<double>((++pir)->image(), 0); // double u_min
                        k3d::from_string<double>((++pir)->image(), 0); // double u_max

                        k3d::from_string<long>((++pir)->image(), 0); // long v_npoints
                        long v_order = k3d::from_string<long>((++pir)->image(), 0);
                        const Hapy::Pree& v_knot_pree = *++pir;
                        assert_warning(v_knot_pree.rid() == rtfloat_array.id());
                        k3d::from_string<double>((++pir)->image(), 0); // double v_min
                        k3d::from_string<double>((++pir)->image(), 0); // double v_max

                        const Hapy::Pree& parameters = *++pir;
                        const Hapy::Pree& pair = *parameters.begin();
                        const Hapy::Pree& value = *pair.begin();
                        const Hapy::Pree& string = *value.begin();
                        const Hapy::Pree& float_array = *(value.begin() + 1);

                        // Load arrays ...
                        std::vector<double> u_knots;
                        get_rtfloat_array(u_knot_pree, u_knots);
                        std::vector<double> v_knots;
                        get_rtfloat_array(v_knot_pree, v_knots);
                        std::vector<double> points;
                        get_rtfloat_array(float_array, points);

                        // Create a new nupatch
                        return_if_fail(create_nupatch(Document));

                        // Set orders ...
                        m_current_nupatch->u_order = u_order;
                        m_current_nupatch->v_order = v_order;

                        // Set knots ...
                        for(std::vector<double>::const_iterator k = u_knots.begin(); k != u_knots.end(); k++)
                              m_current_nupatch->u_knots.push_back(*k);
                        for(std::vector<double>::const_iterator k = v_knots.begin(); k != v_knots.end(); k++)
                              m_current_nupatch->v_knots.push_back(*k);

                        // Add control points ...
                        unsigned long pts = points.size();
                        assert_warning((string.image() == "\"P\"" && (pts % 3 == 0)) || (string.image() == "\"Pw\"" && (pts % 4 == 0)));

                        if(string.image() == "\"P\"")
                        {
                              for(unsigned long p = 0; p < pts / 3; p++)
                              {
                                    k3d::point* const point = new k3d::point(points[p*3], points[p*3 + 1], points[p*3 + 2]);
                                    return_if_fail(point);

                                    m_current_mesh->points.push_back(point);
                                    m_current_nupatch->control_points.push_back(point);
                              }
                        }
                        else if(string.image() == "\"Pw\"")
                        {
                              for(unsigned long p = 0; p < pts / 4; p++)
                              {
                                    k3d::point* const point = new k3d::point(points[p*4], points[p*4 + 1], points[p*4 + 2]);
                                    return_if_fail(point);

                                    m_current_mesh->points.push_back(point);

                                    double weight = points[p*4 + 3];
                                    point->position /= weight ? weight : 1;
                                    m_current_nupatch->control_points.push_back(k3d::nupatch::control_point(point, weight));
                              }
                        }

                        // Set material and transform properties ...
                        m_current_nupatch->material = assign_current_material(Document);
                        set_object_properties(m_current_mesh_instance, "NuPatch", Document);
                  }
                  else if("Patch" == (*pir).image())
                  {
                        std::string type = no_quotes((++pir)->image());
                        if("bilinear" == type)
                        {
                              create_bilinear_patch(Document);

                              const Hapy::Pree& parameters = *++pir;
                              const Hapy::Pree& pair = *parameters.begin();
                              const Hapy::Pree& value = *pair.begin();
                              const Hapy::Pree& string = *value.begin();
                              const Hapy::Pree& float_array = *(value.begin() + 1);

                              if("P" == no_quotes(string.image()))
                              {
                                    std::vector<double> points;
                                    get_rtfloat_array(float_array, points);
                                    assert_warning(4 * 3 == points.size());

                                    for(unsigned long p = 0; p < 4; p++)
                                    {
                                          k3d::point* point = new k3d::point(points[p*3], points[p*3+1], points[p*3+2]);
                                          m_current_mesh->points.push_back(point);
                                          m_current_bilinear_patch->control_points[p] = point;
                                    }
                              }
                              else
                                    std::cerr << debug << "RIB reader : unsupported point type for bilinear patch" << std::endl;
                        }
                        else if("bicubic" == type)
                        {
                        }
                        else
                              std::cerr << debug << "Invalid RenderMan Patch type " << type << std::endl;

                        // Set material and transform properties ...
                        m_current_bilinear_patch->material = assign_current_material(Document);
                        set_object_properties(m_current_mesh_instance, "Patch", Document);
                  }
                  else if("Polygon" == (*pir).image())
                  {
                        pir++;
                        const Hapy::Pree& parameters = *pir++;
                        const Hapy::Pree& pair = *parameters.begin();
                        const Hapy::Pree& value = *pair.begin();
                        const Hapy::Pree& string = *value.begin();
                        std::string parameter_name = no_quotes(string.image());
                        if(parameter_name == "P")
                              {
                                    return_if_fail(create_mesh(Document));

                                    const Hapy::Pree& float_array = *(value.begin() + 1);
                                    coordinates_t points;
                                    get_rtfloat_array(float_array, points);

                                    create_polygon(points, m_current_mesh);
                                    set_object_properties(m_current_mesh_instance, "Polygon", Document);
                              }
                        //else
                              // Find "P"
                  }
                  else if("PointsGeneralPolygons" == (*pir).image())
                  {
                        pir++;

                        const Hapy::Pree& loop_counts = *pir++;
                        const Hapy::Pree& vertex_counts = *pir++;
                        const Hapy::Pree& vertex_ids = *pir++;
                        const Hapy::Pree& parameters = *pir++;

                        assert_warning(loop_counts.rid() == rtint_array.id());
                        assert_warning(vertex_counts.rid() == rtint_array.id());
                        assert_warning(vertex_ids.rid() == rtint_array.id());
                        assert_warning(parameters.rid() == rtparameters.id());

                        std::vector<unsigned long> loops;
                        std::vector<unsigned long> counts;
                        std::vector<unsigned long> ids;

                        get_rtint_array(loop_counts, loops);
                        get_rtint_array(vertex_counts, counts);
                        get_rtint_array(vertex_ids, ids);

                        const Hapy::Pree& pair = *parameters.begin();
                        const Hapy::Pree& value = *pair.begin();
                        //const Hapy::Pree& string = *value.begin();
                        const Hapy::Pree& float_array = *(value.begin() + 1);

                        std::vector<double> points;
                        get_rtfloat_array(float_array, points);

                        // Create a new polyhedron
                        return_if_fail(create_polyhedron(Document));

                        // Add points ...
                        unsigned long pts = points.size();
                        assert_warning(pts % 3 == 0);

                        std::vector<k3d::point*> geometric_points;
                        for(unsigned long p = 0; p < pts/ 3; p++)
                        {
                              k3d::point* const point = new k3d::point(points[p*3], points[p*3 + 1], points[p*3 + 2]);
                              return_if_fail(point);

                              geometric_points.push_back(point);
                              m_current_mesh->points.push_back(point);
                        }

                        // Create faces ...
                        std::vector<unsigned long>::const_iterator current_vertex_count = counts.begin();
                        std::vector<unsigned long>::const_iterator current_vertex_id = ids.begin();
                        for(std::vector<unsigned long>::const_iterator loop = loops.begin(); loop < loops.end(); loop++)
                        {
                              unsigned long loop_number = *loop;
                              for(unsigned long l = 0; l < loop_number; l++)
                              {
                                    unsigned long n_vertices = *current_vertex_count++;

                                    k3d::split_edge* previous_edge = 0;
                                    k3d::face* face = 0;

                                    for(unsigned long vs = 0; vs < n_vertices; vs++)
                                          {
                                                k3d::point* const point = geometric_points[*current_vertex_id++];
                                                return_if_fail(point);

                                                k3d::split_edge* edge = new k3d::split_edge(point);
                                                return_if_fail(edge);

                                                if(!face)
                                                      {
                                                            face = new k3d::face(edge);
                                                            return_if_fail(face);
                                                            m_current_polyhedron->faces.push_back(face);
                                                      }
                                                else
                                                      {
                                                            previous_edge->face_clockwise = edge;
                                                      }

                                                m_current_polyhedron->edges.push_back(edge);
                                                previous_edge = edge;
                                          }

                                    // Close loop
                                    if(face)
                                          {
                                                previous_edge->face_clockwise = face->first_edge;
                                          }
                              }
                        }

                        // Set material and transform properties ...
                        m_current_polyhedron->material = assign_current_material(Document);
                        set_object_properties(m_current_mesh_instance, "Polygons", Document);
                  }
                  else if("Cone" == (*pir).image())
                  {
                        k3d::iobject* const cone = k3d::create_document_plugin(k3d::classes::Cone(), Document);
                        assert_warning(cone);

                        k3d::set_property_value(*cone, "height", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*cone, "radius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*cone, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*cone, "material", assign_current_material(Document));
                        set_object_properties(cone, "Cone", Document);
                  }
                  else if("Cylinder" == (*pir).image())
                  {
                        k3d::iobject* const cylinder = k3d::create_document_plugin(k3d::classes::Cylinder(), Document);
                        assert_warning(cylinder);

                        k3d::set_property_value(*cylinder, "radius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*cylinder, "zmin", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*cylinder, "zmax", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*cylinder, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*cylinder, "material", assign_current_material(Document));
                        set_object_properties(cylinder, "Cylinder", Document);
                  }
                  else if("Disk" == (*pir).image())
                  {
                        k3d::iobject* const disk = k3d::create_document_plugin(k3d::classes::Disk(), Document);
                        assert_warning(disk);

                        k3d::set_property_value(*disk, "height", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*disk, "radius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*disk, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*disk, "material", assign_current_material(Document));
                        set_object_properties(disk, "Disk", Document);
                  }
                  else if("Hyperboloid" == (*pir).image())
                  {
                        k3d::iobject* const hyperboloid = k3d::create_document_plugin(k3d::classes::Hyperboloid(), Document);
                        assert_warning(hyperboloid);

                        k3d::set_property_value(*hyperboloid, "p1x", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "p1y", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "p1z", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "p2x", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "p2y", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "p2z", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*hyperboloid, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*hyperboloid, "material", assign_current_material(Document));
                        set_object_properties(hyperboloid, "Hyperboloid", Document);
                  }
                  else if("Paraboloid" == (*pir).image())
                  {
                        k3d::iobject* const paraboloid = k3d::create_document_plugin(k3d::classes::Paraboloid(), Document);
                        assert_warning(paraboloid);

                        k3d::set_property_value(*paraboloid, "radius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*paraboloid, "zmin", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*paraboloid, "zmax", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*paraboloid, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*paraboloid, "material", assign_current_material(Document));
                        set_object_properties(paraboloid, "Paraboloid", Document);
                  }
                  else if("Sphere" == (*pir).image())
                  {
                        k3d::iobject* const sphere = k3d::create_document_plugin(k3d::classes::Sphere(), Document);
                        assert_warning(sphere);

                        k3d::set_property_value(*sphere, "radius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*sphere, "zmin", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*sphere, "zmax", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*sphere, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*sphere, "material", assign_current_material(Document));
                        set_object_properties(sphere, "Sphere", Document);
                  }
                  else if("Torus" == (*pir).image())
                  {
                        k3d::iobject* const torus = k3d::create_document_plugin(k3d::classes::Torus(), Document);
                        assert_warning(torus);

                        k3d::set_property_value(*torus, "majorradius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*torus, "minorradius", k3d::from_string<double>((++pir)->image(), 0));
                        k3d::set_property_value(*torus, "phimin", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));
                        k3d::set_property_value(*torus, "phimax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));
                        k3d::set_property_value(*torus, "thetamax", k3d::radians(k3d::from_string<double>((++pir)->image(), 0)));

                        k3d::set_property_value(*torus, "material", assign_current_material(Document));
                        set_object_properties(torus, "Torus", Document);
                  }
                  else if("Blobby" == (*pir).image())
                  {
                        /*const Hapy::Pree& nleaf =*/ *++pir;
                        const Hapy::Pree& codes_array = *++pir;
                        const Hapy::Pree& floats_array = *++pir;
                        const Hapy::Pree& names_array = *++pir;
                        const Hapy::Pree& parameters = *++pir;

                        assert_warning(codes_array.rid() == rtint_array.id());
                        assert_warning(floats_array.rid() == rtfloat_array.id());
                        assert_warning(names_array.rid() == rtstring_array.id());
                        assert_warning(parameters.rid() == rtparameters.id());

                        std::vector<unsigned long> codes;
                        std::vector<double> floats;

                        get_rtint_array(codes_array, codes);
                        get_rtfloat_array(floats_array, floats);

                        // Populate blobby
                        return_if_fail(create_mesh(Document));
                        std::vector<k3d::blobby::opcode*> blobbies;

                        std::vector<unsigned long>::iterator code = codes.begin();
                        unsigned long code_val;
                        while(code != codes.end())
                        {
                              code_val = *code++;
                              if(code_val == 1000)
                              {
                                    // Constant
                                    /*unsigned long values_index =*/ *code++;
                              }
                              else
                              if(code_val == 1001)
                              {
                                    // Ellipsoid
                                    unsigned long values_index = *code++;

                                    k3d::matrix4 m = get_blobby_matrix(floats.begin() + values_index);
                                    k3d::point* p = new k3d::point(m[0][3], m[1][3], m[2][3]);
                                    m[0][3] = m[1][3] = m[2][3] = 0;
                                    m_current_mesh->points.push_back(p);

                                    blobbies.push_back(new k3d::blobby::ellipsoid(p, m));
                              }
                              else
                              if(code_val == 1002)
                              {
                                    // Segment
                                    unsigned long values_index = *code++;

                                    k3d::matrix4 m = get_blobby_matrix(floats.begin() + values_index + 7);
                                    k3d::point* start = new k3d::point(*(floats.begin() + values_index), *(floats.begin() + values_index + 1), *(floats.begin() + values_index + 2));
                                    k3d::point* end = new k3d::point(*(floats.begin() + values_index + 3), *(floats.begin() + values_index + 4), *(floats.begin() + values_index + 5));
                                    m_current_mesh->points.push_back(start);
                                    m_current_mesh->points.push_back(end);

                                    blobbies.push_back(new k3d::blobby::segment(start, end, *(floats.begin() + values_index + 6), m));
                              }
                              else
                              if(code_val == 1003)
                              {
                                    // Repelling plane
                                    /*unsigned long values_index =*/ *code++;
                                    /*unsigned long string_index =*/ *code++;
                              }
                              else
                              if(code_val == 0)
                              {
                                    // Add operator
                                    unsigned long operators = *code++;

                                    k3d::blobby::add* add = new k3d::blobby::add();
                                    blobbies.push_back(add);

                                    for(unsigned long n = 0; n < operators; n++)
                                          add->add_operand(blobbies[*code++]);
                              }
                              else
                              if(code_val == 1)
                              {
                                    // Mult operator
                                    unsigned long operators = *code++;

                                    k3d::blobby::multiply* mult = new k3d::blobby::multiply();
                                    blobbies.push_back(mult);

                                    for(unsigned long n = 0; n < operators; n++)
                                          mult->add_operand(blobbies[*code++]);
                              }
                              else
                              if(code_val == 2)
                              {
                                    // Max operator
                                    unsigned long operators = *code++;

                                    k3d::blobby::max* max = new k3d::blobby::max();
                                    blobbies.push_back(max);

                                    for(unsigned long n = 0; n < operators; n++)
                                          max->add_operand(blobbies[*code++]);
                              }
                              else
                              if(code_val == 3)
                              {
                                    // Min operator
                                    unsigned long operators = *code++;

                                    k3d::blobby::min* min = new k3d::blobby::min();
                                    blobbies.push_back(min);

                                    for(unsigned long n = 0; n < operators; n++)
                                          min->add_operand(blobbies[*code++]);
                              }
                              else
                              if(code_val == 4)
                              {
                                    // Substract operator
                                    unsigned long subtrahend = *code++;
                                    unsigned long minuend = *code++;
                                    assert_warning(subtrahend < blobbies.size());
                                    assert_warning(minuend < blobbies.size());

                                    blobbies.push_back(new k3d::blobby::subtract(blobbies[subtrahend], blobbies[minuend]));
                              }
                              else
                              if(code_val == 5)
                              {
                                    // Divide operator
                                    unsigned long dividend = *code++;
                                    unsigned long divisor = *code++;
                                    assert_warning(dividend < blobbies.size());
                                    assert_warning(divisor < blobbies.size());

                                    blobbies.push_back(new k3d::blobby::divide(blobbies[dividend], blobbies[divisor]));
                              }
                              else
                              if(code_val == 6)
                              {
                                    // Negate operator
                                    /*unsigned long negand =*/ *code++;
                              }
                              else
                              if(code_val == 7)
                              {
                                    // Identity operator
                                    /*unsigned long idempotentate =*/ *code++;
                              }
                              else
                                    assert_not_reached();
                        }

                        m_current_mesh->blobbies.push_back(new k3d::blobby(blobbies.back()));
                        set_object_properties(m_current_mesh_instance, "Blobby", Document);
                  }
            }
      }
      else
      if(Node[0].rid() == transformation.id())
      {
            Hapy::Pree::const_iterator transf_item = (Node[0]).begin();
            if(transf_item->image() == "Identity")
            {
                  if(!m_inside_world)
                        frame_transformation = k3d::identity3D();
                  else
                        *m_transformations.rbegin() = k3d::identity3D();
            }
            else if(transf_item->image() == "TransformPoints")
            {
            }
            else
            {
                  Hapy::Pree f = (*transf_item);
                  Hapy::Pree::const_iterator transf_item = f.begin();
                  if("ConcatTransform" == (*transf_item).image())
                  {
                        const Hapy::Pree& matrix = *++transf_item;
                        assert_warning(matrix.rid() == rtfloat_array.id());

                        k3d::matrix4 m;
                        get_rtfloat_matrix(matrix, m);

                        if(!m_inside_world)
                              frame_transformation = k3d::identity3D();
                        else
                              *m_transformations.rbegin() = *m_transformations.rbegin() * m;
                  }
                  else if("Transform" == (*transf_item).image())
                  {
                        const Hapy::Pree& matrix = *++transf_item;
                        assert_warning(matrix.rid() == rtfloat_array.id());

                        k3d::matrix4 m;
                        get_rtfloat_matrix(matrix, m);

                        if(!m_inside_world)
                              frame_transformation = k3d::identity3D();
                        else
                              *m_transformations.rbegin() = m;
                  }
                  else if("Translate" == (*transf_item).image())
                  {
                        double t1 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double t2 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double t3 = k3d::from_string<double>((++transf_item)->image(), 0);

                        if(!m_inside_world)
                              frame_translation += k3d::vector3(t1, t2, t3);
                        else
                              *m_translations.rbegin() += k3d::vector3(t1, t2, t3);
                  }
                  else if("Rotate" == (*transf_item).image())
                  {
                        double angle = k3d::from_string<double>((++transf_item)->image(), 0);
                        double axis1 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double axis2 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double axis3 = k3d::from_string<double>((++transf_item)->image(), 0);
                        k3d::matrix4 r_matrix = k3d::rotation3D(k3d::radians(angle), k3d::vector3(axis1, axis2, axis3));

                        if(!m_inside_world)
                              frame_rotation = frame_rotation * r_matrix;
                        else
                              *m_rotations.rbegin() = *m_rotations.rbegin() * r_matrix;
                  }
                  else if("Scale" == (*transf_item).image())
                  {
                        double s1 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double s2 = k3d::from_string<double>((++transf_item)->image(), 0);
                        double s3 = k3d::from_string<double>((++transf_item)->image(), 0);

                        if(!m_inside_world)
                              frame_scaling = mult_scales(frame_scaling, k3d::vector3(s1, s2, s3));
                        else
                              *m_scalings.rbegin() = mult_scales(*m_scalings.rbegin(), k3d::vector3(s1, s2, s3));
                  }
            }
      }
      else
      if(Node[0].rid() == shader.id())
      {
            Hapy::Pree::const_iterator shader_node = (Node[0]).begin();
            for(; shader_node != (Node[0]).end(); shader_node++)
            {
                  Hapy::Pree f = (*shader_node);
                  Hapy::Pree::const_iterator shader_node = f.begin();
                  if("LightSource" == (*shader_node).image())
                  {
                        std::string name = no_quotes((++shader_node)->image());
                        /*int val = */k3d::from_string<int>((++shader_node)->image(), 0);

                        m_current_shader = create_document_plugin(k3d::classes::RenderManLightShader(), Document, "Light shader " + name);
                        m_current_material = create_document_plugin(k3d::classes::RenderManLight(), Document, "Light " + name);
                        assert_warning(k3d::set_property_value(*m_current_material, "shader", m_current_shader));

                        k3d::set_property_value(*m_current_shader, "shader_name", name);

                        // rtparameters
                        const Hapy::Pree& parameters = *++shader_node;
                        for(Hapy::Pree::const_iterator current_pair = parameters.begin(); current_pair != parameters.end(); current_pair++)
                        {
                              const Hapy::Pree& pair = *current_pair;
                              const Hapy::Pree& pair_value = *pair.begin();
                              const Hapy::Pree& string = *pair_value.begin();
                              const std::string variable = no_quotes(string.image());
                              const Hapy::Pree& value = *(pair_value.begin() + 1);

                              if(m_declarations[variable] == "float")
                              {
                                    const Hapy::Pree& float_val = *(value.begin() + 1);
                                    k3d::set_property_value(*m_current_shader, variable, k3d::from_string<double>(float_val.image(), 0));
                              }
                              else
                              if(m_declarations[variable] == "color")
                              {
                                    const Hapy::Pree& float_vals = *(value.begin() + 1);
                                    k3d::set_property_value(*m_current_shader, variable, k3d::from_string<k3d::color>(float_vals.image(), k3d::color(1.0, 1.0, 1.0)));
                              }
                              else
                              if(m_declarations[variable] == "point")
                              {
                                    const Hapy::Pree& float_vals = *(value.begin() + 1);
                                    k3d::set_property_value(*m_current_shader, variable, k3d::from_string<k3d::vector3>(float_vals.image(), k3d::vector3(0.0, 0.0, 0.0)));
                              }
                              else
                                    std::cerr << debug << "Variable type not declared for " << variable << " : " << m_declarations[variable] << std::endl;
                        }
                  }
                  else
                  if("Surface" == (*shader_node).image())
                  {
                        std::string name = no_quotes((++shader_node)->image());
                        if(name != "null")
                        {
                              m_current_shader = create_document_plugin(k3d::classes::RenderManSurfaceShader(), Document, "Surface shader " + name);
                              m_current_material = create_document_plugin(k3d::classes::RenderManMaterial(), Document, "Surface material " + name);
                              assert_warning(k3d::set_property_value(*m_current_material, "surface_shader", m_current_shader));

                              k3d::set_property_value(*m_current_shader, "shader_name", name);
                              k3d::set_property_value(*m_current_material, "color", m_current_color);
                              k3d::set_property_value(*m_current_material, "opacity", m_current_opacity);
                              k3d::set_property_value(*m_current_material, "matte", m_current_matte ? true : false);

                              // rtparameters
                              const Hapy::Pree& parameters = *++shader_node;
                              for(Hapy::Pree::const_iterator current_pair = parameters.begin(); current_pair != parameters.end(); current_pair++)
                              {
                                    const Hapy::Pree& pair = *current_pair;
                                    const Hapy::Pree& pair_value = *pair.begin();
                                    const Hapy::Pree& string = *pair_value.begin();
                                    const std::string variable = no_quotes(string.image());
                                    const Hapy::Pree& value = *(pair_value.begin() + 1);

                                    if(m_declarations[variable] == "float")
                                    {
                                          const Hapy::Pree& float_val = *(value.begin() + 1);
                                          k3d::set_property_value(*m_current_shader, variable, k3d::from_string<double>(float_val.image(), 0));
                                    }
                                    else
                                    if(m_declarations[variable] == "color")
                                    {
                                          const Hapy::Pree& float_vals = *(value.begin() + 1);
                                          k3d::set_property_value(*m_current_shader, variable, k3d::from_string<k3d::color>(float_vals.image(), k3d::color(1.0, 1.0, 1.0)));
                                    }
                                    else
                                          std::cerr << debug << "Variable type not declared for " << variable << " : " << m_declarations[variable] << std::endl;
                              }
                        }
                  }
            }
      }
      else
      {
            Hapy::Pree::const_iterator pi = Node.begin();
            for(; pi != Node.end(); pi++)
                  parse_subpree(*pi, Document);
      }

      return;
}

bool rib_reader_implementation::read_file(k3d::idocument& Document, const boost::filesystem::path& FilePath)
{
      // Try to open the input file ...
      boost::filesystem::ifstream rib_file(FilePath);
      if(!rib_file.good())
            {
                  std::cerr << warning << __PRETTY_FUNCTION__ << ": error opening [" << FilePath.native_file_string() << "]" << std::endl;
                  return_val_if_fail(0, false);
            }

      std::string buffer("");
      while(!rib_file.eof())
            {
                  std::string linebuffer;
                  k3d::getline(rib_file, linebuffer);
                  buffer += linebuffer + "\n";
            }

      if(!parser.parse(buffer))
      {
            std::cerr << debug << parser.result().location() << " -> parsing failed" << std::endl;
            return_val_if_fail(0, false);
      }

      // Process parse tree ...
      const Hapy::Pree& main_node = parser.result().pree;
      Hapy::Pree::const_iterator pi = main_node.begin();
      for(; pi != main_node.end(); pi++)
            parse_subpree(*pi, Document);

      return true;
}

k3d::iplugin_factory& rib_reader_factory()
{
      return rib_reader_implementation::get_factory();
}

} // namespace libk3dgeometry



Generated by  Doxygen 1.6.0   Back to index