<commit_before>// Filename: cLwoPolygons.cxx
// Created by:  drose (25Apr01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "cLwoPolygons.h"
#include "lwoToEggConverter.h"
#include "cLwoPoints.h"
#include "cLwoLayer.h"
#include "cLwoSurface.h"

#include <lwoPolygonTags.h>
#include <lwoTags.h>
#include <lwoDiscontinuousVertexMap.h>
#include <eggData.h>
#include <eggPolygon.h>
#include <eggPoint.h>
#include <deg_2_rad.h>

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::add_ptags
//       Access: Public
//  Description: Associates the indicated PolygonTags and Tags with
//               the polygons in this chunk.  This may define features
//               such as per-polygon surfaces, parts, and smoothing
//               groups.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags) {
  if (_tags != (LwoTags *)NULL && _tags != tags) {
    nout << "Multiple Tags fields in effect on the same polygons.\n";
  }
  _tags = tags;

  IffId type = lwo_ptags->_tag_type;

  bool inserted = _ptags.insert(PTags::value_type(type, lwo_ptags)).second;
  if (!inserted) {
    nout << "Multiple polygon tags on the same polygons of type "
         << type << "\n";

  } else {
    if (type == IffId("SURF")) {
      _surf_ptags = lwo_ptags;
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::add_vmad
//       Access: Public
//  Description: Associates the indicated DiscontinousVertexMap with
//               the polygons.  This can be used in conjunction with
//               (or in place of) the VertexMap associated with the
//               points set, to define per-polygon UV's etc.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad) {
  IffId map_type = lwo_vmad->_map_type;
  const string &name = lwo_vmad->_name;

  bool inserted;
  if (map_type == IffId("TXUV")) {
    inserted =
      _txuv.insert(VMad::value_type(name, lwo_vmad)).second;

  } else {
    return;
  }

  if (!inserted) {
    nout << "Multiple discontinous vertex maps on the same polygons of type "
         << map_type << " named " << name << "\n";
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::get_surface
//       Access: Public
//  Description: Returns the surface associated with the given
//               polygon, or NULL if no surface is associated.
////////////////////////////////////////////////////////////////////
CLwoSurface *CLwoPolygons::
get_surface(int polygon_index) const {
  if (_surf_ptags == (LwoPolygonTags *)NULL) {
    // No surface definitions.
    return (CLwoSurface *)NULL;
  }

  if (!_surf_ptags->has_tag(polygon_index)) {
    // The polygon isn't tagged.
    return (CLwoSurface *)NULL;
  }

  int tag_index = _surf_ptags->get_tag(polygon_index);
  if (_tags == (LwoTags *)NULL || tag_index < 0 ||
      tag_index >= _tags->get_num_tags()) {
    // The tag index is out-of-bounds.
    nout << "Invalid polygon tag index " << tag_index << "\n";
    return (CLwoSurface *)NULL;
  }

  string tag = _tags->get_tag(tag_index);

  // Now look up the surface name in the header.
  CLwoSurface *surface = _converter->get_surface(tag);
  if (surface == (CLwoSurface *)NULL) {
    nout << "Unknown surface " << tag << "\n";
    return (CLwoSurface *)NULL;
  }

  return surface;
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::get_uv
//       Access: Public
//  Description: Returns true if there is a UV of the indicated name
//               associated with the given vertex of the indicated
//               polygon, false otherwise.  If true, fills in uv with
//               the value.
//
//               This performs a lookup in the optional
//               "discontinuous" vertex mapping, which provides the
//               ability to map different UV's per each polygon for
//               the same vertex.  If the UV is not defined here, it
//               may also be defined in the standard vertex map, which
//               is associated with the points themselves.
////////////////////////////////////////////////////////////////////
bool CLwoPolygons::
get_uv(const string &uv_name, int pi, int vi, LPoint2f &uv) const {
  VMad::const_iterator ni = _txuv.find(uv_name);
  if (ni == _txuv.end()) {
    return false;
  }

  const LwoDiscontinuousVertexMap *vmad = (*ni).second;
  if (vmad->_dimension != 2) {
    nout << "Unexpected dimension of " << vmad->_dimension
         << " for discontinuous UV map " << uv_name << "\n";
    return false;
  }

  if (!vmad->has_value(pi, vi)) {
    return false;
  }

  PTA_float value = vmad->get_value(pi, vi);

  uv.set(value[0], value[1]);
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::make_egg
//       Access: Public
//  Description: Creates the egg structures associated with this
//               Lightwave object.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
make_egg() {
  // First, we need a temporary group to hold all of the polygons
  // we'll create.
  _egg_group = new EggGroup;

  if (_polygons->_polygon_type == IffId("CURV")) {
    nout << "Ignoring Catmull-Rom splines.\n";

  } else if (_polygons->_polygon_type == IffId("PTCH")) {
    nout << "Ignoring subdivision patches.\n";

  } else if (_polygons->_polygon_type == IffId("MBAL")) {
    nout << "Ignoring metaballs.\n";

  } else if (_polygons->_polygon_type == IffId("BONE")) {
    nout << "Ignoring bones.\n";

  } else if (_polygons->_polygon_type == IffId("FACE")) {
    make_faces();

  } else {
    nout << "Ignoring unknown geometry type " << _polygons->_polygon_type
         << ".\n";
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::connect_egg
//       Access: Public
//  Description: Connects all the egg structures together.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
connect_egg() {
  nassertv(_points->_layer->_egg_group != (EggGroup *)NULL);
  nassertv(_egg_group != (EggGroup *)NULL);
  _points->_layer->_egg_group->steal_children(*_egg_group);
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::make_faces
//       Access: Public
//  Description: Generates "face" polygons, i.e. actual polygons.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
make_faces() {
  float smooth_angle = -1.0;

  int num_polygons = _polygons->get_num_polygons();
  for (int pindex = 0; pindex < num_polygons; pindex++) {
    LwoPolygons::Polygon *poly = _polygons->get_polygon(pindex);
    CLwoSurface *surface = get_surface(pindex);

    bool is_valid = true;

    // Set up the vertices.
    const LwoPoints *points = _points->_points;
    int num_points = points->get_num_points();
    EggVertexPool *egg_vpool = _points->_egg_vpool;

    // We reverse the vertex ordering to compensate for Lightwave's
    // clockwise ordering convention.  We also want to start with the
    // last vertex, so that the first convex angle is the first angle
    // in the EggPolygon (for determining correct normals).
    PT(EggPrimitive) egg_prim;

    if (poly->_vertices.size() == 1) {
      egg_prim = new EggPoint;
    } else {
      egg_prim = new EggPolygon;
    }

    // First, we have to create a temporary vector of vertices for the
    // polygon, so we can possibly adjust the properties of these
    // vertices (like the UV's) in the shader before we create them.
    vector_PT_EggVertex egg_vertices;

    int num_vertices = poly->_vertices.size();
    for (int vi = num_vertices; vi > 0; vi--) {
      int vindex = poly->_vertices[vi % num_vertices];
      if (vindex < 0 || vindex >= num_points) {
        nout << "Invalid vertex index " << vindex << " in polygon.\n";
        is_valid = false;
      } else {
        PT(EggVertex) egg_vertex = new EggVertex;
        LPoint3d pos = LCAST(double, points->get_point(vindex));
        egg_vertex->set_pos(pos);

        // Does the vertex used named UV's?
        if (surface != (CLwoSurface *)NULL && surface->has_named_uvs()) {
          string uv_name = surface->get_uv_name();
          LPoint2f uv;
          if (get_uv(uv_name, pindex, vindex, uv)) {
            // This UV is defined in a "discontinuous" map, that
            // associated a particular UV per each polygon.
            egg_vertex->set_uv(LCAST(double, uv));

          } else if (_points->get_uv(uv_name, vindex, uv)) {
            // The UV does not appear in a discontinuous map, but it
            // is defined in the points set.
            egg_vertex->set_uv(LCAST(double, uv));
          }
        }

        egg_vertices.push_back(egg_vertex);
      }
    }

    if (is_valid) {
      if (surface != (CLwoSurface *)NULL) {
        surface->apply_properties(egg_prim, egg_vertices, smooth_angle);
      }

      // Now add all the vertices officially to the primitive.
      vector_PT_EggVertex::const_iterator evi;
      for (evi = egg_vertices.begin(); evi != egg_vertices.end(); ++evi) {
        EggVertex *egg_vertex = (*evi);
        EggVertex *new_vertex = egg_vpool->create_unique_vertex(*egg_vertex);
        egg_prim->add_vertex(new_vertex);
      }

      // And add the primitive to its parent.
      _egg_group->add_child(egg_prim.p());
    }
  }

  CoordinateSystem cs = _converter->get_egg_data().get_coordinate_system();
  if (smooth_angle > 0.0) {
    _egg_group->recompute_vertex_normals(rad_2_deg(smooth_angle), cs);
  } else {
    _egg_group->recompute_polygon_normals(cs);
  }
}

<commit_msg>expose subdivision patches<commit_after>// Filename: cLwoPolygons.cxx
// Created by:  drose (25Apr01)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
//
// All use of this software is subject to the terms of the Panda 3d
// Software license.  You should have received a copy of this license
// along with this source code; you will also find a current copy of
// the license at http://www.panda3d.org/license.txt .
//
// To contact the maintainers of this program write to
// panda3d@yahoogroups.com .
//
////////////////////////////////////////////////////////////////////

#include "cLwoPolygons.h"
#include "lwoToEggConverter.h"
#include "cLwoPoints.h"
#include "cLwoLayer.h"
#include "cLwoSurface.h"

#include <lwoPolygonTags.h>
#include <lwoTags.h>
#include <lwoDiscontinuousVertexMap.h>
#include <eggData.h>
#include <eggPolygon.h>
#include <eggPoint.h>
#include <deg_2_rad.h>

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::add_ptags
//       Access: Public
//  Description: Associates the indicated PolygonTags and Tags with
//               the polygons in this chunk.  This may define features
//               such as per-polygon surfaces, parts, and smoothing
//               groups.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
add_ptags(const LwoPolygonTags *lwo_ptags, const LwoTags *tags) {
  if (_tags != (LwoTags *)NULL && _tags != tags) {
    nout << "Multiple Tags fields in effect on the same polygons.\n";
  }
  _tags = tags;

  IffId type = lwo_ptags->_tag_type;

  bool inserted = _ptags.insert(PTags::value_type(type, lwo_ptags)).second;
  if (!inserted) {
    nout << "Multiple polygon tags on the same polygons of type "
         << type << "\n";

  } else {
    if (type == IffId("SURF")) {
      _surf_ptags = lwo_ptags;
    }
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::add_vmad
//       Access: Public
//  Description: Associates the indicated DiscontinousVertexMap with
//               the polygons.  This can be used in conjunction with
//               (or in place of) the VertexMap associated with the
//               points set, to define per-polygon UV's etc.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
add_vmad(const LwoDiscontinuousVertexMap *lwo_vmad) {
  IffId map_type = lwo_vmad->_map_type;
  const string &name = lwo_vmad->_name;

  bool inserted;
  if (map_type == IffId("TXUV")) {
    inserted =
      _txuv.insert(VMad::value_type(name, lwo_vmad)).second;

  } else {
    return;
  }

  if (!inserted) {
    nout << "Multiple discontinous vertex maps on the same polygons of type "
         << map_type << " named " << name << "\n";
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::get_surface
//       Access: Public
//  Description: Returns the surface associated with the given
//               polygon, or NULL if no surface is associated.
////////////////////////////////////////////////////////////////////
CLwoSurface *CLwoPolygons::
get_surface(int polygon_index) const {
  if (_surf_ptags == (LwoPolygonTags *)NULL) {
    // No surface definitions.
    return (CLwoSurface *)NULL;
  }

  if (!_surf_ptags->has_tag(polygon_index)) {
    // The polygon isn't tagged.
    return (CLwoSurface *)NULL;
  }

  int tag_index = _surf_ptags->get_tag(polygon_index);
  if (_tags == (LwoTags *)NULL || tag_index < 0 ||
      tag_index >= _tags->get_num_tags()) {
    // The tag index is out-of-bounds.
    nout << "Invalid polygon tag index " << tag_index << "\n";
    return (CLwoSurface *)NULL;
  }

  string tag = _tags->get_tag(tag_index);

  // Now look up the surface name in the header.
  CLwoSurface *surface = _converter->get_surface(tag);
  if (surface == (CLwoSurface *)NULL) {
    nout << "Unknown surface " << tag << "\n";
    return (CLwoSurface *)NULL;
  }

  return surface;
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::get_uv
//       Access: Public
//  Description: Returns true if there is a UV of the indicated name
//               associated with the given vertex of the indicated
//               polygon, false otherwise.  If true, fills in uv with
//               the value.
//
//               This performs a lookup in the optional
//               "discontinuous" vertex mapping, which provides the
//               ability to map different UV's per each polygon for
//               the same vertex.  If the UV is not defined here, it
//               may also be defined in the standard vertex map, which
//               is associated with the points themselves.
////////////////////////////////////////////////////////////////////
bool CLwoPolygons::
get_uv(const string &uv_name, int pi, int vi, LPoint2f &uv) const {
  VMad::const_iterator ni = _txuv.find(uv_name);
  if (ni == _txuv.end()) {
    return false;
  }

  const LwoDiscontinuousVertexMap *vmad = (*ni).second;
  if (vmad->_dimension != 2) {
    nout << "Unexpected dimension of " << vmad->_dimension
         << " for discontinuous UV map " << uv_name << "\n";
    return false;
  }

  if (!vmad->has_value(pi, vi)) {
    return false;
  }

  PTA_float value = vmad->get_value(pi, vi);

  uv.set(value[0], value[1]);
  return true;
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::make_egg
//       Access: Public
//  Description: Creates the egg structures associated with this
//               Lightwave object.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
make_egg() {
  // First, we need a temporary group to hold all of the polygons
  // we'll create.
  _egg_group = new EggGroup;

  if (_polygons->_polygon_type == IffId("CURV")) {
    nout << "Ignoring Catmull-Rom splines.\n";

  } else if (_polygons->_polygon_type == IffId("PTCH")) {
    nout << "Treating subdivision patches as ordinary polygons.\n";
    make_faces();

  } else if (_polygons->_polygon_type == IffId("MBAL")) {
    nout << "Ignoring metaballs.\n";

  } else if (_polygons->_polygon_type == IffId("BONE")) {
    nout << "Ignoring bones.\n";

  } else if (_polygons->_polygon_type == IffId("FACE")) {
    make_faces();

  } else {
    nout << "Ignoring unknown geometry type " << _polygons->_polygon_type
         << ".\n";
  }
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::connect_egg
//       Access: Public
//  Description: Connects all the egg structures together.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
connect_egg() {
  nassertv(_points->_layer->_egg_group != (EggGroup *)NULL);
  nassertv(_egg_group != (EggGroup *)NULL);
  _points->_layer->_egg_group->steal_children(*_egg_group);
}

////////////////////////////////////////////////////////////////////
//     Function: CLwoPolygons::make_faces
//       Access: Public
//  Description: Generates "face" polygons, i.e. actual polygons.
////////////////////////////////////////////////////////////////////
void CLwoPolygons::
make_faces() {
  float smooth_angle = -1.0;

  int num_polygons = _polygons->get_num_polygons();
  for (int pindex = 0; pindex < num_polygons; pindex++) {
    LwoPolygons::Polygon *poly = _polygons->get_polygon(pindex);
    CLwoSurface *surface = get_surface(pindex);

    bool is_valid = true;

    // Set up the vertices.
    const LwoPoints *points = _points->_points;
    int num_points = points->get_num_points();
    EggVertexPool *egg_vpool = _points->_egg_vpool;

    // We reverse the vertex ordering to compensate for Lightwave's
    // clockwise ordering convention.  We also want to start with the
    // last vertex, so that the first convex angle is the first angle
    // in the EggPolygon (for determining correct normals).
    PT(EggPrimitive) egg_prim;

    if (poly->_vertices.size() == 1) {
      egg_prim = new EggPoint;
    } else {
      egg_prim = new EggPolygon;
    }

    // First, we have to create a temporary vector of vertices for the
    // polygon, so we can possibly adjust the properties of these
    // vertices (like the UV's) in the shader before we create them.
    vector_PT_EggVertex egg_vertices;

    int num_vertices = poly->_vertices.size();
    for (int vi = num_vertices; vi > 0; vi--) {
      int vindex = poly->_vertices[vi % num_vertices];
      if (vindex < 0 || vindex >= num_points) {
        nout << "Invalid vertex index " << vindex << " in polygon.\n";
        is_valid = false;
      } else {
        PT(EggVertex) egg_vertex = new EggVertex;
        LPoint3d pos = LCAST(double, points->get_point(vindex));
        egg_vertex->set_pos(pos);

        // Does the vertex used named UV's?
        if (surface != (CLwoSurface *)NULL && surface->has_named_uvs()) {
          string uv_name = surface->get_uv_name();
          LPoint2f uv;
          if (get_uv(uv_name, pindex, vindex, uv)) {
            // This UV is defined in a "discontinuous" map, that
            // associated a particular UV per each polygon.
            egg_vertex->set_uv(LCAST(double, uv));

          } else if (_points->get_uv(uv_name, vindex, uv)) {
            // The UV does not appear in a discontinuous map, but it
            // is defined in the points set.
            egg_vertex->set_uv(LCAST(double, uv));
          }
        }

        egg_vertices.push_back(egg_vertex);
      }
    }

    if (is_valid) {
      if (surface != (CLwoSurface *)NULL) {
        surface->apply_properties(egg_prim, egg_vertices, smooth_angle);
      }

      // Now add all the vertices officially to the primitive.
      vector_PT_EggVertex::const_iterator evi;
      for (evi = egg_vertices.begin(); evi != egg_vertices.end(); ++evi) {
        EggVertex *egg_vertex = (*evi);
        EggVertex *new_vertex = egg_vpool->create_unique_vertex(*egg_vertex);
        egg_prim->add_vertex(new_vertex);
      }

      // And add the primitive to its parent.
      _egg_group->add_child(egg_prim.p());
    }
  }

  CoordinateSystem cs = _converter->get_egg_data().get_coordinate_system();
  if (smooth_angle > 0.0) {
    _egg_group->recompute_vertex_normals(rad_2_deg(smooth_angle), cs);
  } else {
    _egg_group->recompute_polygon_normals(cs);
  }
}

<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2019 Ingo Wald                                                 //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "SemanticParser.h"

namespace pbrt {

  /*! extract 'texture' parameters from shape, and assign to shape */
  void SemanticParser::extractTextures(Shape::SP geom, pbrt::syntactic::Shape::SP shape)
  {
    for (auto param : shape->param) {
      if (param.second->getType() != "texture")
        continue;

      geom->textures[param.first] = findOrCreateTexture(shape->getParamTexture(param.first));//param.second);
    }
  }

  Texture::SP SemanticParser::createTexture_mix(pbrt::syntactic::Texture::SP in)
  {
    MixTexture::SP tex = std::make_shared<MixTexture>();

    if (in->hasParam3f("amount"))
      in->getParam3f(&tex->amount.x,"amount");
    else if (in->hasParam1f("amount"))
      tex->amount = vec3f(in->getParam1f("amount"));
    else
      tex->map_amount = findOrCreateTexture(in->getParamTexture("amount"));

    if (in->hasParamTexture("tex1"))
      tex->tex1 = findOrCreateTexture(in->getParamTexture("tex1"));
    else if (in->hasParam3f("tex1"))
      in->getParam3f(&tex->scale1.x,"tex1");
    else
      tex->scale1 = vec3f(in->getParam1f("tex1"));

    if (in->hasParamTexture("tex2"))
      tex->tex2 = findOrCreateTexture(in->getParamTexture("tex2"));
    else if (in->hasParam3f("tex2"))
      in->getParam3f(&tex->scale2.x,"tex2");
    else
      tex->scale2 = vec3f(in->getParam1f("tex2"));
    return tex;
  }

  Texture::SP SemanticParser::createTexture_scale(pbrt::syntactic::Texture::SP in)
  {
    ScaleTexture::SP tex = std::make_shared<ScaleTexture>();
    if (in->hasParamTexture("tex1"))
      tex->tex1 = findOrCreateTexture(in->getParamTexture("tex1"));
    else if (in->hasParam3f("tex1"))
      in->getParam3f(&tex->scale1.x,"tex1");
    else
      tex->scale1 = vec3f(in->getParam1f("tex1"));

    if (in->hasParamTexture("tex2"))
      tex->tex2 = findOrCreateTexture(in->getParamTexture("tex2"));
    else if (in->hasParam3f("tex2"))
      in->getParam3f(&tex->scale2.x,"tex2");
    else
      tex->scale2 = vec3f(in->getParam1f("tex2"));
    return tex;
  }

  Texture::SP SemanticParser::createTexture_ptex(pbrt::syntactic::Texture::SP in)
  {
    const std::string fileName = in->getParamString("filename");
    if (fileName == "")
      std::cerr << "warning: pbrt image texture, but no filename!?" << std::endl;
    return std::make_shared<PtexFileTexture>(fileName);
  }

  Texture::SP SemanticParser::createTexture_constant(pbrt::syntactic::Texture::SP in)
  {
    ConstantTexture::SP tex = std::make_shared<ConstantTexture>();
    if (in->hasParam1f("value"))
      tex->value = vec3f(in->getParam1f("value"));
    else
      in->getParam3f(&tex->value.x,"value");
    return tex;
  }

  Texture::SP SemanticParser::createTexture_checker(pbrt::syntactic::Texture::SP in)
  {
    CheckerTexture::SP tex = std::make_shared<CheckerTexture>();
    for (auto it : in->param) {
      const std::string name = it.first;
      if (name == "uscale") {
        tex->uScale = in->getParam1f(name);
        continue;
      }
      if (name == "vscale") {
        tex->vScale = in->getParam1f(name);
        continue;
      }
      if (name == "tex1") {
        in->getParam3f(&tex->tex1.x,name);
        continue;
      }
      if (name == "tex2") {
        in->getParam3f(&tex->tex2.x,name);
        continue;
      }
      throw std::runtime_error("unknown checker texture param '"+name+"'");
    }
    return tex;
  }

  /*! do create a track representation of given texture, _without_
    checking whether that was already created */
  Texture::SP SemanticParser::createTextureFrom(pbrt::syntactic::Texture::SP in)
  {
    if (!in) return Texture::SP();

    // ------------------------------------------------------------------
    // switch to type-specialized parsing functions ...
    // ------------------------------------------------------------------
    if (in->mapType == "scale")
      return createTexture_scale(in);
    if (in->mapType == "mix")
      return createTexture_mix(in);
    if (in->mapType == "ptex")
      return createTexture_ptex(in);
    if (in->mapType == "constant")
      return createTexture_constant(in);
    if (in->mapType == "checker")
      return createTexture_checker(in);

    // ------------------------------------------------------------------
    // do small ones right here (todo: move those to separate
    // functions for cleanliness' sake)
    // ------------------------------------------------------------------
    if (in->mapType == "imagemap") {
      const std::string fileName = in->getParamString("filename");
      if (fileName == "")
        std::cerr << "warning: pbrt image texture, but no filename!?" << std::endl;
      return std::make_shared<ImageTexture>(fileName);
    }
    if (in->mapType == "fbm") {
      FbmTexture::SP tex = std::make_shared<FbmTexture>();
      return tex;
    }
    if (in->mapType == "windy") {
      WindyTexture::SP tex = std::make_shared<WindyTexture>();
      return tex;
    }
    if (in->mapType == "marble") {
      MarbleTexture::SP tex = std::make_shared<MarbleTexture>();
      if (in->hasParam1f("scale"))
        tex->scale = in->getParam1f("scale");
      return tex;
    }
    if (in->mapType == "wrinkled") {
      WrinkledTexture::SP tex = std::make_shared<WrinkledTexture>();
      return tex;
    }
    throw std::runtime_error("un-handled pbrt texture type '"+in->toString()+"'");
    return std::make_shared<Texture>();
  }

  Texture::SP SemanticParser::findOrCreateTexture(pbrt::syntactic::Texture::SP in)
  {
    if (!textureMapping[in]) {
      textureMapping[in] = createTextureFrom(in);
    }
    return textureMapping[in];
  }

} // ::pbrt
<commit_msg>bugfix: check_board_, not _checker_<commit_after>// ======================================================================== //
// Copyright 2019 Ingo Wald                                                 //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#include "SemanticParser.h"

namespace pbrt {

  /*! extract 'texture' parameters from shape, and assign to shape */
  void SemanticParser::extractTextures(Shape::SP geom, pbrt::syntactic::Shape::SP shape)
  {
    for (auto param : shape->param) {
      if (param.second->getType() != "texture")
        continue;

      geom->textures[param.first] = findOrCreateTexture(shape->getParamTexture(param.first));//param.second);
    }
  }

  Texture::SP SemanticParser::createTexture_mix(pbrt::syntactic::Texture::SP in)
  {
    MixTexture::SP tex = std::make_shared<MixTexture>();

    if (in->hasParam3f("amount"))
      in->getParam3f(&tex->amount.x,"amount");
    else if (in->hasParam1f("amount"))
      tex->amount = vec3f(in->getParam1f("amount"));
    else
      tex->map_amount = findOrCreateTexture(in->getParamTexture("amount"));

    if (in->hasParamTexture("tex1"))
      tex->tex1 = findOrCreateTexture(in->getParamTexture("tex1"));
    else if (in->hasParam3f("tex1"))
      in->getParam3f(&tex->scale1.x,"tex1");
    else
      tex->scale1 = vec3f(in->getParam1f("tex1"));

    if (in->hasParamTexture("tex2"))
      tex->tex2 = findOrCreateTexture(in->getParamTexture("tex2"));
    else if (in->hasParam3f("tex2"))
      in->getParam3f(&tex->scale2.x,"tex2");
    else
      tex->scale2 = vec3f(in->getParam1f("tex2"));
    return tex;
  }

  Texture::SP SemanticParser::createTexture_scale(pbrt::syntactic::Texture::SP in)
  {
    ScaleTexture::SP tex = std::make_shared<ScaleTexture>();
    if (in->hasParamTexture("tex1"))
      tex->tex1 = findOrCreateTexture(in->getParamTexture("tex1"));
    else if (in->hasParam3f("tex1"))
      in->getParam3f(&tex->scale1.x,"tex1");
    else
      tex->scale1 = vec3f(in->getParam1f("tex1"));

    if (in->hasParamTexture("tex2"))
      tex->tex2 = findOrCreateTexture(in->getParamTexture("tex2"));
    else if (in->hasParam3f("tex2"))
      in->getParam3f(&tex->scale2.x,"tex2");
    else
      tex->scale2 = vec3f(in->getParam1f("tex2"));
    return tex;
  }

  Texture::SP SemanticParser::createTexture_ptex(pbrt::syntactic::Texture::SP in)
  {
    const std::string fileName = in->getParamString("filename");
    if (fileName == "")
      std::cerr << "warning: pbrt image texture, but no filename!?" << std::endl;
    return std::make_shared<PtexFileTexture>(fileName);
  }

  Texture::SP SemanticParser::createTexture_constant(pbrt::syntactic::Texture::SP in)
  {
    ConstantTexture::SP tex = std::make_shared<ConstantTexture>();
    if (in->hasParam1f("value"))
      tex->value = vec3f(in->getParam1f("value"));
    else
      in->getParam3f(&tex->value.x,"value");
    return tex;
  }

  Texture::SP SemanticParser::createTexture_checker(pbrt::syntactic::Texture::SP in)
  {
    CheckerTexture::SP tex = std::make_shared<CheckerTexture>();
    for (auto it : in->param) {
      const std::string name = it.first;
      if (name == "uscale") {
        tex->uScale = in->getParam1f(name);
        continue;
      }
      if (name == "vscale") {
        tex->vScale = in->getParam1f(name);
        continue;
      }
      if (name == "tex1") {
        in->getParam3f(&tex->tex1.x,name);
        continue;
      }
      if (name == "tex2") {
        in->getParam3f(&tex->tex2.x,name);
        continue;
      }
      throw std::runtime_error("unknown checker texture param '"+name+"'");
    }
    return tex;
  }

  /*! do create a track representation of given texture, _without_
    checking whether that was already created */
  Texture::SP SemanticParser::createTextureFrom(pbrt::syntactic::Texture::SP in)
  {
    if (!in) return Texture::SP();

    // ------------------------------------------------------------------
    // switch to type-specialized parsing functions ...
    // ------------------------------------------------------------------
    if (in->mapType == "scale")
      return createTexture_scale(in);
    if (in->mapType == "mix")
      return createTexture_mix(in);
    if (in->mapType == "ptex")
      return createTexture_ptex(in);
    if (in->mapType == "constant")
      return createTexture_constant(in);
    if (in->mapType == "checkerboard")
      return createTexture_checker(in);

    // ------------------------------------------------------------------
    // do small ones right here (todo: move those to separate
    // functions for cleanliness' sake)
    // ------------------------------------------------------------------
    if (in->mapType == "imagemap") {
      const std::string fileName = in->getParamString("filename");
      if (fileName == "")
        std::cerr << "warning: pbrt image texture, but no filename!?" << std::endl;
      return std::make_shared<ImageTexture>(fileName);
    }
    if (in->mapType == "fbm") {
      FbmTexture::SP tex = std::make_shared<FbmTexture>();
      return tex;
    }
    if (in->mapType == "windy") {
      WindyTexture::SP tex = std::make_shared<WindyTexture>();
      return tex;
    }
    if (in->mapType == "marble") {
      MarbleTexture::SP tex = std::make_shared<MarbleTexture>();
      if (in->hasParam1f("scale"))
        tex->scale = in->getParam1f("scale");
      return tex;
    }
    if (in->mapType == "wrinkled") {
      WrinkledTexture::SP tex = std::make_shared<WrinkledTexture>();
      return tex;
    }
    throw std::runtime_error("un-handled pbrt texture type '"+in->toString()+"'");
    return std::make_shared<Texture>();
  }

  Texture::SP SemanticParser::findOrCreateTexture(pbrt::syntactic::Texture::SP in)
  {
    if (!textureMapping[in]) {
      textureMapping[in] = createTextureFrom(in);
    }
    return textureMapping[in];
  }

} // ::pbrt
<|endoftext|>


<commit_before>// - Tested
#define RMM_AAR
#define RMM_CAS
#define RMM_CNSTRCT
#define CRB_FLIPPABLE
#define RMM_JIPMARKERS
#define RMM_LOGBOOK
#define RMM_RECRUITMENT
#define RMM_REVIVE
#define RMM_TASKS
#define CRB_TWNMGR
#define RMM_TYRES
#define R3F_LOGISTICS

// WIP
#define WHB_MULTISPAWN
#define RMM_CASEVAC
//#define GC_PACK_COW
<commit_msg>- Moved modules to stable<commit_after>// - Tested
#define RMM_AAR
#define RMM_CAS
#define RMM_CASEVAC
#define CRB_TWNMGR
#define CRB_FLIPPABLE
#define RMM_JIPMARKERS
#define RMM_LOGBOOK
#define R3F_LOGISTICS
#define RMM_RECRUITMENT
#define RMM_REVIVE
#define RMM_TASKS
#define RMM_TYRES
#define WHB_MULTISPAWN

// WIP
//#define GC_PACK_COW
<|endoftext|>


<commit_before>#include "Platform.hpp"
#include "genome.pb.h"
#include "CellComponent.hpp"
#include "ActivityStats.hpp"
#include "Neuron.hpp"
#include "Branch.hpp"
#include "Synapse.hpp"
#include "Base64.hpp"
#include "Brain.hpp"
#include "SimpleProteinEnvironment.hpp"
#include <time.h>

namespace Elysia {
void testTwoConnectedNeurons() {
    ProteinEnvironment *myProteinEnvironment= new SimpleProteinEnvironment();

	Brain *brain= new Brain(myProteinEnvironment);
	FILE *dendriteTree=NULL;
	dendriteTree = fopen("Dendritic_Tree.txt", "w");
	std::vector<Neuron *> createdList;
	int neuronNumber = 2;
	for(int i=0;i<neuronNumber;i++){
        Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
        Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
        Genome::TemporalBoundingBox *targetbb=gene.add_bounds();
        sourcebb->set_minx(i);
        sourcebb->set_miny(i);
        sourcebb->set_minz(i);

        sourcebb->set_maxx(i);
        sourcebb->set_maxy(i);
        sourcebb->set_maxz(i);

        targetbb->set_minx(i);
        targetbb->set_miny(i);
        targetbb->set_minz(i);

        targetbb->set_maxx(1-i);
        targetbb->set_maxy(1-i);
        targetbb->set_maxz(2);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = 1;
		Neuron *n;
		srand(time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
		}
	for(float i=0;i<neuronNumber;i++){
		Neuron *n = createdList[i];
        n->developSynapse(n->getActivityStats());
        size_t parent;
        parent = 0;
        n->visualizeTree(dendriteTree, parent);
		//const Vector3f &location):  mNeuronLocation(location){));
	}
	for(int j=0; j<10; j++){
		for(float i=0;i<neuronNumber;i++){
			Neuron *n = createdList[i];
			if(j== 0 && i==0){n->activateComponent(*brain,100);}
			//if(j== 2){brain->inactivateNeuron(n);}
			n->tick();
		//const Vector3f &location):  mNeuronLocation(location){));
		}

		brain ->tick();
	}
	fclose(dendriteTree);
    delete brain;
}

void testDevelopment(){
	ProteinEnvironment *myProteinEnvironment= new SimpleProteinEnvironment();

	Brain *brain= new Brain(myProteinEnvironment);
	FILE *dendriteTree=NULL;
	dendriteTree = fopen("Development_Tree.txt", "w");
	std::vector<Neuron *> createdList;
	int neuronNumber = 3;

	for(int i=0;i<neuronNumber;i++){
        Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
        Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
        Genome::TemporalBoundingBox *targetbb=gene.add_target_region();
        sourcebb->set_minx(50+i);
        sourcebb->set_miny(50+i);
        sourcebb->set_minz(50+i);

        sourcebb->set_maxx(150+i);
        sourcebb->set_maxy(150+i);
        sourcebb->set_maxz(150+i);

        targetbb->set_minx(i);
        targetbb->set_miny(i);
        targetbb->set_minz(i);

        targetbb->set_maxx(i+1);
        targetbb->set_maxy(i+1);
        targetbb->set_maxz(i+1);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = i;
		Neuron *n;
		srand(time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
	}

		for(int i=100;i<100+neuronNumber;i++){
        Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
        Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
        Genome::TemporalBoundingBox *targetbb=gene.add_target_region();
        sourcebb->set_minx(0);
        sourcebb->set_miny(0);
        sourcebb->set_minz(0);

        sourcebb->set_maxx(20);
        sourcebb->set_maxy(20);
        sourcebb->set_maxz(20);

        targetbb->set_minx(i);
        targetbb->set_miny(i);
        targetbb->set_minz(i);

        targetbb->set_maxx(i+1);
        targetbb->set_maxy(i+1);
        targetbb->set_maxz(i+1);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = i;
		Neuron *n;
		srand(time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
	}

	for(float i=0;i<2*neuronNumber;i++){
		Neuron *n = createdList[i];
        n->developSynapse(n->getActivityStats());
        size_t parent;
        parent = 0;
        n->visualizeTree(dendriteTree, parent);
		//const Vector3f &location):  mNeuronLocation(location){));
	}
	for(int j=0; j<10; j++){
		for(float i=0;i<neuronNumber;i++){
			Neuron *n = createdList[i];
			if(j==0 && i==0){n->activateComponent(*brain,100);}
			n->tick();
		//const Vector3f &location):  mNeuronLocation(location){));
		}

		brain ->tick();
	}
	fclose(dendriteTree);
    delete brain;
}

void testResultHelper(const std::vector<std::pair<Elysia::Genome::Effect, float> >&combinedResult, float*grow_leaf_count,float*grow_neuron_count,float*other_count){
   using namespace Elysia::Genome;
    *grow_neuron_count=0;
    *grow_leaf_count=0;
    *other_count=0;
    for (size_t i=0;i<combinedResult.size();++i) {
       switch(combinedResult[i].first) {
         case GROW_NEURON:
           *grow_neuron_count+=combinedResult[i].second;
           break;
         case GROW_LEAF:
           *grow_leaf_count+=combinedResult[i].second;
           break;
         default:
           *other_count+=combinedResult[i].second;
           break;
       }
   }

}

void testProteinEnvironment() {
   using namespace Elysia::Genome;
   Elysia::Genome::Genome twoOverlappingGenes;
   Elysia::Genome::Chromosome *father=twoOverlappingGenes.mutable_fathers();
   Elysia::Genome::Gene firstGene;
   Elysia::Genome::Protein firstProtein;
   firstProtein.set_protein_code(GROW_NEURON);//so we can easily identify where
   firstProtein.set_density(0.125);
   Elysia::Genome::Protein firstAuxProtein;
   firstAuxProtein.set_protein_code(GROW_LEAF);//so we see that they are additive
   firstAuxProtein.set_density(0.25);
   *firstGene.add_external_proteins()=firstProtein;
   assert(firstGene.external_proteins(0).protein_code()==GROW_NEURON);
   *firstGene.add_external_proteins()=firstAuxProtein;
   assert(firstGene.external_proteins(1).protein_code()==GROW_LEAF);
   Elysia::Genome::TemporalBoundingBox firstRegion;
   firstRegion.set_minx(0);
   firstRegion.set_miny(0);
   firstRegion.set_minz(0);
   firstRegion.set_maxx(2);
   firstRegion.set_maxy(2);
   firstRegion.set_maxz(2);

   *firstGene.add_bounds()=firstRegion;

   Elysia::Genome::TemporalBoundingBox firstTargetRegion;
   firstTargetRegion.set_minx(5);
   firstTargetRegion.set_miny(5);
   firstTargetRegion.set_minz(5);
   firstTargetRegion.set_maxx(8);
   firstTargetRegion.set_maxy(8);
   firstTargetRegion.set_maxz(8);

   *firstGene.add_target_region()=firstTargetRegion;
   Elysia::Genome::Gene secondGene;
   Elysia::Genome::Protein secondProtein;
   secondProtein.set_protein_code(GROW_LEAF);
   secondProtein.set_density(0.5);
   *secondGene.add_external_proteins()=secondProtein;
   Elysia::Genome::TemporalBoundingBox secondRegion;
   secondRegion.set_minx(-1);
   secondRegion.set_miny(-1);
   secondRegion.set_minz(-1);
   secondRegion.set_maxx(1);
   secondRegion.set_maxy(1);
   secondRegion.set_maxz(1);
   *secondGene.add_bounds()=secondRegion;

   Elysia::Genome::TemporalBoundingBox secondTargetRegion;
   secondTargetRegion.set_minx(-5);
   secondTargetRegion.set_miny(-5);
   secondTargetRegion.set_minz(-5);
   secondTargetRegion.set_maxx(3);
   secondTargetRegion.set_maxy(3);
   secondTargetRegion.set_maxz(3);

   *secondGene.add_target_region()=secondTargetRegion;

   *father->add_genes()=firstGene;
   *father->add_genes()=secondGene;

   ProteinEnvironment * pe=new SimpleProteinEnvironment;
   pe->initialize(twoOverlappingGenes);
   std::vector<std::pair<Elysia::Genome::Effect, float> > combinedResult=pe->getCompleteProteinDensity(Vector3f(.5,.5,0));
   //check that firstResult matches expectations
   std::vector<std::pair<Elysia::Genome::Effect, float> > firstResult=pe->getCompleteProteinDensity(Vector3f(1.5,1.5,0));
   //check that secondResult matches expectations
   std::vector<std::pair<Elysia::Genome::Effect, float> > secondResult=pe->getCompleteProteinDensity(Vector3f(-.5,-.5,0));
   float grow_leaf_count=0;
   float grow_neuron_count=0;
   float other_count=0;

   testResultHelper(combinedResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.75);
   assert(grow_neuron_count==.125);
   assert(other_count==0);

   testResultHelper(firstResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.25);
   assert(grow_neuron_count==.125);
   assert(other_count==0);

   testResultHelper(secondResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.5);
   assert(grow_neuron_count==0);
   assert(other_count==0);
   //return;//UNCOMMENT TO GET FAILING TEST
   const Gene * grow_neuron_gene = &pe->retrieveGene(Vector3f(0.5,0.5,0),
                                              GROW_NEURON);
   const Gene * combined_grow_leaf_gene = &pe->retrieveGene(Vector3f(0.5,0.5,0),
                                                     GROW_LEAF);
   const Gene * first_grow_leaf_gene = &pe->retrieveGene(Vector3f(1.5,1.5,0),
                                                  GROW_LEAF);
   const Gene * second_grow_leaf_gene = &pe->retrieveGene(Vector3f(-0.5,-0.5,0),
                                                   GROW_LEAF);
   assert(grow_neuron_gene->target_region(0).minx()==5);

   assert(combined_grow_leaf_gene->target_region(0).minx()==5||combined_grow_leaf_gene->target_region(0).minx()==-5);
   assert(first_grow_leaf_gene->target_region(0).minx()==5);
   assert(second_grow_leaf_gene->target_region(0).minx()==-5);

   delete pe;
}

}

int runtest(){
    //Elysia::testTwoConnectedNeurons();
	Elysia::testDevelopment();
    Elysia::testProteinEnvironment();
    if (0) for (int i=0;i<30000;++i) {
        Elysia::Brain b(new Elysia::SimpleProteinEnvironment);
//        usleep(10);
    }
	//getchar();
	return 1;

}
<commit_msg>Did a few small hacks to fix the torrent of warnings this thing causes upon compile<commit_after>#include "Platform.hpp"
#include "genome.pb.h"
#include "CellComponent.hpp"
#include "ActivityStats.hpp"
#include "Neuron.hpp"
#include "Branch.hpp"
#include "Synapse.hpp"
#include "Base64.hpp"
#include "Brain.hpp"
#include "SimpleProteinEnvironment.hpp"
#include <time.h>

namespace Elysia {
void testTwoConnectedNeurons() {
    ProteinEnvironment *myProteinEnvironment= new SimpleProteinEnvironment();

	Brain *brain= new Brain(myProteinEnvironment);
	FILE *dendriteTree=NULL;
	dendriteTree = fopen("Dendritic_Tree.txt", "w");
	std::vector<Neuron *> createdList;
	int neuronNumber = 2;
	for(int j=0;j<neuronNumber;j++){
		float i = (float)j;		// doing this little hack gets rid of a ton of warnings in Visual C++
        Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
        Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
        Genome::TemporalBoundingBox *targetbb=gene.add_bounds();
        sourcebb->set_minx(i);
        sourcebb->set_miny(i);
        sourcebb->set_minz(i);

        sourcebb->set_maxx(i);
        sourcebb->set_maxy(i);
        sourcebb->set_maxz(i);

        targetbb->set_minx(i);
        targetbb->set_miny(i);
        targetbb->set_minz(i);

        targetbb->set_maxx(1.0f-i);
        targetbb->set_maxy(1.0f-i);
        targetbb->set_maxz(2);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = 1;
		Neuron *n;
		srand((int)time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
		}
	for(float i=0;i<neuronNumber;i++){
		Neuron *n = createdList[(int)i];
        n->developSynapse(n->getActivityStats());
        size_t parent;
        parent = 0;
        n->visualizeTree(dendriteTree, parent);
		//const Vector3f &location):  mNeuronLocation(location){));
	}
	for(int j=0; j<10; j++){
		for(float i=0;i<neuronNumber;i++){
			Neuron *n = createdList[(int)i];
			if(j==0 && (int)i==0){n->activateComponent(*brain,100);}
			//if(j== 2){brain->inactivateNeuron(n);}
			n->tick();
		//const Vector3f &location):  mNeuronLocation(location){));
		}

		brain ->tick();
	}
	fclose(dendriteTree);
    delete brain;
}

void testDevelopment(){
	ProteinEnvironment *myProteinEnvironment= new SimpleProteinEnvironment();

	Brain *brain= new Brain(myProteinEnvironment);
	FILE *dendriteTree=NULL;
	dendriteTree = fopen("Development_Tree.txt", "w");
	std::vector<Neuron *> createdList;
	int neuronNumber = 3;

	for(int j=0;j<neuronNumber;j++){
		float i = (float)j;	// hack to get rid of some warnings
        Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
        Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
        Genome::TemporalBoundingBox *targetbb=gene.add_target_region();
        sourcebb->set_minx(50.0f+i);
        sourcebb->set_miny(50.0f+i);
        sourcebb->set_minz(50.0f+i);

        sourcebb->set_maxx(150.0f+i);
        sourcebb->set_maxy(150.0f+i);
        sourcebb->set_maxz(150.0f+i);

        targetbb->set_minx(i);
        targetbb->set_miny(i);
        targetbb->set_minz(i);

        targetbb->set_maxx(i+1);
        targetbb->set_maxy(i+1);
        targetbb->set_maxz(i+1);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = i;
		Neuron *n;
		srand((int)time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
	}

	for(int j=100;j<100+neuronNumber;j++){
		float i = (float)j;
		Genome::Gene gene;//FIXME set source and target regions to match the desired behavior
		Genome::TemporalBoundingBox *sourcebb=gene.add_bounds();
		Genome::TemporalBoundingBox *targetbb=gene.add_target_region();
		sourcebb->set_minx(0);
		sourcebb->set_miny(0);
		sourcebb->set_minz(0);

	    sourcebb->set_maxx(20);
        sourcebb->set_maxy(20);
		sourcebb->set_maxz(20);

		targetbb->set_minx(i);
		targetbb->set_miny(i);
		targetbb->set_minz(i);

		targetbb->set_maxx(i+1);
		targetbb->set_maxy(i+1);
		targetbb->set_maxz(i+1);

		Vector3f v;
		v.x = i;
		v.y = i;
		v.z = i;
		Neuron *n;
		srand((int)time(NULL));
		brain->mAllNeurons.insert(n = new Neuron(brain, 2, 3, 4, v,gene));
		createdList.push_back(n);
	}

	for(float i=0;i<2*neuronNumber;i++){
		Neuron *n = createdList[(int)i];
        n->developSynapse(n->getActivityStats());
        size_t parent;
        parent = 0;
        n->visualizeTree(dendriteTree, parent);
		//const Vector3f &location):  mNeuronLocation(location){));
	}
	for(int j=0; j<10; j++){
		for(float i=0;i<neuronNumber;i++){
			Neuron *n = createdList[(int)i];
			if(j==0 && (int)i==0){n->activateComponent(*brain,100);}
			n->tick();
		//const Vector3f &location):  mNeuronLocation(location){));
		}

		brain ->tick();
	}
	fclose(dendriteTree);
    delete brain;
}

void testResultHelper(const std::vector<std::pair<Elysia::Genome::Effect, float> >&combinedResult, float*grow_leaf_count,float*grow_neuron_count,float*other_count){
   using namespace Elysia::Genome;
    *grow_neuron_count=0;
    *grow_leaf_count=0;
    *other_count=0;
    for (size_t i=0;i<combinedResult.size();++i) {
       switch(combinedResult[i].first) {
         case GROW_NEURON:
           *grow_neuron_count+=combinedResult[i].second;
           break;
         case GROW_LEAF:
           *grow_leaf_count+=combinedResult[i].second;
           break;
         default:
           *other_count+=combinedResult[i].second;
           break;
       }
   }

}

void testProteinEnvironment() {
   using namespace Elysia::Genome;
   Elysia::Genome::Genome twoOverlappingGenes;
   Elysia::Genome::Chromosome *father=twoOverlappingGenes.mutable_fathers();
   Elysia::Genome::Gene firstGene;
   Elysia::Genome::Protein firstProtein;
   firstProtein.set_protein_code(GROW_NEURON);//so we can easily identify where
   firstProtein.set_density(0.125);
   Elysia::Genome::Protein firstAuxProtein;
   firstAuxProtein.set_protein_code(GROW_LEAF);//so we see that they are additive
   firstAuxProtein.set_density(0.25);
   *firstGene.add_external_proteins()=firstProtein;
   assert(firstGene.external_proteins(0).protein_code()==GROW_NEURON);
   *firstGene.add_external_proteins()=firstAuxProtein;
   assert(firstGene.external_proteins(1).protein_code()==GROW_LEAF);
   Elysia::Genome::TemporalBoundingBox firstRegion;
   firstRegion.set_minx(0);
   firstRegion.set_miny(0);
   firstRegion.set_minz(0);
   firstRegion.set_maxx(2);
   firstRegion.set_maxy(2);
   firstRegion.set_maxz(2);

   *firstGene.add_bounds()=firstRegion;

   Elysia::Genome::TemporalBoundingBox firstTargetRegion;
   firstTargetRegion.set_minx(5);
   firstTargetRegion.set_miny(5);
   firstTargetRegion.set_minz(5);
   firstTargetRegion.set_maxx(8);
   firstTargetRegion.set_maxy(8);
   firstTargetRegion.set_maxz(8);

   *firstGene.add_target_region()=firstTargetRegion;
   Elysia::Genome::Gene secondGene;
   Elysia::Genome::Protein secondProtein;
   secondProtein.set_protein_code(GROW_LEAF);
   secondProtein.set_density(0.5);
   *secondGene.add_external_proteins()=secondProtein;
   Elysia::Genome::TemporalBoundingBox secondRegion;
   secondRegion.set_minx(-1);
   secondRegion.set_miny(-1);
   secondRegion.set_minz(-1);
   secondRegion.set_maxx(1);
   secondRegion.set_maxy(1);
   secondRegion.set_maxz(1);
   *secondGene.add_bounds()=secondRegion;

   Elysia::Genome::TemporalBoundingBox secondTargetRegion;
   secondTargetRegion.set_minx(-5);
   secondTargetRegion.set_miny(-5);
   secondTargetRegion.set_minz(-5);
   secondTargetRegion.set_maxx(3);
   secondTargetRegion.set_maxy(3);
   secondTargetRegion.set_maxz(3);

   *secondGene.add_target_region()=secondTargetRegion;

   *father->add_genes()=firstGene;
   *father->add_genes()=secondGene;

   ProteinEnvironment * pe=new SimpleProteinEnvironment;
   pe->initialize(twoOverlappingGenes);
   std::vector<std::pair<Elysia::Genome::Effect, float> > combinedResult=pe->getCompleteProteinDensity(Vector3f(.5,.5,0));
   //check that firstResult matches expectations
   std::vector<std::pair<Elysia::Genome::Effect, float> > firstResult=pe->getCompleteProteinDensity(Vector3f(1.5,1.5,0));
   //check that secondResult matches expectations
   std::vector<std::pair<Elysia::Genome::Effect, float> > secondResult=pe->getCompleteProteinDensity(Vector3f(-.5,-.5,0));
   float grow_leaf_count=0;
   float grow_neuron_count=0;
   float other_count=0;

   testResultHelper(combinedResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.75);
   assert(grow_neuron_count==.125);
   assert(other_count==0);

   testResultHelper(firstResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.25);
   assert(grow_neuron_count==.125);
   assert(other_count==0);

   testResultHelper(secondResult,&grow_leaf_count,&grow_neuron_count,&other_count);
   assert(grow_leaf_count==.5);
   assert(grow_neuron_count==0);
   assert(other_count==0);
   //return;//UNCOMMENT TO GET FAILING TEST
   const Gene * grow_neuron_gene = &pe->retrieveGene(Vector3f(0.5,0.5,0),
                                              GROW_NEURON);
   const Gene * combined_grow_leaf_gene = &pe->retrieveGene(Vector3f(0.5,0.5,0),
                                                     GROW_LEAF);
   const Gene * first_grow_leaf_gene = &pe->retrieveGene(Vector3f(1.5,1.5,0),
                                                  GROW_LEAF);
   const Gene * second_grow_leaf_gene = &pe->retrieveGene(Vector3f(-0.5,-0.5,0),
                                                   GROW_LEAF);
   assert(grow_neuron_gene->target_region(0).minx()==5);

   assert(combined_grow_leaf_gene->target_region(0).minx()==5||combined_grow_leaf_gene->target_region(0).minx()==-5);
   assert(first_grow_leaf_gene->target_region(0).minx()==5);
   assert(second_grow_leaf_gene->target_region(0).minx()==-5);

   delete pe;
}

}

int runtest(){
    //Elysia::testTwoConnectedNeurons();
	Elysia::testDevelopment();
    Elysia::testProteinEnvironment();
    if (0) for (int i=0;i<30000;++i) {
        Elysia::Brain b(new Elysia::SimpleProteinEnvironment);
//        usleep(10);
    }
	//getchar();
	return 1;

}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------
//
// CASROS: Component-based Architecture for Safe Robotic Systems
//
// Copyright (C) 2012-2014 Min Yang Jung and Peter Kazanzides
//
//------------------------------------------------------------------------
//
// Created on   : Jul 7, 2012
// Last revision: Aug 6, 2014
// Author       : Min Yang Jung (myj@jhu.edu)
// Github       : https://github.com/minyang/casros
//
#include "event.h"

using namespace SF;

Event::Event(const std::string     & name,
             unsigned int            severity,
             const TransitionsType & transitions,
             const std::string     & what)
    : Name(name), Severity(severity), Transitions(transitions), Timestamp(0), What(what)
{
    memset(TransitionMask, 0, TOTAL_NUMBER_OF_STATES * TOTAL_NUMBER_OF_STATES);
#define N 0
#define W 1
#define E 2
    // Counters to check if this event has multiple next states for one current state
    int fromN = 0, fromW = 0, fromE = 0;
    for (size_t i = 0; i < Transitions.size(); ++i) {
        switch (Transitions[i]) {
        case State::NORMAL_TO_WARNING: TransitionMask[N][W] = true; ++fromN; break;
        case State::NORMAL_TO_ERROR  : TransitionMask[N][E] = true; ++fromN; break;
        case State::WARNING_TO_NORMAL: TransitionMask[W][N] = true; ++fromW; break;
        case State::WARNING_TO_ERROR : TransitionMask[W][E] = true; ++fromW; break;
        case State::ERROR_TO_WARNING : TransitionMask[E][W] = true; ++fromE; break;
        case State::ERROR_TO_NORMAL  : TransitionMask[E][N] = true; ++fromE; break;
        default: continue;
        }
    }
#if 0 // check this out later when working on sanity check on event spec file
    if (fromN >= 2 || fromW >= 2 || fromE >= 2) {
        SFLOG_ERROR << "Event transition error: event \"" << Name << "\" has multiple next states" << std::endl;
        SFLOG_ERROR << (int) TransitionMask[N][N] << " " << (int) TransitionMask[N][W] << " " << (int) TransitionMask[N][E] << std::endl;
        SFLOG_ERROR << (int) TransitionMask[W][N] << " " << (int) TransitionMask[W][W] << " " << (int) TransitionMask[W][E] << std::endl;
        SFLOG_ERROR << (int) TransitionMask[E][N] << " " << (int) TransitionMask[E][W] << " " << (int) TransitionMask[E][E] << std::endl;
        throw("Event error");
    }
#endif

#undef N
#undef W
#undef E
}

State::TransitionType Event::GetTransition(State::StateType currentState) const
{
    switch (currentState) {
    case State::NORMAL:
        // Preference on more severe state
        if (TransitionMask[State::NORMAL][State::ERROR])
            return State::NORMAL_TO_ERROR;
        else if (TransitionMask[State::NORMAL][State::WARNING])
            return State::NORMAL_TO_WARNING;
        break;
    case State::WARNING:
        // TODO: W2N and W2E can't be in the same event transition spec
        if (TransitionMask[State::WARNING][State::NORMAL])
            return State::WARNING_TO_NORMAL;
        else if (TransitionMask[State::WARNING][State::ERROR])
            return State::WARNING_TO_ERROR;
        break;
    case State::ERROR:
        if (TransitionMask[State::ERROR][State::NORMAL])
            return State::ERROR_TO_NORMAL;
        else if (TransitionMask[State::ERROR][State::WARNING])
            return State::ERROR_TO_WARNING;
        break;
    default:
        return State::INVALID_TRANSITION;
    }

    // Check no-transition case
    switch (currentState) {
    case State::NORMAL:
        if (TransitionMask[State::WARNING][State::NORMAL] ||
            TransitionMask[State::ERROR][State::NORMAL])
            return State::NO_TRANSITION;
        break;
    case State::WARNING:
        if (TransitionMask[State::NORMAL][State::WARNING] ||
            TransitionMask[State::ERROR][State::WARNING])
            return State::NO_TRANSITION;
        break;
    case State::ERROR:
        if (TransitionMask[State::NORMAL][State::ERROR] ||
            TransitionMask[State::WARNING][State::ERROR])
            return State::NO_TRANSITION;
    }

    return State::INVALID_TRANSITION;
}

void Event::ToStream(std::ostream & os) const
{
    os << Name << ": " << Severity << ", [ ";

    for (size_t i = 0; i < Transitions.size(); ++i) {
        if (i > 0)
            os << " ";
        switch (Transitions[i]) {
        case State::NORMAL_TO_ERROR  : os << "N2E"; break;
        case State::ERROR_TO_NORMAL  : os << "E2N"; break;
        case State::NORMAL_TO_WARNING: os << "N2W"; break;
        case State::WARNING_TO_NORMAL: os << "W2N"; break;
        case State::WARNING_TO_ERROR : os << "W2E"; break;
        case State::ERROR_TO_WARNING : os << "E2W"; break;
        default:                       os << "INVALID";
        }
    }
    os << " ]";

    if (What.size())
        os << ", " << What;
}

const JSON::JSONVALUE Event::SerializeJSON(bool includeStateTransition) const
{
    JSON _json;
    JSON::JSONVALUE & json = _json.GetRoot();
    json["name"] = Name;
    json["severity"] = Severity;
    json["timestamp"] = Timestamp;
    if (What.size())
        json["what"] = What;

    if (includeStateTransition)
        for (size_t i = 0; i < Transitions.size(); ++i) {
            switch (Transitions[i]) {
            case State::NORMAL_TO_ERROR  : json["state_transition"][i] = "N2E"; break;
            case State::ERROR_TO_NORMAL  : json["state_transition"][i] = "E2N"; break;
            case State::NORMAL_TO_WARNING: json["state_transition"][i] = "N2W"; break;
            case State::WARNING_TO_NORMAL: json["state_transition"][i] = "W2N"; break;
            case State::WARNING_TO_ERROR : json["state_transition"][i] = "W2E"; break;
            case State::ERROR_TO_WARNING : json["state_transition"][i] = "E2W"; break;
            default:                       json["state_transition"][i] = "INVALID";
            }
        }

    return json;
}

const std::string Event::SerializeString(bool includeStateTransition) const
{
    return JSON::GetJSONString(SerializeString(includeStateTransition));
}

<commit_msg>minor update<commit_after>//------------------------------------------------------------------------
//
// CASROS: Component-based Architecture for Safe Robotic Systems
//
// Copyright (C) 2012-2014 Min Yang Jung and Peter Kazanzides
//
//------------------------------------------------------------------------
//
// Created on   : Jul 7, 2012
// Last revision: Aug 6, 2014
// Author       : Min Yang Jung (myj@jhu.edu)
// Github       : https://github.com/minyang/casros
//
#include "event.h"

using namespace SF;

Event::Event(const std::string     & name,
             unsigned int            severity,
             const TransitionsType & transitions,
             const std::string     & what)
    : Name(name), Severity(severity), Transitions(transitions), Timestamp(0), What(what)
{
    memset(TransitionMask, 0, TOTAL_NUMBER_OF_STATES * TOTAL_NUMBER_OF_STATES);
#define N 0
#define W 1
#define E 2
    // Counters to check if this event has multiple next states for one current state
    int fromN = 0, fromW = 0, fromE = 0;
    for (size_t i = 0; i < Transitions.size(); ++i) {
        switch (Transitions[i]) {
        case State::NORMAL_TO_WARNING: TransitionMask[N][W] = true; ++fromN; break;
        case State::NORMAL_TO_ERROR  : TransitionMask[N][E] = true; ++fromN; break;
        case State::WARNING_TO_NORMAL: TransitionMask[W][N] = true; ++fromW; break;
        case State::WARNING_TO_ERROR : TransitionMask[W][E] = true; ++fromW; break;
        case State::ERROR_TO_WARNING : TransitionMask[E][W] = true; ++fromE; break;
        case State::ERROR_TO_NORMAL  : TransitionMask[E][N] = true; ++fromE; break;
        default: continue;
        }
    }
#if 0 // check this out later when working on sanity check on event spec file
    if (fromN >= 2 || fromW >= 2 || fromE >= 2) {
        SFLOG_ERROR << "Event transition error: event \"" << Name << "\" has multiple next states" << std::endl;
        SFLOG_ERROR << (int) TransitionMask[N][N] << " " << (int) TransitionMask[N][W] << " " << (int) TransitionMask[N][E] << std::endl;
        SFLOG_ERROR << (int) TransitionMask[W][N] << " " << (int) TransitionMask[W][W] << " " << (int) TransitionMask[W][E] << std::endl;
        SFLOG_ERROR << (int) TransitionMask[E][N] << " " << (int) TransitionMask[E][W] << " " << (int) TransitionMask[E][E] << std::endl;
        throw("Event error");
    }
#endif

#undef N
#undef W
#undef E
}

State::TransitionType Event::GetTransition(State::StateType currentState) const
{
    switch (currentState) {
    case State::NORMAL:
        // Preference on more severe state
        if (TransitionMask[State::NORMAL][State::ERROR])
            return State::NORMAL_TO_ERROR;
        else if (TransitionMask[State::NORMAL][State::WARNING])
            return State::NORMAL_TO_WARNING;
        break;
    case State::WARNING:
        // TODO: W2N and W2E can't be in the same event transition spec
        if (TransitionMask[State::WARNING][State::NORMAL])
            return State::WARNING_TO_NORMAL;
        else if (TransitionMask[State::WARNING][State::ERROR])
            return State::WARNING_TO_ERROR;
        break;
    case State::ERROR:
        if (TransitionMask[State::ERROR][State::NORMAL])
            return State::ERROR_TO_NORMAL;
        else if (TransitionMask[State::ERROR][State::WARNING])
            return State::ERROR_TO_WARNING;
        break;
    default:
        return State::INVALID_TRANSITION;
    }

    // Check no-transition case
    switch (currentState) {
    case State::NORMAL:
        if (TransitionMask[State::WARNING][State::NORMAL] ||
            TransitionMask[State::ERROR][State::NORMAL])
            return State::NO_TRANSITION;
        break;
    case State::WARNING:
        if (TransitionMask[State::NORMAL][State::WARNING] ||
            TransitionMask[State::ERROR][State::WARNING])
            return State::NO_TRANSITION;
        break;
    case State::ERROR:
        if (TransitionMask[State::NORMAL][State::ERROR] ||
            TransitionMask[State::WARNING][State::ERROR])
            return State::NO_TRANSITION;
    default:
        return State::INVALID_TRANSITION;
    }

    return State::INVALID_TRANSITION;
}

void Event::ToStream(std::ostream & os) const
{
    os << Name << ": " << Severity << ", [ ";

    for (size_t i = 0; i < Transitions.size(); ++i) {
        if (i > 0)
            os << " ";
        switch (Transitions[i]) {
        case State::NORMAL_TO_ERROR  : os << "N2E"; break;
        case State::ERROR_TO_NORMAL  : os << "E2N"; break;
        case State::NORMAL_TO_WARNING: os << "N2W"; break;
        case State::WARNING_TO_NORMAL: os << "W2N"; break;
        case State::WARNING_TO_ERROR : os << "W2E"; break;
        case State::ERROR_TO_WARNING : os << "E2W"; break;
        default:                       os << "INVALID";
        }
    }
    os << " ]";

    if (What.size())
        os << ", " << What;
}

const JSON::JSONVALUE Event::SerializeJSON(bool includeStateTransition) const
{
    JSON _json;
    JSON::JSONVALUE & json = _json.GetRoot();
    json["name"] = Name;
    json["severity"] = Severity;
    json["timestamp"] = Timestamp;
    if (What.size())
        json["what"] = What;

    if (includeStateTransition)
        for (size_t i = 0; i < Transitions.size(); ++i) {
            switch (Transitions[i]) {
            case State::NORMAL_TO_ERROR  : json["state_transition"][i] = "N2E"; break;
            case State::ERROR_TO_NORMAL  : json["state_transition"][i] = "E2N"; break;
            case State::NORMAL_TO_WARNING: json["state_transition"][i] = "N2W"; break;
            case State::WARNING_TO_NORMAL: json["state_transition"][i] = "W2N"; break;
            case State::WARNING_TO_ERROR : json["state_transition"][i] = "W2E"; break;
            case State::ERROR_TO_WARNING : json["state_transition"][i] = "E2W"; break;
            default:                       json["state_transition"][i] = "INVALID";
            }
        }

    return json;
}

const std::string Event::SerializeString(bool includeStateTransition) const
{
    return JSON::GetJSONString(SerializeString(includeStateTransition));
}

<|endoftext|>


<commit_before><commit_msg>[clingutils] improve TMetaUtils::GetCppName #7423<commit_after><|endoftext|>