<commit_before>
#include "cssysdef.h"
#include "csutil/csobject.h"
#include "csutil/typedvec.h"
#include "csutil/objiter.h"
#include "csgeom/transfrm.h"
#include "isys/plugin.h"
#include "imesh/crossbld.h"
#include "imesh/mdldata.h"
#include "imesh/thing/thing.h"
#include "imesh/thing/polygon.h"
#include "imesh/sprite3d.h"
#include "imesh/object.h"
#include "iengine/engine.h"
#include "iengine/mesh.h"

SCF_DECLARE_FAST_INTERFACE (iModelDataObject);
SCF_DECLARE_FAST_INTERFACE (iModelDataPolygon);
SCF_DECLARE_FAST_INTERFACE (iModelDataAction);
SCF_DECLARE_FAST_INTERFACE (iModelDataVertices);
SCF_DECLARE_FAST_INTERFACE (iSprite3DFactoryState);

CS_DECLARE_OBJECT_ITERATOR (csModelDataObjectIterator, iModelDataObject);

//----------------------------------------------------------------------------

class csCrossBuilder : public iCrossBuilder
{
public:
  SCF_DECLARE_IBASE;

  /// constructor
  csCrossBuilder (iBase *parent);

  /// Build a thing from a model data object
  virtual bool BuildThing (iModelDataObject *Data, iThingState *tgt,
	iMaterialWrapper *defMat) const;

  /// Build a sprite factory from a model data object
  virtual bool BuildSpriteFactory (iModelDataObject *Data,
	iSprite3DFactoryState *tgt) const;

  /// Build a hierarchical sprite factory from all objects in a scene
  virtual iMeshFactoryWrapper *BuildSpriteFactoryHierarchy (iModelData *Scene,
	iEngine *Engine, iMaterialWrapper *DefaultMaterial) const;

  class Plugin : public iPlugin
  {
  public:
    SCF_DECLARE_EMBEDDED_IBASE (csCrossBuilder);
    virtual bool Initialize (iObjectRegistry *)
    { return true; }
  } scfiPlugin;
};

CS_IMPLEMENT_PLUGIN

SCF_IMPLEMENT_IBASE (csCrossBuilder)
  SCF_IMPLEMENTS_INTERFACE (iCrossBuilder)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iPlugin)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csCrossBuilder::Plugin)
  SCF_IMPLEMENTS_INTERFACE (iPlugin)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_FACTORY (csCrossBuilder)

SCF_EXPORT_CLASS_TABLE (crossbld)
  SCF_EXPORT_CLASS (csCrossBuilder, "crystalspace.mesh.crossbuilder",
    "Modeldata-to-Meshobject cross builder")
SCF_EXPORT_CLASS_TABLE_END

csCrossBuilder::csCrossBuilder (iBase *parent)
{
  SCF_CONSTRUCT_IBASE (parent);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiPlugin);
}

bool csCrossBuilder::BuildThing (iModelDataObject *Object, iThingState *tgt,
  iMaterialWrapper *DefaultMaterial) const
{
  int i;

  // copy the vertices
  iModelDataVertices *Vertices = Object->GetDefaultVertices ();
  if (!Vertices) return false;
  for (i=0; i<Vertices->GetVertexCount (); i++)
    tgt->CreateVertex (Vertices->GetVertex (i));

  // copy the polygons
  iObjectIterator *it = Object->QueryObject ()->GetIterator ();
  while (!it->IsFinished ())
  {
    // test if this is a valid polygon
    iModelDataPolygon *Polygon =
      SCF_QUERY_INTERFACE_FAST (it->GetObject (), iModelDataPolygon);
    if (!Polygon || Polygon->GetVertexCount () < 3)
    {
      it->Next ();
      continue;
    }
    iPolygon3D *ThingPoly = tgt->CreatePolygon ();

    // copy vertices
    for (i=0; i<Polygon->GetVertexCount (); i++)
      ThingPoly->CreateVertex (Polygon->GetVertex (i));
    
    // copy material
    iModelDataMaterial *mat = Polygon->GetMaterial ();
    if (mat && mat->GetMaterialWrapper ())
      ThingPoly->SetMaterial (mat->GetMaterialWrapper ());
    else
      ThingPoly->SetMaterial (DefaultMaterial);
    
    // copy texture transformation
    ThingPoly->SetTextureSpace (
      Vertices->GetVertex (Polygon->GetVertex (0)),
      Vertices->GetTexel (Polygon->GetTexel(0)),
      Vertices->GetVertex (Polygon->GetVertex (1)),
      Vertices->GetTexel (Polygon->GetTexel(1)),
      Vertices->GetVertex (Polygon->GetVertex (2)),
      Vertices->GetTexel (Polygon->GetTexel(2)));

    it->Next ();
  }
  it->DecRef ();

  return true;
}

CS_DECLARE_TYPED_VECTOR_NODELETE (csModelFrameVector, iModelDataVertices);
CS_DECLARE_TYPED_VECTOR_NODELETE (csSpriteFrameVector, iSpriteFrame);
CS_TYPEDEF_GROWING_ARRAY (csIntArray, int);

static void BuildVertexArray (iModelDataPolygon* poly,
	csIntArray& SpriteVertices,
	csIntArray& SpriteNormals,
	csIntArray& SpriteTexels,
	csIntArray& PolyVertices)
{
  // build the vertex array
  PolyVertices.SetLength (0);
  int i, j;
  for (i=0; i<poly->GetVertexCount (); i++)
  {
    int SpriteVertexIndex = -1;
    int PolyVertex = poly->GetVertex (i);
    int PolyNormal = poly->GetNormal (i);
    int PolyTexel = poly->GetTexel (i);

    for (j=0; j<SpriteVertices.Length (); j++)
    {
      int SpriteVertex = SpriteVertices [j];
      int SpriteNormal = SpriteNormals [j];
      int SpriteTexel = SpriteTexels [j];

      if (SpriteVertex == PolyVertex &&
	  SpriteNormal == PolyNormal &&
	  SpriteTexel == PolyTexel)
      {
	SpriteVertexIndex = i;
	break;
      }
    }
    if (SpriteVertexIndex == -1)
    {
      SpriteVertexIndex = SpriteVertices.Length ();
      SpriteTexels.Push (PolyTexel);
      SpriteNormals.Push (PolyNormal);
      SpriteVertices.Push (PolyVertex);
    }
    PolyVertices.Push (SpriteVertexIndex);
  }
}

bool csCrossBuilder::BuildSpriteFactory (iModelDataObject *Object,
	iSprite3DFactoryState *tgt) const
{
  int i,j;
  iObjectIterator *it1;
  iMaterialWrapper *Material = NULL;

  //--- preparation stage: arrange and validate incoming data locally --------<commit_msg>fixed a bug in the sprite crossbuilder<commit_after>
#include "cssysdef.h"
#include "csutil/csobject.h"
#include "csutil/typedvec.h"
#include "csutil/objiter.h"
#include "csgeom/transfrm.h"
#include "isys/plugin.h"
#include "imesh/crossbld.h"
#include "imesh/mdldata.h"
#include "imesh/thing/thing.h"
#include "imesh/thing/polygon.h"
#include "imesh/sprite3d.h"
#include "imesh/object.h"
#include "iengine/engine.h"
#include "iengine/mesh.h"

SCF_DECLARE_FAST_INTERFACE (iModelDataObject);
SCF_DECLARE_FAST_INTERFACE (iModelDataPolygon);
SCF_DECLARE_FAST_INTERFACE (iModelDataAction);
SCF_DECLARE_FAST_INTERFACE (iModelDataVertices);
SCF_DECLARE_FAST_INTERFACE (iSprite3DFactoryState);

CS_DECLARE_OBJECT_ITERATOR (csModelDataObjectIterator, iModelDataObject);

//----------------------------------------------------------------------------

class csCrossBuilder : public iCrossBuilder
{
public:
  SCF_DECLARE_IBASE;

  /// constructor
  csCrossBuilder (iBase *parent);

  /// Build a thing from a model data object
  virtual bool BuildThing (iModelDataObject *Data, iThingState *tgt,
	iMaterialWrapper *defMat) const;

  /// Build a sprite factory from a model data object
  virtual bool BuildSpriteFactory (iModelDataObject *Data,
	iSprite3DFactoryState *tgt) const;

  /// Build a hierarchical sprite factory from all objects in a scene
  virtual iMeshFactoryWrapper *BuildSpriteFactoryHierarchy (iModelData *Scene,
	iEngine *Engine, iMaterialWrapper *DefaultMaterial) const;

  class Plugin : public iPlugin
  {
  public:
    SCF_DECLARE_EMBEDDED_IBASE (csCrossBuilder);
    virtual bool Initialize (iObjectRegistry *)
    { return true; }
  } scfiPlugin;
};

CS_IMPLEMENT_PLUGIN

SCF_IMPLEMENT_IBASE (csCrossBuilder)
  SCF_IMPLEMENTS_INTERFACE (iCrossBuilder)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iPlugin)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csCrossBuilder::Plugin)
  SCF_IMPLEMENTS_INTERFACE (iPlugin)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_FACTORY (csCrossBuilder)

SCF_EXPORT_CLASS_TABLE (crossbld)
  SCF_EXPORT_CLASS (csCrossBuilder, "crystalspace.mesh.crossbuilder",
    "Modeldata-to-Meshobject cross builder")
SCF_EXPORT_CLASS_TABLE_END

csCrossBuilder::csCrossBuilder (iBase *parent)
{
  SCF_CONSTRUCT_IBASE (parent);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiPlugin);
}

bool csCrossBuilder::BuildThing (iModelDataObject *Object, iThingState *tgt,
  iMaterialWrapper *DefaultMaterial) const
{
  int i;

  // copy the vertices
  iModelDataVertices *Vertices = Object->GetDefaultVertices ();
  if (!Vertices) return false;
  for (i=0; i<Vertices->GetVertexCount (); i++)
    tgt->CreateVertex (Vertices->GetVertex (i));

  // copy the polygons
  iObjectIterator *it = Object->QueryObject ()->GetIterator ();
  while (!it->IsFinished ())
  {
    // test if this is a valid polygon
    iModelDataPolygon *Polygon =
      SCF_QUERY_INTERFACE_FAST (it->GetObject (), iModelDataPolygon);
    if (!Polygon || Polygon->GetVertexCount () < 3)
    {
      it->Next ();
      continue;
    }
    iPolygon3D *ThingPoly = tgt->CreatePolygon ();

    // copy vertices
    for (i=0; i<Polygon->GetVertexCount (); i++)
      ThingPoly->CreateVertex (Polygon->GetVertex (i));
    
    // copy material
    iModelDataMaterial *mat = Polygon->GetMaterial ();
    if (mat && mat->GetMaterialWrapper ())
      ThingPoly->SetMaterial (mat->GetMaterialWrapper ());
    else
      ThingPoly->SetMaterial (DefaultMaterial);
    
    // copy texture transformation
    ThingPoly->SetTextureSpace (
      Vertices->GetVertex (Polygon->GetVertex (0)),
      Vertices->GetTexel (Polygon->GetTexel(0)),
      Vertices->GetVertex (Polygon->GetVertex (1)),
      Vertices->GetTexel (Polygon->GetTexel(1)),
      Vertices->GetVertex (Polygon->GetVertex (2)),
      Vertices->GetTexel (Polygon->GetTexel(2)));

    it->Next ();
  }
  it->DecRef ();

  return true;
}

CS_DECLARE_TYPED_VECTOR_NODELETE (csModelFrameVector, iModelDataVertices);
CS_DECLARE_TYPED_VECTOR_NODELETE (csSpriteFrameVector, iSpriteFrame);
CS_TYPEDEF_GROWING_ARRAY (csIntArray, int);

static void BuildVertexArray (iModelDataPolygon* poly,
	csIntArray& SpriteVertices,
	csIntArray& SpriteNormals,
	csIntArray& SpriteTexels,
	csIntArray& PolyVertices)
{
  // build the vertex array
  PolyVertices.SetLength (0);
  int i, j;
  for (i=0; i<poly->GetVertexCount (); i++)
  {
    int SpriteVertexIndex = -1;
    int PolyVertex = poly->GetVertex (i);
    int PolyNormal = poly->GetNormal (i);
    int PolyTexel = poly->GetTexel (i);

    for (j=0; j<SpriteVertices.Length (); j++)
    {
      int SpriteVertex = SpriteVertices [j];
      int SpriteNormal = SpriteNormals [j];
      int SpriteTexel = SpriteTexels [j];

      if (SpriteVertex == PolyVertex &&
	  SpriteNormal == PolyNormal &&
	  SpriteTexel == PolyTexel)
      {
	SpriteVertexIndex = j;
	break;
      }
    }
    if (SpriteVertexIndex == -1)
    {
      SpriteVertexIndex = SpriteVertices.Length ();
      SpriteTexels.Push (PolyTexel);
      SpriteNormals.Push (PolyNormal);
      SpriteVertices.Push (PolyVertex);
    }
    PolyVertices.Push (SpriteVertexIndex);
  }
}

bool csCrossBuilder::BuildSpriteFactory (iModelDataObject *Object,
	iSprite3DFactoryState *tgt) const
{
  int i,j;
  iObjectIterator *it1;
  iMaterialWrapper *Material = NULL;

  //--- preparation stage: arrange and validate incoming data locally --------
{'fraction_non_alphanumeric': 0.12510534694259762, 'fraction_numerical': 0.003745669070137653, 'mean_word_length': 4.117393387637757, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6182168', 'n_tokens_mistral': 3649, 'n_tokens_neox': 3633, 'n_words': 740}