Beispiel #1
0
Selector::Selector(const sf::Texture& t)
    : m_texture     (t),
    m_currentIndex  (0),
    m_target        (0.f)
{
    sf::Vector2f texSize(t.getSize());

    m_topButton.width = texSize.x / 2.f;
    m_topButton.height = texSize.y / 3.f;

    m_bottomButton = m_topButton;
    m_bottomButton.top = m_bottomButton.height * 2.f;

    m_vertices[0].texCoords.x = m_topButton.width;
    m_vertices[0].position.y = m_topButton.height;

    m_vertices[1].texCoords.x = texSize.x;
    m_vertices[1].position = { m_topButton.width, m_topButton.height };

    m_vertices[2].texCoords = { texSize.x, m_topButton.height };
    m_vertices[2].position = { m_topButton.width, m_topButton.height * 2.f };

    m_vertices[3].texCoords = { m_topButton.width, m_topButton.height };
    m_vertices[3].position.y = m_topButton.height * 2.f;

    m_vertices[5].texCoords.x = m_topButton.width;
    m_vertices[5].position.x = m_topButton.width;

    m_vertices[6].texCoords = { m_topButton.width, texSize.y };
    m_vertices[6].position = m_vertices[6].texCoords;

    m_vertices[7].texCoords.y = texSize.y;
    m_vertices[7].position.y = texSize.y;

    m_localBounds.width = m_topButton.width;
    m_localBounds.height = texSize.y;
}
void TransferFunctionPropertyDialog::exportTransferFunction() {
    InviwoFileDialog exportFileDialog(this, "Export transfer function",
        "transferfunction",
        InviwoApplication::getPtr()->getPath(InviwoApplication::PATH_TRANSFERFUNCTIONS)
    );    
    exportFileDialog.setAcceptMode(QFileDialog::AcceptSave);
    exportFileDialog.setFileMode(QFileDialog::AnyFile);
    exportFileDialog.addExtension("itf", "Inviwo Transfer Function");
    exportFileDialog.addExtension("png", "Transfer Function Image");
    exportFileDialog.addExtension("", "All files"); // this will add "All files (*)"

    if (exportFileDialog.exec()) {
        std::string file = exportFileDialog.selectedFiles().at(0).toLocal8Bit().constData();
        std::string extension = filesystem::getFileExtension(file);

        FileExtension fileExt = exportFileDialog.getSelectedFileExtension();

        if (fileExt.extension_.empty()) {
            // fall-back to standard inviwo TF format
            fileExt.extension_ = "itf";
        }

        // check whether file extension matches the selected one
        if (fileExt.extension_ != extension) {
            file.append(fileExt.extension_);
        }

        if (fileExt.extension_ == "png") {
            TransferFunction &tf = tfProperty_->get();
            const Layer* layer = tf.getData();
            vec2 texSize(tf.getTextureSize(), 1);
            const vec4* readData = static_cast<const vec4*>(layer->getRepresentation<LayerRAM>()->getData());
            Layer writeLayer(layer->getDimensions(), DataVec4UINT8::get());
            glm::u8vec4* writeData = static_cast<glm::u8vec4*>(writeLayer.getEditableRepresentation<LayerRAM>()->getData());
            
            for (std::size_t i=0; i<texSize.x * texSize.y; ++i) {
                for (int c=0; c<4; ++c) {
                    writeData[i][c] = static_cast<glm::u8>(std::min(std::max(readData[i][c] * 255.0f, 0.0f), 255.0f));
                }
            }

            auto writer =
                DataWriterFactory::getPtr()->getWriterForTypeAndExtension<Layer>(extension);

            if (writer) {
                try {
                    writer->setOverwrite(true);
                    writer->writeData(&writeLayer, file);
                } catch (DataWriterException const& e) {
                    util::log(e.getContext(), e.getMessage(), LogLevel::Error);
                }
            } else {
                LogError("Error: Cound not find a writer for the specified extension and data type");
            }
        }
        else if (fileExt.extension_ == "itf") {
            IvwSerializer serializer(file);
            tfProperty_->get().serialize(serializer);
            serializer.writeFile();
        }
    }
}
Beispiel #3
0
/**
 * Creates the textures and the display list needed for displaying
 * an OSD part.
 * Callback function for vo_draw_text().
 */
static void create_osd_texture(int x0, int y0, int w, int h,
                                 unsigned char *src, unsigned char *srca,
                                 int stride)
{
  // initialize to 8 to avoid special-casing on alignment
  int sx = 8, sy = 8;
  GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;

  if (w <= 0 || h <= 0 || stride < w) {
    mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
    return;
  }
  texSize(w, h, &sx, &sy);

  if (osdtexCnt >= MAX_OSD_PARTS) {
    mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n");
    return;
  }

  // create Textures for OSD part
  mpglGenTextures(1, &osdtex[osdtexCnt]);
  mpglBindTexture(gl_target, osdtex[osdtexCnt]);
  glCreateClearTex(gl_target, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
  glUploadTex(gl_target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride,
              0, 0, w, h, 0);

#ifndef FAST_OSD
  mpglGenTextures(1, &osdatex[osdtexCnt]);
  mpglBindTexture(gl_target, osdatex[osdtexCnt]);
  glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
  {
  int i;
  char *tmp = malloc(stride * h);
  // convert alpha from weird MPlayer scale.
  // in-place is not possible since it is reused for future OSDs
  for (i = h * stride - 1; i >= 0; i--)
    tmp[i] = -srca[i];
  glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride,
              0, 0, w, h, 0);
  free(tmp);
  }
#endif

  mpglBindTexture(gl_target, 0);

  // Create a list for rendering this OSD part
#ifndef FAST_OSD
  osdaDispList[osdtexCnt] = mpglGenLists(1);
  mpglNewList(osdaDispList[osdtexCnt], GL_COMPILE);
  // render alpha
  mpglBindTexture(gl_target, osdatex[osdtexCnt]);
  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
  mpglEndList();
#endif
  osdDispList[osdtexCnt] = mpglGenLists(1);
  mpglNewList(osdDispList[osdtexCnt], GL_COMPILE);
  // render OSD
  mpglBindTexture(gl_target, osdtex[osdtexCnt]);
  glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0);
  mpglEndList();

  osdtexCnt++;
}
Beispiel #4
0
/**
 * \brief Initialize a (new or reused) OpenGL context.
 * set global gl-related variables to their default values
 */
static int initGl(uint32_t d_width, uint32_t d_height) {
  GLint scale_type = get_scale_type(0);
  autodetectGlExtensions();
  gl_target = use_rectangle == 1 ? GL_TEXTURE_RECTANGLE : GL_TEXTURE_2D;
  yuvconvtype = SET_YUV_CONVERSION(use_yuv) |
                SET_YUV_LUM_SCALER(lscale) |
                SET_YUV_CHROM_SCALER(cscale);

  texSize(image_width, image_height, &texture_width, &texture_height);

  mpglDisable(GL_BLEND);
  mpglDisable(GL_DEPTH_TEST);
  mpglDepthMask(GL_FALSE);
  mpglDisable(GL_CULL_FACE);
  mpglEnable(gl_target);
  mpglDrawBuffer(vo_doublebuffering?GL_BACK:GL_FRONT);
  mpglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  mp_msg(MSGT_VO, MSGL_V, "[gl] Creating %dx%d texture...\n",
          texture_width, texture_height);

  glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
                   texture_width, texture_height, 0);
  if (mipmap_gen)
    mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);

  if (is_yuv) {
    int i;
    int xs, ys;
    scale_type = get_scale_type(1);
    mp_get_chroma_shift(image_format, &xs, &ys);
    mpglGenTextures(21, default_texs);
    default_texs[21] = 0;
    for (i = 0; i < 7; i++) {
      mpglActiveTexture(GL_TEXTURE1 + i);
      mpglBindTexture(GL_TEXTURE_2D, default_texs[i]);
      mpglBindTexture(GL_TEXTURE_RECTANGLE, default_texs[i + 7]);
      mpglBindTexture(GL_TEXTURE_3D, default_texs[i + 14]);
    }
    mpglActiveTexture(GL_TEXTURE1);
    glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
                     texture_width >> xs, texture_height >> ys, 128);
    if (mipmap_gen)
      mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
    mpglActiveTexture(GL_TEXTURE2);
    glCreateClearTex(gl_target, gl_texfmt, gl_format, gl_type, scale_type,
                     texture_width >> xs, texture_height >> ys, 128);
    if (mipmap_gen)
      mpglTexParameteri(gl_target, GL_GENERATE_MIPMAP, GL_TRUE);
    mpglActiveTexture(GL_TEXTURE0);
    mpglBindTexture(gl_target, 0);
  }
  if (is_yuv || custom_prog)
  {
    if ((MASK_NOT_COMBINERS & (1 << use_yuv)) || custom_prog) {
      if (!mpglGenPrograms || !mpglBindProgram) {
        mp_msg(MSGT_VO, MSGL_ERR, "[gl] fragment program functions missing!\n");
      } else {
        mpglGenPrograms(1, &fragprog);
        mpglBindProgram(GL_FRAGMENT_PROGRAM, fragprog);
      }
    }
    update_yuvconv();
  }

  resize(d_width, d_height);

  mpglClearColor( 0.0f,0.0f,0.0f,0.0f );
  mpglClear( GL_COLOR_BUFFER_BIT );
  if (mpglSwapInterval && swap_interval >= 0)
    mpglSwapInterval(swap_interval);
  return 1;
}
Beispiel #5
0
/**
 * \brief construct display list from ass image list
 * \param img image list to create OSD from.
 *            A value of NULL has the same effect as clearEOSD()
 */
static void genEOSD(struct mp_eosd_image_list *imgs) {
  int sx, sy;
  int tinytexcur = 0;
  int smalltexcur = 0;
  GLuint *curtex;
  GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST;
  struct mp_eosd_image *img = eosd_image_first(imgs);
  struct mp_eosd_image *i;

  if (imgs->changed == 0) // there are elements, but they are unchanged
      return;
  if (img && imgs->changed == 1) // there are elements, but they just moved
      goto skip_upload;

  clearEOSD();
  if (!img)
    return;
  if (!largeeosdtex[0]) {
    mpglGenTextures(2, largeeosdtex);
    mpglBindTexture(gl_target, largeeosdtex[0]);
    glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
    mpglBindTexture(gl_target, largeeosdtex[1]);
    glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0);
  }
  for (i = img; i; i = eosd_image_next(imgs))
  {
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
      continue;
    if (is_tinytex(i, tinytexcur))
      tinytexcur++;
    else if (is_smalltex(i, smalltexcur))
      smalltexcur++;
    else
      eosdtexCnt++;
  }
  mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n",
         tinytexcur, smalltexcur, eosdtexCnt);
  if (eosdtexCnt) {
    eosdtex = calloc(eosdtexCnt, sizeof(GLuint));
    mpglGenTextures(eosdtexCnt, eosdtex);
  }
  tinytexcur = smalltexcur = 0;
  for (i = eosd_image_first(imgs), curtex = eosdtex; i; i = eosd_image_next(imgs)) {
    int x = 0, y = 0;
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w) {
      mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n");
      continue;
    }
    if (is_tinytex(i, tinytexcur)) {
      tinytex_pos(tinytexcur, &x, &y);
      mpglBindTexture(gl_target, largeeosdtex[0]);
      tinytexcur++;
    } else if (is_smalltex(i, smalltexcur)) {
      smalltex_pos(smalltexcur, &x, &y);
      mpglBindTexture(gl_target, largeeosdtex[1]);
      smalltexcur++;
    } else {
      texSize(i->w, i->h, &sx, &sy);
      mpglBindTexture(gl_target, *curtex++);
      glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0);
    }
    glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride,
                x, y, i->w, i->h, 0);
  }
  eosdDispList = mpglGenLists(1);
skip_upload:
  mpglNewList(eosdDispList, GL_COMPILE);
  tinytexcur = smalltexcur = 0;
  for (i = eosd_image_first(imgs), curtex = eosdtex; i; i = eosd_image_next(imgs)) {
    int x = 0, y = 0;
    if (i->w <= 0 || i->h <= 0 || i->stride < i->w)
      continue;
    mpglColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - (i->color & 0xff));
    if (is_tinytex(i, tinytexcur)) {
      tinytex_pos(tinytexcur, &x, &y);
      sx = sy = LARGE_EOSD_TEX_SIZE;
      mpglBindTexture(gl_target, largeeosdtex[0]);
      tinytexcur++;
    } else if (is_smalltex(i, smalltexcur)) {
      smalltex_pos(smalltexcur, &x, &y);
      sx = sy = LARGE_EOSD_TEX_SIZE;
      mpglBindTexture(gl_target, largeeosdtex[1]);
      smalltexcur++;
    } else {
      texSize(i->w, i->h, &sx, &sy);
      mpglBindTexture(gl_target, *curtex++);
    }
    glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0);
  }
  mpglEndList();
  mpglBindTexture(gl_target, 0);
}
void TSLastDetail::_update()
{
   // We're gonna render... make sure we can.
   bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   _validateDim();

   Vector<GBitmap*> bitmaps;
   Vector<GBitmap*> normalmaps;

   // We need to create our own instance to render with.
   TSShapeInstance *shape = new TSShapeInstance( mShape, true );

   // Animate the shape once.
   shape->animate( mDl );

   // So we don't have to change it everywhere.
   const GFXFormat format = GFXFormatR8G8B8A8;  

   S32 imposterCount = ( ((2*mNumPolarSteps) + 1 ) * mNumEquatorSteps ) + ( mIncludePoles ? 2 : 0 );

   // Figure out the optimal texture size.
   Point2I texSize( smMaxTexSize, smMaxTexSize );
   while ( true )
   {
      Point2I halfSize( texSize.x / 2, texSize.y / 2 );
      U32 count = ( halfSize.x / mDim ) * ( halfSize.y / mDim );
      if ( count < imposterCount )
      {
         // Try half of the height.
         count = ( texSize.x / mDim ) * ( halfSize.y / mDim );
         if ( count >= imposterCount )
            texSize.y = halfSize.y;
         break;
      }

      texSize = halfSize;
   }

   GBitmap *imposter = NULL;
   GBitmap *normalmap = NULL;
   GBitmap destBmp( texSize.x, texSize.y, true, format );
   GBitmap destNormal( texSize.x, texSize.y, true, format );

   U32 mipLevels = destBmp.getNumMipLevels();

   ImposterCapture *imposterCap = new ImposterCapture();

   F32 equatorStepSize = M_2PI_F / (F32)mNumEquatorSteps;

   static const MatrixF topXfm( EulerF( -M_PI_F / 2.0f, 0, 0 ) );
   static const MatrixF bottomXfm( EulerF( M_PI_F / 2.0f, 0, 0 ) );

   MatrixF angMat;

   F32 polarStepSize = 0.0f;
   if ( mNumPolarSteps > 0 )
      polarStepSize = -( 0.5f * M_PI_F - mDegToRad( mPolarAngle ) ) / (F32)mNumPolarSteps;

   PROFILE_START(TSLastDetail_snapshots);

   S32 currDim = mDim;
   for ( S32 mip = 0; mip < mipLevels; mip++ )
   {
      if ( currDim < 1 )
         currDim = 1;
      
      dMemset( destBmp.getWritableBits(mip), 0, destBmp.getWidth(mip) * destBmp.getHeight(mip) * GFXFormat_getByteSize( format ) );
      dMemset( destNormal.getWritableBits(mip), 0, destNormal.getWidth(mip) * destNormal.getHeight(mip) * GFXFormat_getByteSize( format ) );

      bitmaps.clear();
      normalmaps.clear();

      F32 rotX = 0.0f;
      if ( mNumPolarSteps > 0 )
         rotX = -( mDegToRad( mPolarAngle ) - 0.5f * M_PI_F );

      // We capture the images in a particular order which must
      // match the order expected by the imposter renderer.

      imposterCap->begin( shape, mDl, currDim, mRadius, mCenter );

      for ( U32 j=0; j < (2 * mNumPolarSteps + 1); j++ )
      {
         F32 rotZ = -M_PI_F / 2.0f;

         for ( U32 k=0; k < mNumEquatorSteps; k++ )
         {            
            angMat.mul( MatrixF( EulerF( rotX, 0, 0 ) ),
                        MatrixF( EulerF( 0, 0, rotZ ) ) );

            imposterCap->capture( angMat, &imposter, &normalmap );

            bitmaps.push_back( imposter );
            normalmaps.push_back( normalmap );

            rotZ += equatorStepSize;
         }

         rotX += polarStepSize;

         if ( mIncludePoles )
         {
            imposterCap->capture( topXfm, &imposter, &normalmap );

            bitmaps.push_back(imposter);
            normalmaps.push_back( normalmap );

            imposterCap->capture( bottomXfm, &imposter, &normalmap );

            bitmaps.push_back( imposter );
            normalmaps.push_back( normalmap );
         }         
      }

      imposterCap->end();

      Point2I texSize( destBmp.getWidth(mip), destBmp.getHeight(mip) );

      // Ok... pack in bitmaps till we run out.
      for ( S32 y=0; y+currDim <= texSize.y; )
      {
         for ( S32 x=0; x+currDim <= texSize.x; )
         {
            // Copy the next bitmap to the dest texture.
            GBitmap* bmp = bitmaps.first();
            bitmaps.pop_front();
            destBmp.copyRect( bmp, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip );
            delete bmp;

            // Copy the next normal to the dest texture.
            GBitmap* normalmap = normalmaps.first();
            normalmaps.pop_front();
            destNormal.copyRect( normalmap, RectI( 0, 0, currDim, currDim ), Point2I( x, y ), 0, mip );
            delete normalmap;

            // Did we finish?
            if ( bitmaps.empty() )
               break;

            x += currDim;
         }

         // Did we finish?
         if ( bitmaps.empty() )
            break;

         y += currDim;
      }

      // Next mip...
      currDim /= 2;
   }

   PROFILE_END(); // TSLastDetail_snapshots

   delete imposterCap;
   delete shape;   
   
   
   // Should we dump the images?
   if ( Con::getBoolVariable( "$TSLastDetail::dumpImposters", false ) )
   {
      String imposterPath = mCachePath + ".imposter.png";
      String normalsPath = mCachePath + ".imposter_normals.png";

      FileStream stream;
      if ( stream.open( imposterPath, Torque::FS::File::Write  ) )
         destBmp.writeBitmap( "png", stream );
      stream.close();

      if ( stream.open( normalsPath, Torque::FS::File::Write ) )
         destNormal.writeBitmap( "png", stream );
      stream.close();
   }

   // DEBUG: Some code to force usage of a test image.
   //GBitmap* tempMap = GBitmap::load( "./forest/data/test1234.png" );
   //tempMap->extrudeMipLevels();
   //mTexture.set( tempMap, &GFXDefaultStaticDiffuseProfile, false );
   //delete tempMap;

   DDSFile *ddsDest = DDSFile::createDDSFileFromGBitmap( &destBmp );
   DDSUtil::squishDDS( ddsDest, GFXFormatDXT3 );

   DDSFile *ddsNormals = DDSFile::createDDSFileFromGBitmap( &destNormal );
   DDSUtil::squishDDS( ddsNormals, GFXFormatDXT5 );

   // Finally save the imposters to disk.
   FileStream fs;
   if ( fs.open( _getDiffuseMapPath(), Torque::FS::File::Write ) )
   {
      ddsDest->write( fs );
      fs.close();
   }
   if ( fs.open( _getNormalMapPath(), Torque::FS::File::Write ) )
   {
      ddsNormals->write( fs );
      fs.close();
   }

   delete ddsDest;
   delete ddsNormals;

   // If we did a begin then end it now.
   if ( !sceneBegun )
      GFX->endScene();
}
void TSLastDetail::update( bool forceUpdate )
{
   // This should never be called on a dedicated server or
   // anywhere else where we don't have a GFX device!
   AssertFatal( GFXDevice::devicePresent(), "TSLastDetail::update() - Cannot update without a GFX device!" );

   // Clear the materialfirst.
   SAFE_DELETE( mMatInstance );
   if ( mMaterial )
   {
      mMaterial->deleteObject();
      mMaterial = NULL;
   }

   // Make sure imposter textures have been flushed (and not just queued for deletion)
   TEXMGR->cleanupCache();

   // Get the real path to the source shape for doing modified time
   // comparisons... this might be different if the DAEs have been 
   // deleted from the install.
   String shapeFile( mCachePath );
   if ( !Platform::isFile( shapeFile ) )
   {
      Torque::Path path(shapeFile);
      path.setExtension("cached.dts");
      shapeFile = path.getFullPath();
      if ( !Platform::isFile( shapeFile ) )  
      {
         Con::errorf( "TSLastDetail::update - '%s' could not be found!", mCachePath.c_str() );
         return;
      }
   }

   // Do we need to update the imposter?
   const String diffuseMapPath = _getDiffuseMapPath();
   if (  forceUpdate || 
         Platform::compareModifiedTimes( diffuseMapPath, shapeFile ) <= 0 )
      _update();

   // If the time check fails now then the update must have not worked.
   if ( Platform::compareModifiedTimes( diffuseMapPath, shapeFile ) < 0 )
   {
      Con::errorf( "TSLastDetail::update - Failed to create imposters for '%s'!", mCachePath.c_str() );
      return;
   }

   // Figure out what our vertex format will be.
   //
   // If we're on SM 3.0 we can do multiple vertex streams
   // and the performance win is big as we send 3x less data
   // on each imposter instance.
   //
   // The problem is SM 2.0 won't do this, so we need to
   // support fallback to regular single stream imposters.
   //
   //mImposterVertDecl.copy( *getGFXVertexFormat<ImposterCorner>() );
   //mImposterVertDecl.append( *getGFXVertexFormat<ImposterState>(), 1 );
   //mImposterVertDecl.getDecl();   
   mImposterVertDecl.clear();
   mImposterVertDecl.copy( *getGFXVertexFormat<ImposterState>() );

   // Setup the material for this imposter.
   mMaterial = MATMGR->allocateAndRegister( String::EmptyString );
   mMaterial->mAutoGenerated = true;
   mMaterial->mDiffuseMapFilename[0] = diffuseMapPath;
   mMaterial->mNormalMapFilename[0] = _getNormalMapPath();
   mMaterial->mImposterLimits.set( (mNumPolarSteps * 2) + 1, mNumEquatorSteps, mPolarAngle, mIncludePoles );
   mMaterial->mTranslucent = true;
   mMaterial->mTranslucentBlendOp = Material::None;
   mMaterial->mTranslucentZWrite = true;
   mMaterial->mDoubleSided = true;
   mMaterial->mAlphaTest = true;
   mMaterial->mAlphaRef = 84;

   // Create the material instance.
   FeatureSet features = MATMGR->getDefaultFeatures();
   features.addFeature( MFT_ImposterVert );
   mMatInstance = mMaterial->createMatInstance();
   if ( !mMatInstance->init( features, &mImposterVertDecl ) )
   {
      delete mMatInstance;
      mMatInstance = NULL;
   }

   // Get the diffuse texture and from its size and
   // the imposter dimensions we can generate the UVs.
   GFXTexHandle diffuseTex( diffuseMapPath, &GFXDefaultStaticDiffuseProfile, String::EmptyString );
   Point2I texSize( diffuseTex->getWidth(), diffuseTex->getHeight() );

   _validateDim();

   S32 downscaledDim = mDim >> GFXTextureManager::getTextureDownscalePower(&GFXDefaultStaticDiffuseProfile);

   // Ok... pack in bitmaps till we run out.
   Vector<RectF> imposterUVs;
   for ( S32 y=0; y+downscaledDim <= texSize.y; )
   {
      for ( S32 x=0; x+downscaledDim <= texSize.x; )
      {
         // Store the uv for later lookup.
         RectF info;
         info.point.set( (F32)x / (F32)texSize.x, (F32)y / (F32)texSize.y );
         info.extent.set( (F32)downscaledDim / (F32)texSize.x, (F32)downscaledDim / (F32)texSize.y );
         imposterUVs.push_back( info );
         
         x += downscaledDim;
      }

      y += downscaledDim;
   }

   AssertFatal( imposterUVs.size() != 0, "hey" );

   mMaterial->mImposterUVs = imposterUVs;
}
Beispiel #8
0
//--------------------------------------------------------------
void ofApp::setup() {
    ofDirectory dir;
    ofVideoPlayer player;

    int edge = 2;

    ofxXmlSettings settings;
    settings.loadFile("settings.xml");


    ofVec2f movieSize(settings.getValue("movieSize:width", 128) + edge,
                      settings.getValue("movieSize:height", 128) + edge);
    ofVec2f texSize(settings.getValue("texSize:width", 1024),
                    settings.getValue("texSize:height", 1024));
    float duration = settings.getValue("duration", 1.0);
    float fps = settings.getValue("fps", 1.0);

    int numFrames = duration * fps;
    int numMovies = dir.listDir("movies");
    int totalFrames = numFrames * numMovies;

    float movieRatio = movieSize.x / movieSize.y;

    float texArea = texSize.x * texSize.y;
    float fitArea = texArea / (float)totalFrames;

    float fitHeight = sqrt(fitArea/movieRatio);
    float fitWidth = fitArea/fitHeight;

    ofVec2f fitSize(fitWidth,
                    fitHeight);

    ofVec2f numUnits(ceil(texSize.x / fitSize.x),
                     ceil(texSize.y / fitSize.y));

    ofVec2f size = texSize / numUnits;
    ofVec2f scale = movieSize / size;

    ofFile::removeFile("sprite.js");
    ofstream js;
    js.open (ofToDataPath("sprite.js").c_str(), std::ios::out | std::ios::app);
    js << "var sprite={coordinates:[";

    ofFbo fbo;
    fbo.allocate(texSize.x, texSize.y);
    fbo.begin();
    ofClear(0, 0, 0, 0);
    fbo.end();

    float column = -1;
    float row = -1;
    int frameIndex = 0;

    for (float i = 0; i < numMovies; i++) {
        player.loadMovie(dir.getPath(i));
        cout << dir.getPath(i) << endl;
        int playerNumFrames = player.getTotalNumFrames();
        float offset = (float)playerNumFrames / (float)numFrames;

        js << "[";
        for (float j = 0; j < numFrames; j++) {
            column = frameIndex % (int)numUnits.x;
            if(column == 0) row++;

            js << "\"-" << (column * movieSize.x) << "px -" << (row * movieSize.y) << "px\"";
            if(j < numFrames-1) js << ",";

            player.setFrame(j * offset+1);
            player.update();
            fbo.begin();
            player.draw(floor(column * size.x), floor(row * size.y), ceil(size.x), ceil(size.y));
            fbo.end();

            frameIndex++;
        }
        js << "]";
        if(i < numMovies-1) js << ",";

    }

    js << "]";
    js << ",duration:" << duration;
    js << ",image:\"sprite.png\"";
    js << ",numFrames:" << numFrames;
    js << ",numMovies:" << numMovies;
    js << ",width:" << movieSize.x - edge;
    js << ",height:" << movieSize.y - edge;
    js << ",backgroundSize:\"" << (texSize.x * scale.x) << "px " << (texSize.y * scale.y)<< "px\"";
    js << "};";
    js.close();

    ofPixels pixels;
    pixels.allocate(texSize.x, texSize.y, 4);
    fbo.readToPixels(pixels);
    ofSaveImage(pixels, "sprite.png");

    ofExit(0);
}
Beispiel #9
0
void XRandBG::update(float steptime)
{
	if (!m_isInited) return;
	float curTime = steptime * 0.001f;
	//出生的处理
	//m_bornTime -= curTime;
	//if (m_bornTime <= 0.0f)
	//{
	//	born();
	//	m_bornTime = XRand::randomf(0.75f, 1.25f) * m_avgBornTimer;
	//}
	//状态更新
	//方案1:
	//for (int i = 0; i < m_usedObjs.size(); ++i)
	//{
	//	if (!m_usedObjs[i]->update(curTime)) continue;

	//	m_freeObjs.push_back(m_usedObjs[i]);
	//	m_usedObjs.erase(m_usedObjs.begin() + i);
	//	--i;
	//	born();
	//}
	//方案2:
	int deadSum = 0;
	for (auto it = m_usedObjs.begin(); it != m_usedObjs.end();)
	{
		if (!(*it)->update(curTime))
		{
			++it;
			continue;
		}
		m_freeObjs.push_back(*it);
		it = m_usedObjs.erase(it);
		++deadSum;
	}
	for (int i = 0; i < deadSum; ++i)
	{//不分开处理会crash
		born();
	}
	//显示
	XVec2 texSize(m_tex.getOpWidth(), m_tex.getOpHeight());
	m_fbo.useFBO();
	XEG.clearScreen(XFColor::black);
	//XGL::setBlendAlpha();
	XGL::setBlendAdd();
	XVec2 s, pos;
#ifdef WITH_DRAW_OP
	glActiveTexture(GL_TEXTURE0);
	XGL::EnableTexture2D();
	XGL::BindTexture2D(m_tex.getTexGLID());
	glBegin(GL_QUADS);

	for (auto it = m_usedObjs.begin(); it != m_usedObjs.end(); ++it)
	{
		s = texSize * (*it)->m_scale * 0.5f;
		pos = (*it)->m_pos;

		glColor4fv(XFColor(1.0f, (*it)->m_alpha));
		glTexCoord2fv(XVec2::zero);
		glVertex2fv(pos - s);
		glTexCoord2fv(XVec2::zeroOne);
		glVertex2f(pos.x - s.x, pos.y + s.y);
		glTexCoord2fv(XVec2::one);
		glVertex2fv(pos + s);
		glTexCoord2fv(XVec2::oneZero);
		glVertex2f(pos.x + s.x, pos.y - s.y);
	}

	glEnd();
#else
	for (auto it = m_usedObjs.begin(); it != m_usedObjs.end(); ++it)
	{
		tmpSize = texSize * (*it)->m_scale;
		XRender::drawBlankPlane((*it)->m_pos - tmpSize * 0.5f,
			tmpSize, m_tex.getTexGLID(), nullptr, XFColor(1.0f, (*it)->m_alpha));
	}
#endif
	glReadPixels(0, 0, m_w, m_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_buff.getBuffer());
	m_fbo.removeFBO();
}