USNavalResearchLaboratory / simdissdk

SIMDIS SDK
Other
120 stars 42 forks source link

Problem displaying some 3D models #98

Closed faculaganymede closed 1 year ago

faculaganymede commented 1 year ago

SIMDIS SDK Gurus,

I have a 3D ship model in OpenSceneGraph .ive format. It displays OK in the osgviewer (see 1st picture below) but appears ghost like in the SIMDIS SDK viewer (see 2nd picture below). The SIMDIS SDK viewer is not showing the textures/materials and not applying the vertex normals. Are there maybe specific flags I have to enable in the code? However, if I replace the ship model with one of the IVE files in the SIMDIS_SDK-Data folder, the latter displays fine with the same code.

Note: This ship model was originally created in USDZ format, converted into OBJ, and then I used osgconv to convert it from OBJ to IVE. The ship model is just an example, I see similar problems with other 3D models that I have. I thought the 3D model reader/renderer in SIMDIS SDK is based on OpenSceneGraph, so a 3D model should appear the same in both!?

image

image

nebsar commented 1 year ago

There might be a shader issue. Materials are not used in new versions of osgEarth from 3.3 on as far as I know. You need to disable materials as fas as I remember.

faculaganymede commented 1 year ago

Thank you nebsar for your reply!

Is this the correct way to disable material? The following code didn't make a difference.

  osg::ref_ptr<simVis::PlatformNode> platformId1Node = scene->getScenario()->find<simVis::PlatformNode>(obj1);
  osg::ref_ptr<osg::Material> material = new osg::Material;
  platformId1Node->getOrCreateStateSet()->setAttributeAndModes(material, osg::StateAttribute::OFF);

I believe the ghost like effect is the result of the following function in SDK\simVis\ModelCache.cpp, has something to do with FFP Material.

  virtual void apply(osg::Drawable& drawable)
  {
    apply(static_cast<osg::Node&>(drawable));

    osg::Geometry* geom = drawable.asGeometry();
    if (geom)
    {
      // Ensure every geometry has a valid color array.
      // Some older models that use an FFP Material default to using the diffuse
      // material color as the active color, but this only works under FFP. Without
      // a color array, state leakage can occur.
      if (geom->getColorArray() == nullptr)
      {
        osg::Vec4Array* colors = new osg::Vec4Array(osg::Array::BIND_OVERALL, 1);
        (*colors)[0].set(1, 1, 1, 1);
        geom->setColorArray(colors);
      }
    }

    traverse(drawable);
  }

One partial solution I found is to load the 3D model using osgDB::readNodeFile(). The resulting model displays OK.

  osg::Node* tgtNode = osgDB::readNodeFile("ship.ive");

However, I want to be able to use the functions in simData::PlatformPrefs to manipulate the 3D model. How do I replace the node data loaded by prefs->set_icon() with tgtNode loaded by osgDB::readNodeFile()?

    simData::DataStore::Transaction txn;
    simData::PlatformPrefs* prefs = dataStore.mutable_platformPrefs(obj1, &txn);
    prefs->set_dynamicscale(true);
    prefs->set_scale(3.0);
    prefs->mutable_commonprefs()->set_name("First");
    prefs->mutable_commonprefs()->mutable_labelprefs()->set_draw(true);
    prefs->mutable_commonprefs()->mutable_labelprefs()->set_offsetx(50);
    prefs->mutable_commonprefs()->mutable_labelprefs()->set_offsety(-10);
    prefs->set_icon("ship.ive");
    txn.complete(&prefs);

I've tried the attach(), addChild(), insertChild(), replaceChild() functions in osg::ref_ptr<simVis::PlatformNode> platformId1Node, but none of them worked.

Basically, I want to replace this line prefs->set_icon("ship.ive"); with osg::Node* tgtNode = osgDB::readNodeFile("ship.ive"); and somehow add tgtNode to prefs. How would I add tgtNode to prefs?

emminizer commented 1 year ago

Sorry for the late response, have been on leave. As nesbar said, you're going to see vastly different visualizations between GL 3.3+ and earlier versions of GL. OSG defaults to build against earlier fixed function pipeline, which is only available in GL 3.3+ in compatibility mode. Compatibility mode in GL 3.3 is only available on certain drivers and certain systems, and often doesn't give a consistent display/experience either. osgEarth requires GL 3.3+, and SIMDIS SDK by default works off the GL core profile, which (colloquially) basically removes the "compatibility" features that tend to be problematic, allowing the software to execute on more targets (Linux, VMs).

To get models to properly display in a GL core profile that were built with features from fixed function pipeline, they have to be massaged into the right format. There are a number of things that are required to get this working in a decent state. simVis::ModelCache does take care of these things in the typical use with platforms and prefs->set_icon().

The majority of this is handled in the PrepareForProgrammablePipeline code in ModelCache.cpp. If you're trying to load your own model in GL 3.3, you might want to use this. Instead of exposing it directly, we expose it only through the ModelCache instance; I recommend using this through a call like simVis::Registry::instance()->getOrCreateIconModel() (indirectly) or through its accessor directly.

Some more notes responding directly to items in your comments:

At this point in time we do not provide a method for intercepting the model loading on a simVis::Platform. While that may help your specific issue, it sounds like you've got issues with the model itself and the texture bindings on it, but not positive. Just guessing based on the information presented here.

faculaganymede commented 1 year ago

Thank you so much for your detailed reply, emminizer!

I tried a few more things and then had to move on to some higher priority tasks, so I put this on the back burner for a while.

Perhaps I should ask a more general question. Does the SIMDIS community use 3D models from sites like sketchfab.com? If yes, how do you convert the models into the correct format and GL mode for use in a SIMDIS SDK application?

We are trying to take advantage of the 3D models available from sketchfab.com. The models are typically downloadable in DAE, USDZ, glTF, GLB, and FBX formats. I would download them in USDZ format, convert into OBJ, and then into IVE using osgconv for use in our SIMDIS SDK application. I chose to convert the models from OBJ into IVE binary format to reduce the file size (IVE also loads faster). The resulting OBJ and IVE models all appear "ghost like" when displayed in the SIMDIS SDK viewer (as described above with the ship model).

I've also tried creating some simple 3D models using tools like Blender and MeshLab, saved them into OBJ and then converted into IVE. They all have the same "ghost like" appearance problem when displayed in the SIMDIS SDK viewer.

emminizer commented 1 year ago

I do not personally have experience with sketchfab.com. We load models using OSG and rely entirely on that process to load the models, with extra code on top that I pointed out in my previous comment. The majority of models we receive are OpenFlight-based. I'm not a models guy and don't know particulars about most of the formats. I'd have to defer to others in the community about the conversion process.

dasheww commented 1 year ago

Regarding the conversion of models, we typically use visual studio when attempting to convert FBX models and ModelConverterX (https://www.scenerydesign.org/modelconverterx/) when trying to convert DAE. In all cases models have to be converted through OBJ in order to get them rendered in OSG. Of the models we and other users have acquired, they are typically purchased from TurboSquid and we try to find models in either OBJ or FLT formats as we know those will work out of the box.