FSPathMakeRef

hyperutila
Unregistered
 
Post: #1
Hey there. I can't seem to get FSPathMakeRef to work. I'm using it to gain access to an image file to load it as an OpenGL texture. My program compiles fine, but every time I run it, I get a bus error from FSPathMakeRef. FSPathMakeRef is only in Carbon, right? So, here's the part that really confuses me. I'm using glut for my window handling. For some reason, glut requires me to include the Cocoa framework in order to compile. I don't remember it ever doing that before. In fact, I got this whole thing to work on another project that I wrote a little over a year ago. Does the presence of both the Carbon and Cocoa frameworks mess up FSPathMakeRef's ability to work? Or what am I doing wrong?


Code:
void MakeFSSpecFromPath(const char* path,FSSpec* spec){
  FSRef fsref;
  //bus error at FSPathMakeRef
  err=FSPathMakeRef((const UInt8*)path,&fsref,NULL);
  err=FSGetCatalogInfo(&fsref,kFSCatInfoNone,NULL,NULL,spec,NULL);
}

void LoadTexturesGL(const char* name){
  Rect natbound;
  MakeFSSpecFromPath(name,&spec);
  err=GetGraphicsImporterForFile(&spec,&gi);
  cr=GraphicsImportGetNaturalBounds(gi,&natbound);
  buffer=malloc(3*natbound.right*natbound.bottom);
  err=QTNewGWorldFromPtr(&gw,k24RGBPixelFormat,&natbound,NULL,NULL,0,buffer,3*natbound.right);
  cr=GraphicsImportSetGWorld(gi,gw,NULL);
  cr=GraphicsImportDraw(gi);
  err=CloseComponent(gi);
  glEnable(GL_TEXTURE_2D);
  glGenTextures(1,&texture[texnum]);
  glBindTexture(GL_TEXTURE_2D,texture[texnum]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR​);
  glTexImage2D(GL_TEXTURE_2D,0,3,natbound.right,natbound.bottom,0,GL_RGB,GL_U​NSIGNED_BYTE,buffer);
  gluBuild2DMipmaps(GL_TEXTURE_2D,3,natbound.right,natbound.bottom,GL_RGB,GL_​UNSIGNED_BYTE,buffer);
  DisposeGWorld(gw);
  free(buffer);
  texnum++;
}
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #2
Hi there and welcome,

Not sure if I can help you here - that looks alright. To clear some things up: GLUT is built around Cocoa, but in earlier days, GLUT pulled in Cocoa by itself (iirc) so that's why you didn't see it before. Cocoa and Carbon co-exist just fine, so that's not the problem either. I would recommend you to turn on GuardMalloc in the Debug menu and then debugging the application. It will stop on the first memory error, which might be elsewhere than you think.

Otherwise, feel free to post your project and I'll take a peek. Smile
Quote this message in a reply
hyperutila
Unregistered
 
Post: #3
According to the debugger, the problem is in my FSRef. It says "Can't get path". Which I don't quite understand. I passed it the address like I was supposed to! Apparently, I accessed the wrong memory block. Why that is, I have no idea. If anyone has any thoughts, they'd be welcome!
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #4
Hm, can't get path? That sounds like your file path is messed up - what are you passing to it? Please throw in a printf of path before you crash, it might be corrupted or malformed. Not that it would kill the application, but still...
Quote this message in a reply
hyperutila
Unregistered
 
Post: #5
Thanks so much for your help. It's still not working though. I added a printf of the path right before, and it's not corrupt or anything. This may sound really dumb, but I pretty much always put all of my code in 1 source file, and only have 1 header file. But this time, I decided to create multiple source files for the sake of organization. That isn't at all related to this problem, is it? I mean, considering that that's all I'm doing differently from the times that it worked, am I wrong to think that might be related to my problem?
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #6
Code:
// you probably should check if the file exists first...
FSRef fsref;
Boolean isdir = false; //<--not sure if you need this
  //bus error at FSPathMakeRef
  err=FSPathMakeRef((const UInt8*)path,&fsref,&isdir);
  err=FSGetCatalogInfo(&fsref,kFSCatInfoNone,NULL,NULL,spec,NULL);
Also, make sure "name" is a fully qualified path string.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
hyperutila
Unregistered
 
Post: #7
You suggested that I post my project for you to look over. Is this the best way to post projects? So far, my project has only 3 files:

ProjectXI.c
ProjectXI.h
Interface.c

Interface.c includes a parser for Direct X model files that loads in mesh data and texture mapping data. It also contains the texture loading:

Code:
#include "ProjectXI.h"

void loadXModel(char *filename,Model *m){
  FILE *file=NULL;
  file=fopen(filename,"r");
  if (!file)
    senderror(1,filename);
  char oneline[256];
  fgets(oneline,256,file);
  fgets(oneline,256,file);
  fgets(oneline,256,file);
  fgets(oneline,256,file);
  fgets(oneline,256,file);
  fgets(oneline,256,file);
  fscanf(file,"%d;\n",&(m->numverts));
  m->verticies=(Vertex*)malloc(m->numverts*sizeof(Vertex));
  int i;
  for (i=0;i<m->numverts-1;i++){
    fscanf(file,"%f; %f; %f;,\n",&m->verticies[i].x,&m->verticies[i].y,&m->verticies[i].z);
  }
  fscanf(file,"%f; %f; %f;;\n",&m->verticies[m->numverts-1].x,&m->verticies[m->numverts-1].y,&m->verticies[m->numverts-1].z);
  fscanf(file,"%d;\n",&m->numfaces);
  m->quads=(QUAD*)malloc(m->numfaces*sizeof(QUAD));
  m->triangles=(TRI*)malloc(m->numfaces*sizeof(TRI));
  for (i=0;i<m->numfaces-1;i++){
    int typeface=0;
    fscanf(file,"%d; ",&typeface);
    if (typeface==3){
      fscanf(file,"%d; %d; %d;,\n",&m->triangles->vertexreference[0],&m->triangles->vertexreference[1],&m->triangles->vertexreference[2]);
      m->triangles++;
      m->numtris++;
    }
    else if (typeface==4){
      fscanf(file,"%d; %d; %d; %d;,\n",&m->quads->vertexreference[0],&m->quads->vertexreference[1],&m->quads->vertexreference[2],&m->quads->vertexreference[3]);
      m->quads++;
      m->numquads++;
    }
    else
      senderror(2,"Error Parsing Model File");
  }
  int typeface=0;
  fscanf(file,"%d; ",&typeface);
  if (typeface==3){
    fscanf(file,"%d; %d; %d;;\n",&m->triangles->vertexreference[0],&m->triangles->vertexreference[1],&m->triangles->vertexreference[2]);
    m->triangles++;
    m->numtris++;
  }
  else if (typeface==4){
    fscanf(file,"%d; %d; %d; %d;;\n",&m->quads->vertexreference[0],&m->quads->vertexreference[1],&m->quads->vertexreference[2],&m->quads->vertexreference[3]);
    m->quads++;
    m->numquads++;
  }
  else
    senderror(2,"Error Parsing Model File");
  while(1){
    if (strstr(oneline,"MeshTextureCoords {"))
      break;
    fgets(oneline,256,file);
  }
  fscanf(file,"%d;\n",&m->numtex);
  for (i=0;i<m->numtex;i++){
    fscanf(file,"%e;%e;,\n",&m->verticies[i].tx,&m->verticies[i].ty);
  }
  fclose(file);
  m->quads-=m->numquads;
  m->triangles-=m->numtris;
}

void DrawModel(Model m){
  if (!m.textrue){
    int i;
    glBegin(GL_TRIANGLES);
    for (i=0;i<m.numtris;i++){
      glVertex3f(m.verticies[*((m.triangles+i)->vertexreference)].x,m.verticies[*((m.triangles+i)->vertexreference)].y,m.verticies[*((m.triangles+i)->vertexreference)].z);
      glVertex3f(m.verticies[*((m.triangles+i)->vertexreference+1)].x,m.verticies[*((m.triangles+i)->vertexreference+1)].y,m.verticies[*((m.triangles+i)->vertexreference+1)].z);
      glVertex3f(m.verticies[*((m.triangles+i)->vertexreference+2)].x,m.verticies[*((m.triangles+i)->vertexreference+2)].y,m.verticies[*((m.triangles+i)->vertexreference+2)].z);
    }
    glEnd();
    glBegin(GL_QUADS);
    for (i=0;i<m.numquads;i++){
      glVertex3f(m.verticies[*((m.quads+i)->vertexreference)].x,m.verticies[*((m.quads+i)->vertexreference)].y,m.verticies[*((m.quads+i)->vertexreference)].z);
      glVertex3f(m.verticies[*((m.quads+i)->vertexreference+1)].x,m.verticies[*((m.quads+i)->vertexreference+1)].y,m.verticies[*((m.quads+i)->vertexreference+1)].z);
      glVertex3f(m.verticies[*((m.quads+i)->vertexreference+2)].x,m.verticies[*((m.quads+i)->vertexreference+2)].y,m.verticies[*((m.quads+i)->vertexreference+2)].z);
      glVertex3f(m.verticies[*((m.quads+i)->vertexreference+3)].x,m.verticies[*((m.quads+i)->vertexreference+3)].y,m.verticies[*((m.quads+i)->vertexreference+3)].z);
    }
    glEnd();
  }
}

void senderror(int num,char *error){
  printf("Error of type %d\n",num);
  printf("%s\n",error);
}

//Texture Importing

void MakeFSSpecFromPath(const char* path,FSSpec* spec){
  FSRef *fsref=NULL;
  //bus error at FSPathMakeRef
  printf("%s\n",path);
  err=FSPathMakeRef((const UInt8*)path,fsref,NULL);
  err=FSGetCatalogInfo(fsref,kFSCatInfoNone,NULL,NULL,spec,NULL);
}

void LoadTexturesGL(const char* name){
  Rect natbound;
  MakeFSSpecFromPath(name,&spec);
  err=GetGraphicsImporterForFile(&spec,&gi);
  cr=GraphicsImportGetNaturalBounds(gi,&natbound);
  buffer=malloc(3*natbound.right*natbound.bottom);
  err=QTNewGWorldFromPtr(&gw,k24RGBPixelFormat,&natbound,NULL,NULL,0,buffer,3*natbound.right);
  cr=GraphicsImportSetGWorld(gi,gw,NULL);
  cr=GraphicsImportDraw(gi);
  err=CloseComponent(gi);
  glEnable(GL_TEXTURE_2D);
  glGenTextures(1,&texture[texnum]);
  glBindTexture(GL_TEXTURE_2D,texture[texnum]);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR​);
  glTexImage2D(GL_TEXTURE_2D,0,3,natbound.right,natbound.bottom,0,GL_RGB,GL_U​NSIGNED_BYTE,buffer);
  gluBuild2DMipmaps(GL_TEXTURE_2D,3,natbound.right,natbound.bottom,GL_RGB,GL_​UNSIGNED_BYTE,buffer);
  DisposeGWorld(gw);
  free(buffer);
  texnum++;
}

Here's ProjectXI.h:

Code:
#ifndef PROJECTXI_H
#define PROJECTXI_H

#include <Carbon/Carbon.h>
#include <Quicktime/Quicktime.h>
#include <Quicktime/ImageCompression.h>
#include <ApplicationServices/ApplicationServices.h>
#include <CoreServices/CoreServices.h>
//#include <OpenGL/OpenGL.h>
//#include <OpenAL/alut.h>
//#include <OpenGL/gl.h>
//#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#include <stdio.h>
#include <string.h>

//definitions:

#define NUM_TEXTURES 5

#define PI_ 3.14159265358979323846

#define kWindowWidth 640
#define kWindowHeight 480

//type definitions:

typedef struct Vertex{
  GLfloat x,y,z;//position
  GLfloat mx,my,mz;//rotation
  GLfloat tx,ty;//texture coords
}Vertex;

typedef struct XY{
  GLfloat x,y;
}XY;

typedef struct TRI{
  int vertexreference[3];
}TRI;

typedef struct QUAD{
  int vertexreference[4];
}QUAD;

typedef struct Model{
  int numverts,numfaces,numtex,numtris,numquads,texture,textrue;
  char *texfilename;
  Vertex *verticies;
  TRI *triangles;
  QUAD *quads;
}Model;

//Interface.c function prototypes:

void loadXModel(char*,Model*);
void senderror(int,char*);
void MakeFSSpecFromPath(const char*,FSSpec*);
void LoadTexturesGL(const char*);

//ProjectXI.c function prototypes:

GLvoid InitGL(GLvoid);
GLvoid DrawGLScene(GLvoid);
void ReSizeGLScene(int width,int height);
GLvoid IdleGL(GLvoid);
void initvars();

//OpenGL Variable Definitions:

GLuint texture[NUM_TEXTURES];

int texnum;
float rot;

GLUquadricObj *quad;


//texture handling


OSStatus err;
Rect natbounds;
FSSpec spec;
GraphicsImportComponent gi;
ComponentResult cr;
GWorldPtr gw;
void *buffer;

#endif

Most of ProjectXI.c is not even going to be used. It's mostly OpenGL initialization and such that will be used later. Here it is:

Code:
#include "ProjectXI.h"

//Global Variable Initialization:

GLfloat lighta[]={0.01f,0.01f,0.01f,0.001f};
GLfloat lightd[]={1.0f,1.0f,1.0f,1.0f};
GLfloat lightp[]={10.0f,10.0f,10.0f,1.0f};
GLfloat lights[]={1.0f,1.0f,1.0f,1.0f};

Model house;

void ReSizeGLScene(int width,int height){
  if (height==0)
    height=1;
  glViewport(0, 0, width, height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

void initvars(){
  rot=0;
}

GLvoid IdleGL(GLvoid){
  rot+=0.1;
  DrawGLScene();
}

GLvoid InitGL(GLvoid){
  glShadeModel(GL_SMOOTH);
  glClearDepth(1.0f);
  glEnable(GL_DEPTH_TEST);
  //glDepthMask(GL_TRUE);
  glDepthFunc(GL_LEQUAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

  glEnable(GL_DITHER);

  quad=gluNewQuadric();
  gluQuadricNormals(quad,GLU_SMOOTH);

  glEnable(GL_LIGHTING);
  glLightfv(GL_LIGHT1,GL_AMBIENT,lighta);
  glLightfv(GL_LIGHT1,GL_DIFFUSE,lightd);
  glLightfv(GL_LIGHT1,GL_POSITION,lightp);
  glLightfv(GL_LIGHT1,GL_SPECULAR,lights);
  glEnable(GL_LIGHT1);
  //glEnable(GL_COLOR_MATERIAL);

  glFrontFace(GL_CCW);
}

GLvoid DrawGLScene(GLvoid){
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glTranslatef(0.0f,0.0f,-10.0f);
  glRotatef(rot,0.0f,1.0f,0.0f);

  //glColor3f(1.0f,0.0f,0.0f);
  glMateriali(GL_FRONT,GL_SHININESS,100);
  GLfloat spec[]={1.0f,1.0f,1.0f,1.0f};
  glMaterialfv(GL_FRONT,GL_SPECULAR,spec);
  GLfloat amb[]={0.1f,0.0f,0.0f,1.0f};
  glMaterialfv(GL_FRONT,GL_AMBIENT,amb);
  GLfloat diff[]={1.0f,0.0f,0.0f,1.0f};
  glMaterialfv(GL_FRONT,GL_DIFFUSE,diff);
  //glColorMaterial(GL_FRONT,GL_SPECULAR && GL_AMBIENT && GL_SHININESS);
  //gluSphere(quad,1.0f,32,32);

  DrawModel(house);

  glFlush();
  glutSwapBuffers();
  //glColor4f(0.0f,0.0f,0.0f,1.0f);
}

void accFrustum(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far,GLdouble pixdx,GLdouble pixdy,GLdouble eyedx,GLdouble eyedy,GLdouble focus) {
  GLdouble xwsize, ywsize;
  GLdouble dx, dy;
  GLint viewport[4];
  glGetIntegerv (GL_VIEWPORT, viewport);
  xwsize = right - left;
  ywsize = top - bottom;
  dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
  dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glFrustum (left + dx, right + dx, bottom + dy, top + dy,near, far);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef (-eyedx, -eyedy, 0.0);
}

void accPerspective(GLdouble fovy,GLdouble aspect,GLdouble near,GLdouble far,GLdouble pixdx,GLdouble pixdy,GLdouble eyedx,GLdouble eyedy,GLdouble focus) {
  GLdouble fov2,left,right,bottom,top;
  fov2 = ((fovy*PI_) / 180.0) / 2.0;
  top = near / (cos(fov2) / sin(fov2));
  bottom = -top;
  right = top * aspect;
  left = -right;
  accFrustum (left, right, bottom, top, near, far, pixdx, pixdy, eyedx, eyedy, focus);
}

void ummdisplay(){
  int jitter;
  glClear(GL_ACCUM_BUFFER_BIT);
  for (jitter = 0; jitter < 10; jitter++) {
    accPerspective (45.0f,(GLfloat)kWindowWidth/(GLfloat)kWindowHeight,0.1f,100.0f, 0.1*(jitter-5), 0.1*(jitter-5), 0.0, 0.0, 1.0);
    DrawGLScene();
    glAccum(GL_ACCUM, 1.0/10);
  }
  glAccum (GL_RETURN, 1.0);
  glFlush();
  glutSwapBuffers();  
}

void loadAllTextures(){
  LoadTexturesGL("Textures/House.jpg");
}

void loadAllModels(){
  house.texture=0;
  house.textrue=0;
  loadXModel("Models/Data/house1.x",&house);
}

int main(int argc,char* argv[]){
  texnum=0;
  loadAllTextures();
  loadAllModels();
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_ACCUM);
  glutInitWindowSize(kWindowWidth,kWindowHeight);
  glutInitWindowPosition(100,100);
  glutCreateWindow(argv[0]);
  InitGL();
  initvars();
  glutDisplayFunc(ummdisplay);
  glutIdleFunc(IdleGL);
  glutReshapeFunc(ReSizeGLScene);
  ReSizeGLScene(kWindowWidth, kWindowHeight);
  DrawGLScene();
  //glutFullScreen();
  glutMainLoop();
  return 0;
}
Quote this message in a reply
hyperutila
Unregistered
 
Post: #8
Fenris Wrote:I would recommend you to turn on GuardMalloc in the Debug menu and then debugging the application. It will stop on the first memory error, which might be elsewhere than you think.

By the way, I can't find GuardMalloc in the Debug Menu. There's a "MallocDebug" under "Launch using Performance Tool" which is under the Debug Menu. Maybe I have an older version or something
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #9
You need to read up on pointers.

Code:
FSRef ref;
FSPathMakeRef(name, &ref, NULL);

[edit]whoops, Kelvin already said that![/edit]
Quote this message in a reply
hyperutila
Unregistered
 
Post: #10
Well, that's basically what I've got. In fact, I think I originally wrote it that way. Both of these two work the same:


Code:
FSRef *fsref=NULL;
  err=FSPathMakeRef((const UInt8*)path,fsref,NULL);

Code:
FSRef fsref;
  err=FSPathMakeRef((const UInt8*)path,&fsref,NULL);

In the first one, fsref is a pointer, in the second one, fsref isn't, but I pass it's address, so it has the same effect. However, written either way, I still get a bus error.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #11
They are not in any sense the same. The first one should segfault; the second one should not (unless path is an invalid pointer or not NUL-terminated, neither of which seemed likely from your code).
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #12
Heh, now I see it too.
What Keith the Cookie is suggesting is that:
FSRef fsRef;
&fsRef <-- this is the adress of an FSRef that actually exists, that you can manipulate.

while

FSRef *fsRef = NULL
fsRef <-- this is just a pointer to nothing. If you manipulate it, you manipulate whatever is at adress 0x0 in memory, which is forbidden.

Notice the difference here? In both cases you have pointers to FSRefs, that much is granted. But in the first case, that pointer points to a real FSRef that has been allocated, in the second case, you have an empty pointer that points to whatever. Smile
Quote this message in a reply
hyperutila
Unregistered
 
Post: #13
Right, I understand. But the problem is that I still get a bus error either way. I originally wrote it like this:

Code:
FSRef fsref;
  err=FSPathMakeRef((const UInt8*)path,&fsref,NULL);

Then I tried this:

Code:
FSRef *fsref=(FSRef*)malloc(sizeof(FSRef));
  err=FSPathMakeRef((const UInt8*)path,fsref,NULL);

then this:

Code:
FSRef *fsref=NULL;
  err=FSPathMakeRef((const UInt8*)path,fsref,NULL);

And every single one of them got the same error. So, Yeah, you're right, the most recent posting shows it passing a null pointer. Which wouldn't work, but it still gets that same error anyway.
Quote this message in a reply
hyperutila
Unregistered
 
Post: #14
By the way, I don't know if this is useful to anyone, but feel free to use my direct x file parser. It's in the code above, part of interface.c. It loads in the verticies, faces and texture mapping information. It skips over loading the normals. That wouldn't be hard to add though. I just didn't have a need for that, so I didn't include it. Anyway, at least I know that that part of my program works! Smile So help yourself!
Quote this message in a reply
hyperutila
Unregistered
 
Post: #15
For anyone who's interested, I found the answer to the problem:

OSStatus err;

is defined in ProjectXI.h as a global variable. I'm not quite sure why, but it is mapped to a part of memory that cannot be accessed by Interface.c. So, if I just don't set err equal to the result of FSPathMakeRef, then it works. I'm not sure why, but that's all I need. Thanks so much for all of your help!
Quote this message in a reply
Post Reply