Basic question for importers, answered, now with sample importer

Eric WinemillerEric Winemiller Posts: 84
edited September 2014 in Daz SDK Developer Discussion

Hi folks,

I'm just getting rolling with the DAZ Studio SDK so this is probably some basic misconception I've got going.

I'm building an importer and trying to implement my read function. As I understand it I need to read my stuff, build my mesh, and somehow drop it into that DzShape object.

I see references on these boards to a DzFacetMesh which seems to be where you build a generic mesh, and it looks to be everything I'd expect it to be. However as I poke around DzShape, I can't for the life of me understand how you'd hook those up (e.g. I see a getGeometry, but no corresponding setGeometry).

Sadly the samples don't have a basic importer and the only things that reference DzShape are a custom shape and some stuff that pull existing attributes.

Any suggestions?

Thanks,

Post edited by Eric Winemiller on

Comments

  • Eric WinemillerEric Winemiller Posts: 84
    edited December 1969

    Okay. I'm a little farther along, but still not there yet.

    The object I was looking for was a DzFacetShape. It derives from shape and lets you assign a DzFacetMesh to it. So my read looks something like the code below.

    However, I can't see it in the scene. If I have it selected and hover over, some of the mesh is visible, but fades back to the bounding box when I'm done. The mesh I can see on hover over is what I'm expecting so I think the geometry is right.

    It seems like it might be some missing material settings or something.

    Any suggestions?

    
    
     DzFacetMesh *vMesh = new DzFacetMesh();
        vMesh->beginEdit(false);
     vMesh->setVertexArray(fullMapInfo.mesh->pointCount);
    
     for (point = 0; point < fullMapInfo.mesh->pointCount; point++) {
            //use set vertex to load my vMesh
     }
    
     for (facet = 0; facet < fullMapInfo.mesh->facetCount; facet++) {
           //use addFacet to load my facets
     }
    
        vMesh->finishEdit();  
    
     (*shape)= new DzFacetShape();
     DzFacetShape *facetShape = reinterpret_cast(*shape);
     facetShape->setFacetMesh(vMesh);
     (*shape)->setName(fullMapInfo.description);
    
    
    

    Thanks,

  • Eric WinemillerEric Winemiller Posts: 84
    edited December 1969

    Got it!

    
    
     (*shape)->addMaterial(new DzDefaultMaterial());
    
    
  • Eric WinemillerEric Winemiller Posts: 84
    edited November 2015

    Hi folks,

    Since there isn't an importer sample in the SDK, here's mine.

    Of course Ground Control is doing a lot of the heavy lifting behind the scenes to actually read the file and build the mesh, but this should give you a place to start in terms of which objects/apis to call to get something on the screen. Figuring out which UV thingy actually sets the UVs and what it was expecting took me a couple of hours of tweak, compile, test, rinse, and repeat.

    Just a few words of warning. This is a work in progress. I'm probably not cleaning up everything correctly here yet. I need to sit down and see which APIs just take over the newly allocated memory and which do deep copies (e.g. does vMesh freak out if I destroy uvList). I also should use the native maps instead of calloc for a couple of the arrays. Finally, not sure I'm building the mesh in the fastest way. addFacet seems pokey, but can't find a way to allocate the number of facets up front and then value them (like I can do with vertices).

    header

     

    
    
    #ifndef GROUND_CONTROL_IMPORTER
    #define GROUND_CONTROL_IMPORTER
    
    #include 
    
    class GroundControlImporter : public  DzGeometryImporter {
        Q_OBJECT
    public:
    
        GroundControlImporter();
     virtual int getNumExtensions () const;
     virtual QString getDescription () const;
     virtual QString getExtension (int i) const;
     virtual bool recognize (const QString &filename;) const;
     virtual void getDefaultOptions( DzFileIOSettings *options ) const;
    
    protected:
     virtual DzError read( const QString &filename;, DzShape **shape,
          const DzFileIOSettings *options );
    };
    
    #endif 
    
    

     

    code

     

    
    
    #include "GroundControlImporter.h"
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace Qt;
    
    const int NUMBER_OF_EXTENSIONS = 9;
    char *extensions[NUMBER_OF_EXTENSIONS] = {"dem", "r32", "ter", "bil", "hgt", "pgm", "asc", "flt", "img"};
    
    GroundControlImporter::GroundControlImporter() {
    
    };
    
    int GroundControlImporter::getNumExtensions () const{
     return NUMBER_OF_EXTENSIONS;
    };
    
    QString GroundControlImporter::getDescription () const{
     return "Ground Control elevation map";
    };
    
    QString GroundControlImporter::getExtension (int i) const{
     return extensions[ i ];
    };
    
    bool GroundControlImporter::recognize (const QString &filename;) const{
     bool returnValue = false;
    
     gcMapInfo fullMapInfo;
    
     gcInitialize(&fullMapInfo;);
    
     if (gcCanOpenFile(filename.toAscii(), &fullMapInfo;) == GC_OK)
     {
      returnValue = true;
     }
    
     gcCleanUp(&fullMapInfo;);
    
     return returnValue;
    };
    
    void GroundControlImporter::getDefaultOptions( DzFileIOSettings *options ) const {
    };
    
    DzError GroundControlImporter::read( const QString &filename;, DzShape **shape,
             const DzFileIOSettings *options ) {
     DzError returnValue = DZ_NO_ERROR;
     int meshType = GC_MESH_GRID_SMART;
     int fullPolyCount, targetPolyCount;
    
     gcMapInfo fullMapInfo;
    
     gcInitialize(&fullMapInfo;);
    
     if (gcCanOpenFile(filename.toAscii(), &fullMapInfo;) == GC_ERROR) {
      returnValue = DZ_UNABLE_TO_OPEN_FILE_ERROR;
      goto Finish;
     }
     
     if (gcOpenFile(filename.toAscii(), &fullMapInfo;) == GC_ERROR) {
      returnValue = DZ_UNABLE_TO_OPEN_FILE_ERROR;
      goto Finish;
     } 
     
     float percent = .1f;
    
     fullPolyCount = gcGetFullPolyCount(&fullMapInfo;);
     if (fullPolyCount > 100000000) {
      percent = .001f;
     }
     else if (fullPolyCount > 10000000) {
      percent = .01f;
     }
    
     targetPolyCount = (float)fullPolyCount * percent;
    
     if (gcCreateMesh(&fullMapInfo;, targetPolyCount, meshType) == GC_ERROR) {
      returnValue = DZ_UNABLE_TO_OPEN_FILE_ERROR;
      goto Finish;
     }
    
     //build the mesh
     //DAZ X=West to East, Z=North to South, Y = elevation
     float sizeZ = 200.0f, sizeX = 200.0f, sizeY = 10.0f, elevationMin = 0;
     unsigned long east, north, point, facet;
     float* XLines = NULL;
     float* ZLines = NULL;
    
     XLines = reinterpret_cast(calloc( fullMapInfo.mesh->samples[GC_EAST], sizeof( float )));
     if ( !XLines ) goto Finish;
    
     ZLines = reinterpret_cast(calloc( fullMapInfo.mesh->samples[GC_NORTH], sizeof( float )));
     if ( !ZLines ) goto Finish;
    
     for (east = 0; east < fullMapInfo.mesh->samples[GC_EAST]; east++){
      XLines[east] = sizeX * fullMapInfo.mesh->EPercent[east] - sizeX * 0.5f;
     }
    
     for (north = 0; north < fullMapInfo.mesh->samples[GC_NORTH]; north++){
      ZLines[north] = - sizeZ * fullMapInfo.mesh->NPercent[north] + sizeZ * 0.5f;
     }
    
     DzFacetMesh *vMesh = new DzFacetMesh();
     DzMap *uvList = new DzMap(DzMap::FLOAT2_MAP);
    
        vMesh->beginEdit(false);
     vMesh->setVertexArray(fullMapInfo.mesh->pointCount);
     uvList->setNumValues(fullMapInfo.mesh->pointCount);
    
     for (point = 0; point < fullMapInfo.mesh->pointCount; point++) {
      const DzVec3 vertex(XLines[fullMapInfo.mesh->points[point].east], 
       elevationMin + fullMapInfo.mesh->points[point].elevation * sizeY,  
       ZLines[fullMapInfo.mesh->points[point].north]);
      const DzPnt2 uv = {fullMapInfo.mesh->EPercent[fullMapInfo.mesh->points[point].east], 
       fullMapInfo.mesh->NPercent[fullMapInfo.mesh->points[point].north]};
      vMesh->setVertex(point, vertex);
      uvList->setPnt2Value(point, uv);
     }
     vMesh->setUVList(uvList);
    
     for (facet = 0; facet < fullMapInfo.mesh->facetCount; facet++) {
    
      const int vertIdx[4] = {fullMapInfo.mesh->facets[facet].pointIndex[0],
       fullMapInfo.mesh->facets[facet].pointIndex[1],
       fullMapInfo.mesh->facets[facet].pointIndex[2],
       -1};
      vMesh->addFacet(vertIdx, vertIdx);
     }
        vMesh->finishEdit();  
    
     //build our shape and assign the mesh
     (*shape)= new DzFacetShape();
     DzFacetShape *facetShape = reinterpret_cast(*shape);
     facetShape->setFacetMesh(vMesh);
     (*shape)->setName(fullMapInfo.description);
    
     //generate a texture out of the elevation map and make that our material
     DzDefaultMaterial* material = new DzDefaultMaterial();
     material->setLabel(fullMapInfo.description);
    
     QImage* image = new QImage(fullMapInfo.samples[GC_EAST], fullMapInfo.samples[GC_NORTH],QImage::Format_RGB888);
    
     for (east = 0; east < fullMapInfo.samples[GC_EAST]; east++){
      for (north = 0; north < fullMapInfo.samples[GC_NORTH]; north++){
       float value = gcGetElevationByCoordinates(&fullMapInfo;, east, north);
       value *= 255.0f;
       image->setPixel(east, fullMapInfo.samples[GC_NORTH] - north - 1, qRgb(value, value, value));
      }
     }
    
     DzImageMgr* imageManager = dzApp->getImageMgr();
    
     //TODO: find a safe place to deal with generated content
     DzError saveImageResult = imageManager->saveImage("C:\\test.jpg" , *image);
     DzTexture* texture = imageManager->getImage("C:\\test.jpg");
    
     material->setColorMap(texture);
     material->setBumpMap(texture);
     material->setBumpStrength(1.0f);
     material->setBumpMax(1.0f);
     material->setBumpMin(0);
    
     (*shape)->addMaterial(material);
    
    Finish:
     gcCleanUp(&fullMapInfo;);
     if (XLines) free (XLines);
     if (ZLines) free (ZLines);
     return returnValue;
    };
    
    

     

    Regards,

    Post edited by Richard Haseltine on
Sign In or Register to comment.