Пример #1
0
	//============================================================================
	//============================================================================
	osg::Geode* createPlant( const NgpFileName &ngpfile ) const
	{
		std::string filename = ngpfile.settings().filePath;
		std::string folder = osgDB::getFilePath(filename);

		NGPInputStream stream( filename );
		if (!stream.isOpen())
		{
			OSG_WARN << "Unable to open plant file: " << filename << std::endl;
			return NULL;
		}

		P3DHLIPlantTemplate plantTemplate( &stream );
		P3DHLIPlantInstance* plantInstance = plantTemplate.CreateInstance(ngpfile.settings().seed);
		unsigned int branchGroupCount = plantTemplate.GetGroupCount();
		if ( !branchGroupCount )
		{
			OSG_WARN << "Loaded empty plant, so ignore it." << std::endl;
			return NULL;
		}
    
		osg::ref_ptr<osg::Geode> geode = new osg::Geode;
		for ( unsigned int i=0; i<branchGroupCount; ++i )
		{
			unsigned int branchCount = plantInstance->GetBranchCount(i);
			unsigned int vertexCount = plantInstance->GetVAttrCountI(i);
			unsigned int indexCount = plantTemplate.GetIndexCount( i, P3D_TRIANGLE_LIST );
        
			// Read materials
			const P3DMaterialDef* material = plantTemplate.GetMaterial(i);
			float r, g, b; material->GetColor( &r, &g, &b );
        
			const char* diffuseName = material->GetTexName( P3D_TEX_DIFFUSE );
			bool hasTexture = (diffuseName!=NULL);
			std::string txfile;

			if (hasTexture)
			{
				txfile = osgDB::concatPaths(folder, diffuseName);
				if (!osgDB::fileExists(txfile))
				{
					OSG_WARN << "Texture file " << filename << " doesn't exist." << std::endl;
					hasTexture = false;
				}
			}

			if ( hasTexture )
			{
				const char* normalName = material->GetTexName( P3D_TEX_NORMAL_MAP );
				const char* aux0Name = material->GetTexName( P3D_TEX_AUX0 );
				const char* aux1Name = material->GetTexName( P3D_TEX_AUX1 );
				// TODO: how to handle these textures?
			}
        
			// Read vertex buffer
			float* vertexBuffer = new float[vertexCount * 3];
			float* normalBuffer = new float[vertexCount * 3];
			float* texcoodBuffer = NULL;
			P3DHLIVAttrBuffers attrBuffers;
			attrBuffers.AddAttr( P3D_ATTR_VERTEX, vertexBuffer, 0, sizeof(float)*3 );
			attrBuffers.AddAttr( P3D_ATTR_NORMAL, normalBuffer, 0, sizeof(float)*3 );
			if ( hasTexture )
			{
				texcoodBuffer = new float[vertexCount * 2];
				attrBuffers.AddAttr( P3D_ATTR_TEXCOORD0, texcoodBuffer, 0, sizeof(float)*2 );
			}
			plantInstance->FillVAttrBuffersI( &attrBuffers, i );
        
			// scale the verts if needed
			if (ngpfile.hasScale())
			{
				for (unsigned int i=0; i<vertexCount*3; i++)
				{
					vertexBuffer[i] *= ngpfile.settings().scale;
				}
			}
			// Read index buffer
			unsigned int indexCountAll = indexCount * branchCount;
			unsigned int* indexBuffer = new unsigned int[indexCountAll];
			unsigned int attrCount = plantTemplate.GetVAttrCountI(i);
			for ( unsigned int c=0; c<branchCount; ++c )
			{
				plantTemplate.FillIndexBuffer( &(indexBuffer[c*indexCount]), i,
												P3D_TRIANGLE_LIST, P3D_UNSIGNED_INT, c*attrCount );
			}
        
			// Write data to OSG geometry
			osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array(vertexCount);
			osg::ref_ptr<osg::Vec3Array> na = new osg::Vec3Array(vertexCount);
			osg::ref_ptr<osg::Vec2Array> ta = hasTexture ? new osg::Vec2Array(vertexCount) : NULL;
			for ( unsigned int n=0; n<vertexCount; ++n )
			{
				(*va)[n].set( *(vertexBuffer + 3*n), *(vertexBuffer + 3*n + 1), *(vertexBuffer + 3*n + 2) );
				(*na)[n].set( *(normalBuffer + 3*n), *(normalBuffer + 3*n + 1), *(normalBuffer + 3*n + 2) );
				if ( hasTexture ) (*ta)[n].set( *(texcoodBuffer + 2*n), *(texcoodBuffer + 2*n + 1) );
			}
        
			osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(GL_TRIANGLES, indexCountAll);
			for ( unsigned int n=0; n<indexCountAll; ++n )
				(*indices)[n] = indexBuffer[n];
        
			osg::ref_ptr<osg::Vec4Array> ca = new osg::Vec4Array(1);
			ca->front() = osg::Vec4(r, g, b, 1.0f);
        
			osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
			geode->addDrawable( geometry.get() );
        
			geometry->setVertexArray( va.get() );
			geometry->setTexCoordArray( 0, ta.get() );
			geometry->setNormalArray( na.get() );
			geometry->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
			geometry->setColorArray( ca.get() );
			geometry->setColorBinding( osg::Geometry::BIND_OVERALL );
			geometry->addPrimitiveSet( indices.get() );
        
			osg::StateSet* ss = geometry->getOrCreateStateSet();
			if (ngpfile.settings().alphaMode == NgpFileName::Test)
			{
				osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
				alphaFunc->setFunction(osg::AlphaFunc::GEQUAL, ngpfile.settings().alphaThreshold);
				ss->setAttributeAndModes( alphaFunc, osg::StateAttribute::ON );
			}
			else
			{
				ss->setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
				ss->setMode( GL_BLEND, osg::StateAttribute::ON );
			}

			if ( hasTexture )
			{
				osg::ref_ptr<osg::Texture2D> diffuseTex = new osg::Texture2D;
				diffuseTex->setImage( osgDB::readImageFile(txfile) );
				ss->setTextureAttributeAndModes( 0, diffuseTex.get() );
			}

			 if (vertexBuffer) delete []  vertexBuffer;
			 if (normalBuffer) delete []  normalBuffer;
			 if (texcoodBuffer) delete [] texcoodBuffer;
		}
		return geode.release();
	}
Пример #2
0
static void        RenderBranchGroup  (P3DHLIPlantTemplate*PlantTemplate,
                                       P3DHLIPlantInstance*PlantInstance,
                                       unsigned int        GroupIndex)
 {
  unsigned int                         BranchIndex;
  unsigned int                         BranchCount;
  const P3DMaterialDef                *MaterialDef;

  BranchCount = PlantInstance->GetBranchCount(GroupIndex);

  if (BranchCount == 0)
   {
    return;
   }

  MaterialDef = PlantTemplate->GetMaterial(GroupIndex);

  unsigned int     BranchVAttrCount;
  unsigned int     BranchIndexCount;
  unsigned int     TotalVAttrCount;
  unsigned int     TotalIndexCount;

  BranchVAttrCount = PlantTemplate->GetVAttrCountI(GroupIndex);
  BranchIndexCount = PlantTemplate->GetIndexCount(GroupIndex,P3D_TRIANGLE_LIST);

  TotalVAttrCount = BranchVAttrCount * BranchCount;
  TotalIndexCount = BranchIndexCount * BranchCount;

  float           *PosBuffer      = 0;
  float           *NormalBuffer   = 0;
  float           *BiNormalBuffer = 0;
  float           *TexCoordBuffer = 0;
  unsigned int    *IndexBuffer    = 0;

  PosBuffer      = new(std::nothrow) float[3 * TotalVAttrCount];
  NormalBuffer   = new(std::nothrow) float[3 * TotalVAttrCount];
  TexCoordBuffer = new(std::nothrow) float[2 * TotalVAttrCount];
  IndexBuffer    = new(std::nothrow) unsigned int[TotalIndexCount];
  BiNormalBuffer = new(std::nothrow) float[3 * TotalVAttrCount];

  if ((PosBuffer != 0) && (NormalBuffer != 0) &&
      (TexCoordBuffer != 0) && (IndexBuffer != 0) &&
      (BiNormalBuffer != 0))
   {
    P3DHLIVAttrBuffers                 VAttrBuffers;

    if (MaterialDef->IsBillboard())
     {
      VAttrBuffers.AddAttr(P3D_ATTR_BILLBOARD_POS,PosBuffer,0,sizeof(float) * 3);
     }
    else
     {
      VAttrBuffers.AddAttr(P3D_ATTR_VERTEX,PosBuffer,0,sizeof(float) * 3);
     }

    VAttrBuffers.AddAttr(P3D_ATTR_NORMAL,NormalBuffer,0,sizeof(float) * 3);
    VAttrBuffers.AddAttr(P3D_ATTR_TEXCOORD0,TexCoordBuffer,0,sizeof(float) * 2);

    if (BiNormalBuffer != 0)
     {
      VAttrBuffers.AddAttr(P3D_ATTR_BINORMAL,BiNormalBuffer,0,sizeof(float) * 3);
     }

    PlantInstance->FillVAttrBuffersI(&VAttrBuffers,GroupIndex);

    if (MaterialDef->IsBillboard())
     {
      float        BillboardWidth;
      float        BillboardHeight;

      PlantTemplate->GetBillboardSize(&BillboardWidth,&BillboardHeight,GroupIndex);
     }

    for (BranchIndex = 0; BranchIndex < BranchCount; BranchIndex++)
     {
      PlantTemplate->FillIndexBuffer
       (&IndexBuffer[BranchIndex * BranchIndexCount],
         GroupIndex,
         P3D_TRIANGLE_LIST,
         P3D_UNSIGNED_INT,
         BranchVAttrCount * BranchIndex);
     }
   }
  else
   {
    fprintf(stderr,"error: out of memory\n");
   }

  delete[] IndexBuffer;
  delete[] TexCoordBuffer;
  delete[] BiNormalBuffer;
  delete[] NormalBuffer;
  delete[] PosBuffer;
 }