Clockowl 56 Posting Whiz

Hi guys,

I've got two loops, and I want to be able to continue; the outermost loop when the innermost loop finds something. How would I do that?

//(...)
    for (n = startStorage; n < quadcount; n++) {
        if (!notOptimized(n, optimized)) continue;
        int *x = &quadindex[n*4];
        for (eachX = 0; eachX < 4; eachX++) {
            if(facesPerVert[x[eachX]] > 4) continue n-loop, not eachX-loop!;
//(...)

TIA,
Clockowl

Clockowl 56 Posting Whiz

Lessons in pretty advanced C for me. Never seen it used before.

Clockowl 56 Posting Whiz

Thanks for pointing that out Aia.

Still I'd like to suggest changing it to the above code for readability. It seems like you don't need to make it a pointer. If you still like it to be a pointer, you can allocate some memory? I don't see the use of it, and it does make the program a bit more difficult imho.

Clockowl 56 Posting Whiz

Erm.. I think you are creating an array of 40 char pointers... Not sure tho.

char (*str)[40] =(*env)->GetStringUTFChars(env,s,0);

Try this:

char str[40];

Same seem to be errors in your loop. You are dereferencing <char *>str, making it a <char>... This is not needed and quite possibly wrong. If you want to access element 0 of <char *>str, you do it like this:

str[0]
Clockowl 56 Posting Whiz

Can't you use qsort() for this? It'd make the code a lot shorter... and easier I guess.

And a, a bit more precise about the error? What are you getting? Segfaults or just a not-sorted listbox?

Clockowl 56 Posting Whiz

I must admit I don't know 100% what you're trying to do, but as far as I know, a C-style string object _is_ a general character array. Maybe you can create a function that returns a <char *> and print that to your textbox? Make sure the memory the <char*> is pointing to is valid though.

Clockowl 56 Posting Whiz

*

for(t=1; t >= 4; t++){<code>}

You use comma's in the for() loop when you want multiple statements, like this:

int i, j, n;

for(i = j = 0, n = 5; i < 10 && j <= 20; printf("%d %d %d", i, j, n), i++, n = n * 2,  j += 2);

Nobody in his right mind would write the above code, but it shows that you use comma's to seperate statements, while you use semicolons to specify if they are initializing (gets executed before the loop, once), condition (checked after each iteration, break; if false), or erm.. well the last part. That just gets executed each loop, you *could* write all your code in there. :D

Clockowl 56 Posting Whiz

Well I'd recommend you to start out simple. Use the bounding box, understand the mechanism behind it and then apply it on other "simple" objects such as spheres, piramids, etc. Once you've done all that, you'll know a lot more and, I think, be readier for finding a method that works with any 3D object.

Clockowl 56 Posting Whiz

yeah, I only did the "myPrintfVerbose()" because else I'd need to #ifdef #endif like.. 70 printf()s, hahaha. Maybe I should regex search and replace the printf()s with #ifdef #endifs. Can't be done with regular search expressions I'm afraid. :(

PS: I removed all the verbose code, and it seemed not to matter, but thanks for the input.

Clockowl 56 Posting Whiz

I've tried using fastcall, alignment and other keywords/attributes for optimizations. Just like register and inline, they don't seem to change anything. GCC's pretty smart.

With that done, I guess this was it for the simple optimizations.

Here's the main algorithm:

int visualPart::simplifyQuads() {
    unsigned int *quadsPerVert = NULL;
    struct vertexMatch vertexMatchy;

    unsigned char *optimized = new unsigned char[quadcount * 4];
    memset(optimized, FALSE, sizeof(char) * quadcount * 4);

    printf("Simplifying to LOD level %u:\n", LOD+1);
    do {
        if (verbose) {
            printf("DEBUG:: Waiting for input...");
            char c = getchar();
            fflush(stdin);
            if (c == 'y') {
                LOD++;
                return 0;
            }
        }

        if (findVertexMatch(vertexMatchy, optimized) == 0) {
            printf("Done simplifying!\n");
            LOD++;
            updateQuadsPerVert(&quadsPerVert);
            removeLonelyVerts(quadsPerVert);
            return 0;
        }

        if (optimizeQuad(vertexMatchy, optimized) == 0) {
            quadcount--;
        }

    } while (true);

    LOD = 1;

    return 0;
}

Here is the function that also does a lot of scanning work. The findVertexMatch function:

int visualPart::findVertexMatch(struct vertexMatch &vertexMatchy,
                                     const unsigned char * const optimized) {
    unsigned int n, i, eachX, eachY, nextX, nextY;

    //for each quad that isn't optimized
    for (n = 0; n < quadcount; n++) {
        if (!notOptimized(n, optimized)) continue;
        //find another quad that isn't optimized
        for (i = n+1; i < quadcount; i++) {
            if (!notOptimized(i, optimized)) continue;
            //if they both aren't, create pointers to their 4 vertices. 
            int *x, *y;
            x = &quadindex[n*4];
            y = &quadindex[i*4];
            //if 2 of those vertices match, we have a match and are able to simplify it.
            //for each vertex of quad x
            for (eachX = 0; eachX …
Clockowl 56 Posting Whiz

EDIT: Didn't see the new[] Ouch. My bad, 100%.

Job well done on the program. However, when write is now called multiple times, each time it will allocate 100 bytes of memory to the pointer. This is called a memory leak. To fix that, make sure you only allocate the memory once (call new once).

Clockowl 56 Posting Whiz

Hey, in the past I've messed with those functions a bit, here're the results. Might help you a bit.

Finds a window given a caption:

#include <windows.h>
#include <stdio.h>

int main(int argc, char *argv[]){
  HWND hWnd;
  char windowName[512];

  printf("Window to look for: ");
  fgets(windowName, 512, stdin);
  if (hWnd = FindWindow(NULL, windowName)){
    printf("hWnd : %Xh with caption:\n\t",hWnd );
    GetWindowText(hWnd, windowName, 512);
  }
  else printf("No window found with that caption!");
  
  return 0;
}

Enumerates all windows and displays some information about them. Then allows to hide a window.

#include <windows.h>
#include <stdio.h>

char windowName[63];

int DisplayWindows(HWND hWnd, LPARAM lParam);

int main(int argc, char *argv[]){
  EnumWindows((WNDENUMPROC) DisplayWindows,(LPARAM) NULL);

  printf("What window do you want to hide? (give the hWnd)\nhWnd: ");
  int hWnd;
  scanf("%d", &hWnd);

  if (!IsWindow((HWND)hWnd)){
    printf("Window doesn't exist!");
    return 0;
  }

  if(!ShowWindow((HWND) hWnd, SW_HIDE)){
    printf("Window was already hidden...");
  }

  return 0;
}

int DisplayWindows(HWND hWnd, LPARAM lParam){
  GetWindowText(hWnd, windowName, 63);
  if (windowName[0] == '\0') return 1;

  printf("hWnd: %d\nClass: ", hWnd);
  GetClassName(hWnd, windowName, 63);
  puts(windowName);
  printf("Caption:");
  GetWindowText(hWnd, windowName, 63);
  puts(windowName);
  printf("\n");
  return 1;
}
Clockowl 56 Posting Whiz

Found the uses of new by the way, it is in the loading/copying part of my code, nothing to worry about. In the part that gets executed a lot there's no new.

Clockowl 56 Posting Whiz

Hey! I changed the (only) other vector to an array, and it got down to 4 seconds and 648 milliseconds. Just by changing from vector to arrays, it already executes 50% faster! Yeey.

Clockowl 56 Posting Whiz

WHOOOOOOHOOOOOOOOO!

On the first run, changed the vector<bool> to a C style char array, it finished in *trumpets*

5 seconds and 406 milliseconds!

3,3 seconds. Yeah. :D

PS:

Yesterday I changed the vector in struct VertexMatch to an array, and it actually was slower.. Any ideas? The usage of the vector's functions is minimal: A single reserve(2) and for the rest it's being treated like an array only accessing 2 elements. However, I'll change it again to an array and see what happens.

Clockowl 56 Posting Whiz

Whoohoo! So much reactions, thanks a lot! I'll implement them one by one, checking if it has an advantage and keep you guys up to date.

Yesterday when I posted, the time was 9 seconds and 481 milliseconds.

Now, it is was 8,586 milliseconds. (as in, 8 seconds, 586 ms.)

Clockowl 56 Posting Whiz

In 2D it's more or less simple no?

Check if one of the corners (read: vertices) pokes into the area of another square.

You can calculate the location of each vertex when you know the center of the square, it's length and it's rotation.

Do you know how to calculate the location of a vertex with that information?

Clockowl 56 Posting Whiz

Hey guys,

I've written quite a large piece of code the past few days, and today I've cleaned it up a bit, divided it into functions (I know, bad, should've done it the other way around) etc. etc. The project is a simple 3D thingamadingy, the program is able to display WaveFront .obj files using OpenGL, the GLUT library and C++. The part I was working on these few days was the LOD(Level of detail) algorithm. I'd like to use this thread to optimize that particular part as whole by optimizing each of its functions.

Now, with the program more or less working (working in most cases) I want to optimize some functions. I'll post the functions that get called the most, profiled by gcc/gprof. First, (a part of) the output of the profilation:

Flat profile:

Each sample counts as 0.01 seconds.
 no time accumulated

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
  0.00      0.00     0.00 100724734     0.00     0.00  visualPart::notOptimized(unsigned int, std::vector<bool, std::allocator<bool> > const&)
  0.00      0.00     0.00   196605     0.00     0.00  visualPart::myVerbosePrintf(char*, ...)
  0.00      0.00     0.00   147432     0.00     0.00  visualPart::rotateFour(int*)
  0.00      0.00     0.00    73736     0.00     0.00  operator new(unsigned int, void*)
  0.00      0.00     0.00    49160     0.00     0.00  vertexMatch::~vertexMatch()
  0.00      0.00     0.00    24587     0.00     0.00  visualPart::updateVertexMatches(std::vector<vertexMatch, std::allocator<vertexMatch> >&, std::vector<bool, std::allocator<bool> >&)
  0.00      0.00     0.00    24587     0.00     0.00  vertexMatch::vertexMatch()
  0.00      0.00     0.00    24573     0.00     0.00  visualPart::optimizeQuad(vertexMatch&, std::vector<bool, std::allocator<bool> >&)
  0.00      0.00     0.00    24573     0.00     0.00  vertexMatch::vertexMatch(vertexMatch const&)

(BTW: does anybody know how I can get gcc …

Clockowl 56 Posting Whiz

Tell them if they are within range...

Do a simulation in your head of 2 cubes having 8 vertices and 6 faces each. See if you can come up with any rules for collision.

PS:
The external library would have to know about the geometry of the object, the location of the object and the location/geometry of the objects it may collide with.

Clockowl 56 Posting Whiz

I think this comes down to:

Does it cross this line/face.

For a 3D-object you'd have to at least have a bounding box. When an other objects is IN the bounding box (easy to check) check if it hits one of the faces of your 3D object.

In 2D it's the same, but with lines. Use the bounding box to check if there are any objects near, then check the lines if one is being overlapped by another object.

(problems of course occur when the speed of the object that's incoming is so great that it'll "skip" the face/line. This happens in many commercial games too, so I don't think there's an easy solution for that).

Clockowl 56 Posting Whiz

By the way blrjohn, you could also try and fire up a console and execute your program from there. It won't disappear then. I dunno on which OS you are, but guessing it's Windows (80% market share or something eh):

Go to:

Start -> Run

type in "cmd"

Hit enter.

Behold the almighty black screen with often blinking cursor! :D

Typing in "cd" and then a path will let you change your directory. Type in "help" if you're in need of more help. Mastering the console is pretty convenient for developers.

Salem commented: This is how it should be done. +20
Clockowl 56 Posting Whiz

Oooooooooh okay, thanks.

Clockowl 56 Posting Whiz

Hi guys,

Could you tell me what's wrong with this code? I don't get why the compiler says it can't find a matching function...

#include <iostream>
#include <vector>
using namespace std;

template <class T>
int printVector(vector<T> &x){
    for(unsigned int col = 0; col < x.size(); col++){
        cout << x[col] << " ";
    }
    cout << endl;

    return 0;
}

int main(){
    vector<int> x;
    x.resize(10, 100);
    printVector(&x);

    return 0;
}

Errors:

C:\Code\TEMP\main.cpp||In function `int main()':|
C:\Code\TEMP\main.cpp|28|error: no matching function for call to `printVector(std::vector<int, std::allocator<int> >*)'|
||=== Build finished: 1 errors, 0 warnings ===|
Clockowl 56 Posting Whiz

First: read the link william posted. It's important.

And...
I've said some more, also answer those questions. It doesn't make sense you're using a <char*> when you've included <string> for example.

Clockowl 56 Posting Whiz

EDIT:

cin >> <char*> should work, but be sure to first make the <char*> point to some allocated memory with the new operator. And keep in mind that it won't parse spaces.

To parse spaces as well, use cin.getline();

Your output mechanism should work, but you might want to get rid of ios::app, just try it with ios::binary alone.

Clockowl 56 Posting Whiz

What errors are you getting?
Why isn't your code in code-tags?
... or indented for that matter?

You should post this along with your compiler.

You're trying to use cout without #including <iostream>. That won't work I guess.

You're #including <string>, but then using a <char*> instead of a <string>!

On top of that, you're declaring a pointer that's pointing to ANY place in the memory and ordering cin to write the input to that? I think that's what you were trying to do.

I don't know how cin and char* work together, but it's better to make per a <string> instead of a <char*>, so you won't run into memory troubles.

Clockowl 56 Posting Whiz

Try and compile such an example. If it compiles, see what's the difference in source code. Also look at included libraries.

Clockowl 56 Posting Whiz

Erm.. from what I can see there are tons of examples: C:\Program Files (x86)\FMOD SoundSystem\FMOD Programmers API Win32\examples Does your code do the same as the examples?

Clockowl 56 Posting Whiz

Better to post your full code so we can analyze it completely.

Clockowl 56 Posting Whiz

Okay, thanks. I get it now.

Clockowl 56 Posting Whiz

You forgot to call FSOUND_Init() perhaps?

Clockowl 56 Posting Whiz

"but I don't have access to that space because the individual places haven't been initialized by their constructor? xD"

So that is true? I can't access the reserved vectors because they aren't initialized yet and therefore do not exist...

So it'd work with chars, ints, floats.. but not with vectors. Okay, makes sense now.

Clockowl 56 Posting Whiz

No, because in the purse I would have "allocated" the space for "coins".

Now bear with me and change coins for ints, why is it giving me segfaults? I have allocated plenty of space for the coins by having a big purse, but I don't have access to that space because the individual places haven't been initialized by their constructor? xD

PS:
I see how I can use the vector (and other STL container classes) now, thanks for that, I'm just wondering how it all works underneath.

Clockowl 56 Posting Whiz

I don't have VC++, using GCC... But thanks for the explanation, although.. I don't really understand the underlying mechanism. I thought reserve() was like allocating some extra memory (with or without moving the whole vector), so that after that allocation I should be able to access the newly allocated elements.

But it only makes sure it doesn't need to reallocate when the vector grows to that size?

Clockowl 56 Posting Whiz

Well it's not necessarily bad.

If you are sure you are only going to recurse N-times, with N being.. say, below 2000, it's okay to do it recursive. I somewhere read: "Never hire a developer who computes the factorial using Recursion."

What it says it that you should avoid recursion if it's really simple to implement a non-recursive way. However, recursion is often more a more natural approach to solving problems, so feel free to use it, imho.

Clockowl 56 Posting Whiz

Thanks, worked like a charm!

How does that work then? It allocates more memory, but the vector doesn't grow in size?

and...

quadsPerVertIndex.resize(quadcount * 4);
    quadsPerVertIndex.clear();

Is that the correct way to allocate and clear (as in, set all elements to zero) a vector then?

Clockowl 56 Posting Whiz

Hi guys, I'm getting a segfault and I don't really understand why.. Here is the code

n, i, quadcount, quadPerVert and quadindex are all (arrays of) unsigned integers.

unsigned int *quadsPerVert = new unsigned int[quadcount * 4];
//(...)
vector<vector<unsigned int> > quadsPerVertIndex;
quadsPerVertIndex.reserve(quadcount * 4);

for (n = 0; n < quadcount * 4; n++) {
    //find vertex with >= 2 quads
    if (quadsPerVert[n] >= 2) {
        for (i = 0; i < quadcount * 4; i++) {
            if ((unsigned int)quadindex[i] == n) {
                quadsPerVertIndex[n].push_back(i/4); //it segfaults here
            }
        }
    }
}

I'm guessing that quadPerVertIndex[n] doesn't exist yet, but how can that be when I reserved it? And how would I fix this? I've looked at the vector methods, but I don't understand why this doesn't work.

TIA,
Nick

Clockowl 56 Posting Whiz

Then you need to parse the string first.. That can be pretty hard.

Try to understand how you do it, how you calculate f(x), write that down in steps on paper or on your computer and post it here.

Clockowl 56 Posting Whiz

w00ps

Clockowl 56 Posting Whiz

I forgot these:

Snippet from entity.h

class entity {
    vector<visualPart*> visualEntity;
};

Snippet from visualPart.h

class visualPart {
    friend class entity;

private:
    unsigned int LOD;

};

And for mitrmkar: I missed it, but I added it and updated the error message as well. It still doesn't work. EDIT:
But I missed the parenthesis. Didn't know they were necessary, thanks a lot!

Clockowl 56 Posting Whiz

Hi guys,

I tried rewriting my C-ish C++ function to true C++, but I'm failing so far:

The first function (working)

const visualPart * entity::getVisualPart(unsigned int wantLOD){
    for(unsigned int i = 0; i < visualEntity.size(); i++){
        if(visualEntity[i]->LOD == wantLOD){
            return visualEntity[i];
        }
    }

    return NULL;
}

And the second (not working)

const visualPart * entity::getVisualPart(unsigned int wantLOD){
    for(unsigned int i = 0; i < visualEntity.size(); i++){
        if(*(visualEntity.begin() + i)->LOD == wantLOD){
            return *(visualEntity.begin() + i);
        }
    }

    return NULL;
}

The error I get from GCC's G++:

(...)entity.cpp|50|error: request for member `LOD' in `*(&(&(((std::vector<visualPart*, std::allocator<visualPart*> >*)((entity*)this)) + 44u)->std::vector<_Tp, _Alloc>::begin [with _Tp = visualPart*, _Alloc = std::allocator<visualPart*>]())->__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator+ [with _Iterator = visualPart**, _Container = std::vector<visualPart*, std::allocator<visualPart*> >](((const ptrdiff_t&)((const ptrdiff_t*)(&((ptrdiff_t)i))))))->__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator-|

Could you please point out what I'm doing wrong?

TIA,
Nick

PS:

I've learned that iterators are pointers to the elements, so in this case, the iterators are of type visualPart**, therefore I dereference them once to get access to LOD, but this doesn't seem to work. Why not?

Clockowl 56 Posting Whiz

Yeah, but I think the problem is with fileSize being wrong, no? Suppose filesize would exactly the amount of bytes fread would read even in text-mode, like on linux and apple systems... there is no problem in using fread() then, right?

Clockowl 56 Posting Whiz

Behold! The error has been found. fread() shall be used on binary opened files only. Thanks go to Prabakar for noticing it. So, WaveFront .obj files are text files, but fread() can't be used to read blocks of data from files opened in textmode.

So, change the above code opening mode to "rb" and it works like a charm. :D

Or maybe it is because fread() convert CRLF to LF, thus fileSize being wrong... Whatever it is, on Windows it's not advisable to use it on text files containing CRLFs I guess.

Clockowl 56 Posting Whiz

Come to think of it, the size of the file doesn't matter. digi.obj is way bigger, almost 2MB, and it doesn't have the errors...

I've attached the textfile and the WaveFront .obj file as a zip for you to reproduce the errors I had.

Clockowl 56 Posting Whiz

Yeah sorry, didn't really think about it.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int loadAndOutputFile(char *loc){
    int fileSize = 0;
    printf("Opening file: \"%s\"\n", loc);

    FILE *pFile = fopen(loc, "r");
    if (pFile == NULL)
    {
        perror("fopen()");
        exit(1);
    }

    fseek(pFile, 0, SEEK_END);
    fileSize = ftell(pFile);
    rewind(pFile);

    printf("Allocating %d bytes...\n", fileSize);
    char *data = (char*) calloc(sizeof(char), fileSize*2);

    fread(data, 1, fileSize, pFile);
    if (ferror(pFile))
    {
        perror("fread()");
        exit(1);
    }
    memset(data+fileSize, 0, fileSize);
    int outputBytes = printf("%s", data);
    printf("\nOutput counted %d bytes.", outputBytes);

    fclose(pFile);

    printf("Done reading, parsing file now.\n");
    /*You can return here, the "wrong" data is now written to stdout*/
    return 123;
}

int main(int argc, char **argv){
  loadAndOutputFile(argv[1]);
  return 0;
}

It's best to tunnel the output, it only seems to occur with quite big files, anubis.obj is 458KB.

By the way, on my machine outputBytes is way bigger than fileSize. :(

Clockowl 56 Posting Whiz

Okay, first wanted to check if it really was a binary file instead of text file, so just created a big text file and read that in. Same results:

The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
The dog, Ziggi, fetched the paper and drooled all over it.
/*ORIGINAL EOF*/
it.

etched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

The dog, Ziggi, fetched the paper and drooled all over it.

Since the error persists I'm sure it also effects textfiles. I …

Clockowl 56 Posting Whiz

ooh w00ps. Yeah it was C code used in a C++ program as part of an object. If you remove the entity:: it'll work. I hope. ;)

AncientDragon, I'll open it in binary instead and have a look then, thanks.
Aia: Sorry for missing that, I didn't think you meant the writing-style, but then again I couldn't think of anything not conforming to C.

Clockowl 56 Posting Whiz

EDIT: You did mean the lay out right? Not something else?

There you go:


ANSI C syntaxing:

int entity::loadObj(const char *loc,\
                    float **retvertices, float **retgouraudnormals,\
                    int **rettriangleindex, int **retquadindex,\
                    unsigned int *quadcount, unsigned int *trianglecount)
{

    float *vertices, *gouraudnormals;
    int *triangleindex, *quadindex;
    float *normals, *verttext;
    int *trianglenormals, *quadnormals;

    clock_t startTime = clock();
    int fileSize = 0;
    int n, i, j;
    printf("Opening file: \"%s\"\n", loc);

    FILE *pFile = fopen(loc, "r");
    if (pFile == NULL)
    {
        dbgError("fopen()");
        exit(1);
    }

    fseek(pFile, 0, SEEK_END);
    fileSize = ftell(pFile);
    rewind(pFile);

    char *data = (char*) calloc(sizeof(char), fileSize + 20);

    fread(data, 1, fileSize, pFile);
    if (ferror(pFile))
    {
        dbgError("fread()");
        exit(1);
    }
    puts(data);

    fclose(pFile);

    printf("Done reading, parsing file now.\n");
    /*You can return here, the "wrong" data is now written to stdout*/
    return 123;
    /*Or you can continue and let it load all the way*/

    TIMEELAPSED

    printf("Removing #IND if there...");
    char *pIND = data;
    n = 0;
    while (1)
    {
        pIND = strstr(pIND, "#IND");
        if (pIND != NULL)
        {
            memcpy(pIND, "0000", sizeof(char) * 4);
            n++;
        }
        else break;
    }
    printf("Removed %d #INDs\n", n);
    TIMEELAPSED

    printf("Counting lines and determining maximum length...");
    int maxLen, lenCount;
    int lines;

    for (i = lines = lenCount = maxLen = 0; i <= fileSize; i++)
    {
        if (data[i] == '\n')
        {
            lines++;
            lenCount++;
            if (lenCount > maxLen) maxLen = lenCount;
            lenCount = 0;
        }
        lenCount++;
    }

    printf("Counted %d lines, maximum length: %d\n", lines, maxLen);
    TIMEELAPSED

    printf("Allocating %d strings of %d chars...", lines, maxLen);
    char **parsedText = (char**) calloc(sizeof(char*), lines);
    for (n =
Clockowl 56 Posting Whiz

Oh, here's the code by the way. It looks like a lot of code, but the error is in the first 40 lines.

loadObj:

int entity::loadObj(const char *loc,\
            float **retvertices, float **retgouraudnormals,\
            int **rettriangleindex, int **retquadindex,\
            unsigned int *quadcount, unsigned int *trianglecount){

  float *vertices, *gouraudnormals;
  int *triangleindex, *quadindex;
  float *normals, *verttext;
  int *trianglenormals, *quadnormals;

  clock_t startTime = clock();
  int fileSize = 0;
  int n, i, j;
  printf("Opening file: \"%s\"\n", loc);

  FILE *pFile = fopen(loc, "r");
  if(pFile == NULL){
      dbgError("fopen()");
      exit(1);
  }

  fseek(pFile, 0, SEEK_END);
  fileSize = ftell(pFile);
  rewind(pFile);

  char *data = (char*) calloc(sizeof(char), fileSize + 20);

  fread(data, 1, fileSize, pFile);
  if(ferror(pFile)){
      dbgError("fread()");
      exit(1);
  }
  puts(data);

  fclose(pFile);

  printf("Done reading, parsing file now.\n");
  /*You can return here, the "wrong" data is now written to stdout*/
  return 123;
  /*Or you can continue and let it load all the way*/

  TIMEELAPSED

  printf("Removing #IND if there...");
  char *pIND = data;
  n = 0;
  while(1){
    pIND = strstr(pIND, "#IND");
    if(pIND != NULL){
      memcpy(pIND, "0000", sizeof(char) * 4);
      n++;
    }
    else break;
  }
  printf("Removed %d #INDs\n", n);
  TIMEELAPSED

  printf("Counting lines and determining maximum length...");
  int maxLen, lenCount;
  int lines;

  for (i = lines = lenCount = maxLen = 0; i <= fileSize; i++){
    if (data[i] == '\n'){
      lines++;
      lenCount++;
      if(lenCount > maxLen) maxLen = lenCount;
      lenCount = 0;
    }
    lenCount++;
  }

  printf("Counted %d lines, maximum length: %d\n", lines, maxLen);
  TIMEELAPSED

  printf("Allocating %d strings of %d chars...", lines, maxLen);
  char **parsedText = (char**) calloc(sizeof(char*), lines);
  for(n = 0; n < lines; n++){
    parsedText[n] = (char*) malloc(sizeof(char)
Clockowl 56 Posting Whiz

Hey guys,

I'm parsing this WaveFront .obj file, still (for those that have read the previous post), but it has some really weird error in it that I haven't seen in a program before.

The parsing algorithm starts out like this:

Open the file in textmode.
Get filesize
Allocate buffer with calloc, size: filesize + 1
Read file in buffer
Count the lines

Now, the filesize is correct, and reading goes okay too: ferror() doesn't report any errors.

The linecount is, however, off! :( I'm using this code:

printf("Counting lines and determining maximum length...");
  int maxLen, lenCount;
  int lines;

  for (i = lines = lenCount = maxLen = 0; i <= fileSize; i++){
    if (data[i] == '\n'){
      lines++;
      lenCount++;
      if(lenCount > maxLen) maxLen = lenCount;
      lenCount = 0;
    }
    lenCount++;
  }

  printf("Counted %d lines, maximum length: %d\n", lines, maxLen);

In short:

current char a newline?
Yes: 
  add one to lines and chars
  update max string length
No: 
  add one to chars

Well, I couldn't think that that piece of code is wrong since it's so simple. Besides, it worked with numerous files and I've used that same code in the past. But the linecount is off. So I output char *data. Just to make sure, the output (cut away a lot, it's a 458KB file ;))

f 2483//3522 2134//3498 2028//3437
f 2527//3523 2028//3437 2906//3436
f 2555//3524 2527//3523 2906//3436
f 2556//3525 2555//3524 2906//3436
f 2558//3526 2556//3525 2906//3436
f 2558//3526 2906//3436 2560//3515
f 2527//3523 2483//3522 …