Re: Textures on pfGeoSet.

New Message Reply Date view Thread view Subject view Author view

Frederic Francis (pffred++at++llogic.com)
Thu, 20 Nov 1997 13:31:06 -0500 (EST)


On Thu, 20 Nov 1997, Frederic Francis wrote:

>
> Ola Jorge,
>
> I think that the default geostate associated with instances of
> pfdNewSphere is the global one. So probably the best thing to do
> is to give it it's own and apply a texture on that geostate:
>
> pfGeoSet *s = pfdNewSphere(...);
> pfGeoState *g = new pfGeoState;
>
> // Attach geostate to geoset
> s->setGstate(g);
>
> // If you want to load a file from disk
> pfTexture *tex = new pfTexture; tex->loadFile("mytexturefile.rgb");
>
>
> // Apply texture
> g->setMode(PFSTATE_ENTEXTURE, PF_ON);
> g->setAttr(PFSTATE_TEXTURE, tex);
>
> // Define texture environment
> pfTexEnv *tenv = new pfTexEnv;
> tenv->setMode(PFTE_DECAL); // for example
> g->setAttr(PFSTATE_TEXENV, tenv);
>
>
>
> Best Regards,
>
> Fred.
>

Sorry Jorge,

 I forgot that pfdSpheres have no texture coordinates.

 For my penance:

 Here is a program that makes a textured sphere uses an
equirectangular texture mapping. It uses a different
tesselation than pfdSphere but which is better for
equirectangular mappings. It also allows you to make
spherical sections.

Disclaimer: This code is a tad old but it seems to work.
            Please give me a shout if it misbehaves.

                        Best Regards,

                        Fred.

__________________________________________________________________

Frederic Francis email: fred++at++llogic.com
Director of Technology phone: 1-514-287-1166
Lateral Logic fax: 1-514-287-3360
__________________________________________________________________

____________________________________________________________________

#include <stdlib.h>
#include <math.h>
#include <iostream.h>

#include <Performer/pfdu.h>
#include <Performer/pfdb/pfpfb.h>

#include <Performer/pr/pfTexture.h>
#include <Performer/pf/pfGeode.h>
#include <Performer/pr/pfGeoSet.h>
#include <Performer/pr/pfLinMath.h>

const double twoPi = 2.0 * M_PI;
const double oneOverPi = 1.0 / M_PI;
const double oneOverTwoPi = 1.0 / twoPi;

pfNode *makeSphereSection(int nTris, float minP, float maxP,
                         float minT, float maxT, char *texFile);

void main (int argc, char *argv[]) {

 if ((argc > 8) || (argc < 7) )
 {
  cerr << " Usage: " << argv[0] << " outFile numTris minPhi
  maxPhi minTheta maxTheta textureFile";
  cerr << endl << endl << " Note: PI = 1 so phi's range is [0,2] and theta's range is [0,1]";
  cerr << endl << " The last argument is optional, if no texture file is given the";
  cerr << endl << " sphere is assigned tex coords but nothing is mapped onto it.";
  cerr << endl << " The actual number of triangles will be greater than numTris.";
  cerr << endl << endl;
 }
 else {
  const int numTris = atoi(argv[2]);
  float minPhi = atof(argv[3]);
  float maxPhi = atof(argv[4]);
  float minTheta = atof(argv[5]);
  float maxTheta = atof(argv[6]);
  char *textureFile = argv[7];

  int goodPhi = ( (maxPhi > minPhi) && (minPhi >= 0.0) && (maxPhi <= 2.0) );
  int goodTheta = ( (maxTheta > minTheta) && (minTheta >= 0.0) && (maxTheta <= 1.0) );
  int goodTriNum = ( (numTris > 49) && (numTris < 500000) );
  int cool = goodPhi && goodTheta && goodTriNum;
   
  if ( !cool ) {
    if ( (!goodPhi) || (!goodTheta) )
      cerr << " Usage: pi = 1 so phi's range is [0,2] and theta's range is [0,1]" << endl;
    if ( (!goodTriNum) )
      cerr << " Usage: Number of triangles restricted between 50 and 500,000" << endl;
  }

   
  else {
    pfInit();
    pfMultiprocess(0);
    pfConfig();

    minPhi = minPhi * M_PI; minTheta = minTheta * M_PI;
    maxPhi = maxPhi * M_PI; maxTheta = maxTheta * M_PI;
    pfNode *s = makeSphereSection(numTris, minPhi, maxPhi, minTheta, maxTheta, textureFile);
    pfdStoreFile_pfb(s, argv[1]);

    pfExit();
  }
 }
}

pfNode *makeSphereSection(int numTris, float minPhi, float maxPhi,float minTheta, float maxTheta, char *textureFile) {

    int numPrims = fceil(fsqrt(numTris));
    int primLengths = 2 * (((numPrims + 2) + 1) / 2) ;
    int numVertices = numPrims * primLengths;

    float deltaPhi = (maxPhi - minPhi) / (0.5f * numPrims);
    float deltaTheta = (maxTheta - minTheta) / numPrims;

    pfGeode *sphere = new pfGeode;
    pfGeoSet *sphereGset = new pfGeoSet;
    pfGeoState *sphereGState = new pfGeoState;

    pfVec3 *sphereCoords = (pfVec3 *) new(numVertices * sizeof(pfVec3)) pfMemory;
    pfVec3 *sphereNorms = (pfVec3 *) new(numVertices * sizeof(pfVec3)) pfMemory;
    pfVec4 *sphereColor = (pfVec4 *) new(sizeof(pfVec4)) pfMemory;
    pfVec2 *sphereTexCoords = (pfVec2 *) new(numVertices * sizeof(pfVec2)) pfMemory;

    int i,j,k;
    float x,y,z,u,v;
    float phi, theta;

    theta = minTheta;
    for(i=0;i<numPrims;i++) {
       phi = minPhi;
       for(j=0;j<primLengths;j+=2) {
          k = j + i * primLengths;
          x = cos(phi) * sin(theta);
           y = sin(phi) * sin(theta);
           z = cos(theta);
           
          sphereCoords[k].set(x,y,z); sphereNorms[k].set(x,y,z);

          sphereTexCoords[k][0] = phi * oneOverTwoPi;
          sphereTexCoords[k][1] = 1.0f - (theta * oneOverPi);

          k++;
          x = cos(phi) * sin((theta + deltaTheta));
           y = sin(phi) * sin((theta + deltaTheta));
           z = cos((theta + deltaTheta));

          sphereCoords[k].set(x,y,z); sphereNorms[k].set(x,y,z);

          sphereTexCoords[k][0] = phi * oneOverTwoPi;
          sphereTexCoords[k][1] = 1.0f - ((theta + deltaTheta) * oneOverPi);

          phi += deltaPhi;
       }
       theta += deltaTheta;
    }

    sphereGset->setAttr(PFGS_COORD3, PFGS_PER_VERTEX, sphereCoords, NULL);
    sphereGset->setAttr(PFGS_NORMAL3, PFGS_PER_VERTEX, sphereNorms, NULL);
    sphereGset->setAttr(PFGS_TEXCOORD2, PFGS_PER_VERTEX, sphereTexCoords, NULL);

    sphereColor[0].set(1.0f,1.0f,1.0f,1.0f);
    sphereGset->setAttr(PFGS_COLOR4, PFGS_OVERALL, sphereColor, NULL);

    int *spherePrimitivesLength = (int *) new(numPrims * sizeof(int)) pfMemory;
    for(i=0;i<numPrims;i++) spherePrimitivesLength[i] = primLengths;

    sphereGset->setPrimLengths(spherePrimitivesLength);
    sphereGset->setPrimType(PFGS_TRISTRIPS);
    sphereGset->setNumPrims(numPrims);

    sphereGState->setMode(PFSTATE_ENTEXTURE, PF_ON);

    if (textureFile) {
        pfTexture *tex = new pfTexture; tex->loadFile(textureFile);
        pfTexEnv *tenv = new pfTexEnv; tenv->setMode(PFTE_DECAL);

        sphereGState->setAttr(PFSTATE_TEXTURE, tex); sphereGState->setAttr(PFSTATE_TEXENV, tenv);
    }

   sphereGset->setGState(sphereGState);
   sphere->addGSet(sphereGset);
   return(sphere);
}

  

=======================================================================
List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
            Submissions: info-performer++at++sgi.com
        Admin. requests: info-performer-request++at++sgi.com


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:56:13 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.