Results 1 to 1 of 1

Thread: ISEFfects - transformation demo

  1. #1
    Join Date
    Mar 2006
    Posts
    897

    Default ISEFfects - transformation demo

    here is the source I used to create the effects in this video:
    http://www.youtube.com/watch?v=12JJ3...layer_embedded

    the whole animation is a series of ISEffects transformations of the album cover, rendered to an AVI file.

    i use Windows Movie Maker to combine the AVI and the audio for the song.

    the first bit of code is a custom ISEffects transformation. it's a simple point attractor:
    Code:
    struct particle
    {
       typedef enum {linear, square, log, cos, sin, cost} attractMode;
    
       particle()
       {
       }
    
       double x, y;
       double mag;
       double maxDist;
       double fK;
       attractMode mode;
    
    };
    
    struct partInfo
    {
        std::vector<particle> particles;
        UINT w, h;
        double fCenterX, fCenterY;
    };
    
    // our custom XForm.
    BOOL CALLBACK ParticleXForm(const double wx, const double wy, 
                                                    double *x, double *y, 
                                                    const ISE_CALLBACK_DATA uUserData)
    {
       partInfo *pInfo = (partInfo*)uUserData;
    
       double vx=0, vy=0;
    
       for (std::vector<particle>::iterator it = pInfo->particles.begin(); 
              it != pInfo->particles.end(); 
              it++)
       {
          if ((*it).maxDist==0)
          {
             continue;
          }
    
          double offX=0, offY=0;
    
          double dx = wx - (*it).x, dy = wy - (*it).y;
    
          double fDist = sqrt(dx * dx + dy * dy);
    
          double mag = 0;
    
          switch ((*it).mode)
          {
          case particle::linear:
             if (fDist <= (*it).maxDist)
                mag = 1.0 - fDist / (*it).maxDist;  
             break;
    
            // ... other modes removed to keep the sample short...
          }
    
          mag *= (*it).mag;
    
          // new point lies this far out on the line
          double fNewDist = mag;
         
          // find the angle that the input points make with the +X axis
          if (dx != 0)
          {
             double fAngle = atan((double)dy / (double)dx);
            
             double nY = sin(fAngle) * fNewDist, nX = cos(fAngle) * fNewDist;
            
             // handle negative quadrants
             if (dx >= 0)
             {
                offX = nX; offY = nY;
             }
             else
             {
                offX = -nX; offY = -nY;
             }
          }
          else
          {
             // on y axis
             offX = 0;
    
             if (dy < 0)
                offY = -fNewDist;
             else
                offY = fNewDist ;
          }
    
          vx+=offX;
          vy+=offY;
       }
    
       *x = wx + vx;
       *y = wy + vy;
    
       return TRUE;
    }
    and here's the main function:

    Code:
    #include "ISource.h"
    #include "ISEffects.h"
    #include <io.h>
    #include <iostream>
    #include "math.h"
    
    ...
    
    void WarpIt()
    {
        bool bAVI = true;
    
        int frame_rate = 20;        // 20 per second
       
        // the song is 4 minutes and 4 seconds long.
        int totalFrames = frame_rate * (60 * 4 + 4);// 4:04 = 4880 frames;
        //int totalFrames = frame_rate * 10; // 10 sec demo, useful for testing
       
        char *lpFilename = "c:\\temp\\warp_out.avi";
       
        if (_access(lpFilename, 0) == 0)
        {
            if (!DeleteFile(lpFilename))
            {
                AfxMessageBox("Can't delete target. (Is it open in WMP?");
                return;
            }
        }
       
        ::CoInitialize(NULL);
        PAVIFILE pfile = NULL;
        PAVISTREAM ps = NULL, psCompressed = NULL;
       
        // get a DC so we can draw frames as they're rendered
        CClientDC dc(this);
       
        // output image size   
        UINT32 w = 400;
        UINT32 h = 300;
       
        // read the source image
        UINT32 bw, bh;
        HISSRC hSrc = IS40_OpenFileSource(DPIX"bizcover.bmp");
        HGLOBAL hImgDIB = IS40_ReadImage(hSrc, &bw, &bh, 2, 0);
        IS40_CloseSource(hSrc);
       
       
        BITMAPINFOHEADER * pInBMIH = (BITMAPINFOHEADER *)hImgDIB;
       
        UINT32 uBitCount;
        IS40_DIBBitCount(pInBMIH, &uBitCount);
       
        ASSERT(uBitCount==24);
        if (uBitCount!=24) return;
       
       
        BYTE *pInDIBPix = IS40_DIBPixelStart(pInBMIH);
       
        UINT32 inRowStride = IS40_GetDIBRowStride(bw, 24);
        UINT32 srcRowStride = IS40_GetDIBRowStride(w, 24);
       
        UINT dibSize = IS40_GetISDIBSize(w, h, 24, 0);
       
        // resized input
        BYTE *pSrcDIB = new BYTE[dibSize];
        BITMAPINFOHEADER * pSrcBMIH = (BITMAPINFOHEADER *)pSrcDIB;
        pSrcBMIH->biBitCount = 24;
        pSrcBMIH->biClrImportant = 0;
        pSrcBMIH->biClrUsed = 0;
        pSrcBMIH->biCompression = BI_RGB;
        pSrcBMIH->biHeight = h;
        pSrcBMIH->biPlanes = 1;
        pSrcBMIH->biSize = sizeof(BITMAPINFOHEADER);
        pSrcBMIH->biSizeImage = dibSize;
        pSrcBMIH->biWidth = w;
        pSrcBMIH->biXPelsPerMeter = 10000;
        pSrcBMIH->biYPelsPerMeter = 10000;
       
        BYTE *pSrcPix = IS40_DIBPixelStart(pSrcBMIH);
       
        // output
        BYTE *pOutDIB = new BYTE[dibSize];
        BITMAPINFOHEADER * pOutBMIH = (BITMAPINFOHEADER *)pOutDIB;
        pOutBMIH->biBitCount = 24;
        pOutBMIH->biClrImportant = 0;
        pOutBMIH->biClrUsed = 0;
        pOutBMIH->biCompression = BI_RGB;
        pOutBMIH->biHeight = h;
        pOutBMIH->biPlanes = 1;
        pOutBMIH->biSize = sizeof(BITMAPINFOHEADER);
        pOutBMIH->biSizeImage = dibSize;
        pOutBMIH->biWidth = w;
        pOutBMIH->biXPelsPerMeter = 0;
        pOutBMIH->biYPelsPerMeter = 0;
       
        BYTE *pOutPix = IS40_DIBPixelStart(pOutBMIH);
       
        if (bAVI)
        {
            AVI_Init();
           
            AVI_FileOpenWrite(&pfile, lpFilename);
           
            AVI_CreateStream(pfile, &ps, frame_rate,
                (unsigned long)0,// lpbi->biSizeImage,
                (int) pSrcBMIH->biWidth,
                (int) pSrcBMIH->biHeight);
           
            AVI_SetOptions(&ps, &psCompressed, pSrcBMIH);
           
            if (!psCompressed) return;
        }
       
        // init our Perlin noise source
        HISEPERLIN perlin = ISE40_InitializePerlinNoise3D(0);
        BYTE *perlinData = new BYTE[w * h];
        BYTE *perlinData2 = new BYTE[w * h];
       
        int iFrame = 0;
       
        int z = 0;
       
        double pi = acos(-1);
       
        BYTE *pInStart = pInDIBPix;
        IS40_ResizeImage(pInStart, bw, bh, inRowStride, 
                                      pSrcPix, w, h, srcRowStride, 3, 0, 0);
       
        memcpy(pOutPix, pSrcPix, h * srcRowStride);
       
        // loop over the total number of frames.
        for (z=0;z<totalFrames;z++)
        {  
            ISE40_ClearAllTransforms();
           
            double dz = (double)z;
            double totalDone = dz / (totalFrames - 1);
           
            ///////////////////////////////////////////////////////////////////
    
            // first effect is some warping, using a 
            // Perlin noise image as the input to a Bump XForm
            int part1Start = 0;
    
            // it will run for the first 1/3 of the animation
            int part1End = part1Start + totalFrames / 3;  
            int part1Size = part1End - part1Start;
    
            if (z >= part1Start && z < part1End)
            {
                double pz = z - part1Start;
                double partDone = pz / (double)(part1Size - 1.);
                double fScale = 0.15;
                double fZoomScale = part1Size/fScale;
                double fZoomSpeed = .5;
                double fFeatureSpeed = .01;
                double fz = fScale - pz / fZoomScale;
                double zpos = 0.001 + pz / 50.;
                ISE40_GetPerlinNoise3DSliceBYTE(perlin, perlinData, w, h, w, 
                                         fz * fZoomSpeed, zpos * partDone);
               
                // add some high-frequency noise, too
                double freq = 2;
                for (; freq >= 1. ; freq /= 2)
                {
                    ISE40_GetPerlinNoise3DSliceBYTE(perlin, perlinData2, w, h, w,
                                                freq * fz * fZoomSpeed, zpos * fFeatureSpeed);
                   
                    ISE40_AddBumpMapDisplacementTransform(w, h, 
                                                20. * partDone, perlinData2, w, h);
                }
               
                ISE40_AddBumpMapDisplacementTransform(w, h, 
                                      50. * partDone, perlinData, w, h);
            }
    
            ///////////////////////////////////////////////////////////////////
    
              // the next effect, comes in 5 seconds before the end of the first effect
            int part2Start = part1End - frame_rate * 5;
            int part2End = part2Start + totalFrames / 3;  // runs for 1/3 the total time
            int part2Size = part2End - part2Start;
    
              // the next two effects use the custom "particle" XForm, 
              // which is a simple point attractor. but we're using it backwards, 
             // sortof. instead of attracting, it's pulling image data from the 
             // outside of the image and shoving it up through the middle,
             // turning the image inside out.
            partInfo pia;
            pia.particles.clear();
            particle p0;
    
            if (z >= part2Start && z < part2End)
            {
                double pz = z - part2Start;
                double partDone = pz / (double)(part2Size - 1.);
    
                // vary the strength of the attractor over the lifetime of the effect
                double f = 1 + (.5 - cos(partDone * pi) / 2.0);
               
                p0.x = w/2;
                p0.y = h/2;
                p0.mag = 200 * (1.0 - f);
    
                p0.fK = 1;
                p0.maxDist = 400;
                p0.mode = particle::linear;
                pia.particles.push_back(p0);
               
                ISE40_AddUserTransform(w,h,ParticleXForm, (UINT32)&pia);
            }
    
            ///////////////////////////////////////////////////////////////////
                                                         
              // the next effect is basically the previous one running in 
              // reverse - sucking all the image data back in.
            int part3Start = part2End;
            int part3End = part3Start + totalFrames / 3;
            int part3Size = part3End - part3Start;
    
            if (z >= part3Start && z < part3End)
            {  
                double pz = z - part3Start;
                double partDone = pz / (double)(part3Size - 1.);
               
                double f = 2. - partDone;
                ASSERT(f >= 0);
               
                p0.x = w/2;
                p0.y = h/2;
                p0.mag = 200 * (1.0 - f);
                p0.fK = 1;
                p0.maxDist = 400;
                p0.mode = particle::linear;
                pia.particles.push_back(p0);
               
                ISE40_AddUserTransform(w,h,ParticleXForm, (UINT32)&pia);
            }
    
            ///////////////////////////////////////////////////////////////////
    
              // this effect comes in part way through the previous one. it's a 
              // spin XForm, which will vary in direction and intensity over the
              // effect's lifetime. 
            int part4Start = part2End + part3Size / 3;
            int part4End = totalFrames - (frame_rate * 4);
            int part4Size = part4End - part4Start;
    
            if (z >= part4Start && z < part4End)
            {  
                double pz = z - part4Start;
                double partDone = pz / (double)(part4Size - 1.);
               
                double sta = 45.0 * sin(2.0 * pi * partDone);
                double rad = 300 * sin(2.0 * pi * partDone);
               
                ISE40_AddSpinTransform(w, h, rad, sta, w/2, h/2);
            }
    
            ///////////////////////////////////////////////////////////////////
    
              // and finally, the last 4 seconds gets the dissolve. this is a 
              // "random" XForm which increases in intensity over the for seconds.
            int part5Start = totalFrames - (frame_rate * 4);
            int part5End = totalFrames - frame_rate / 2;
            int part5Size = part5End - part5Start;
    
            if (z >= part5Start && z < part5End)
            {  
                double pz = z - part5Start;
                double partDone = pz / (double)(part5Size - 1.);
               
                double sta = w * partDone;
               
                ISE40_AddRandomTransform(w,h,sta);
            }
    
            ///////////////////////////////////////////////////////////////////
    
              // perform whatever transforms we have lined-up
            UINT32 uMode = 2;
            ISE40_TransformProcess(pSrcPix, w, h - 20, srcRowStride, 
                            pOutPix, srcRowStride, 3, uMode | (1<<3), RGB(0,0,0));
    
              // draw the image
            IS40_StretchDrawDIB(dc.m_hDC, pOutBMIH, 0, 0, w, h); 
           
              // add the AVI frame
            if (bAVI) AVI_AddFrame(psCompressed, iFrame++, pOutBMIH);
           
              // monitor the progress
            char buf[10];
            sprintf(buf, "&#37;d\n", z);
            OutputDebugString(buf);
        }
       
         // add the final frame
        if (bAVI) AVI_AddFrame(psCompressed, iFrame++, pSrcBMIH);
       
        // clean up.   
        ISE40_DestroyPerlinNoise3D(perlin);
       
        GlobalFree(hImgDIB);
       
        // The end...
        if (bAVI)
        {
            AVI_CloseStream(ps, psCompressed, NULL);
           
            AVI_CloseFile(pfile);
           
            AVI_Exit();
        }
       
       
        delete [] pOutDIB;
        delete [] pSrcDIB;
       
        delete [] perlinData;
        delete [] perlinData2;
    }
    Last edited by Admin; 04-04-2009 at 12:29 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •