Beispiel #1
0
GLUSboolean GLUSAPIENTRY glusLoadObjFile(const GLUSchar* filename, GLUSshape* shape)
{
	GLUSboolean result;

    FILE* f;

    GLUSchar buffer[GLUS_BUFFERSIZE];
    GLUSchar identifier[3];

    GLUSfloat x, y, z;
    GLUSfloat s, t;

    GLUSfloat* vertices = 0;
    GLUSfloat* normals = 0;
    GLUSfloat* texCoords = 0;

    GLUSuint numberVertices = 0;
    GLUSuint numberNormals = 0;
    GLUSuint numberTexCoords = 0;

    GLUSfloat* triangleVertices = 0;
    GLUSfloat* triangleNormals = 0;
    GLUSfloat* triangleTexCoords = 0;

    GLUSuint totalNumberVertices= 0;
    GLUSuint totalNumberNormals= 0;
    GLUSuint totalNumberTexCoords= 0;

    GLUSuint facesEncoding = 0;

    if (!filename || !shape)
    {
        return GLUS_FALSE;
    }

    memset(shape, 0, sizeof(GLUSshape));

    f = fopen(filename, "r");

    if (!f)
    {
        return GLUS_FALSE;
    }

    if (!glusMallocTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords))
    {
    	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

    	fclose(f);

    	return GLUS_FALSE;
    }

    while (!feof(f))
    {
        if (fgets(buffer, GLUS_BUFFERSIZE, f) == 0)
        {
        	if (ferror(f))
        	{
        		glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                fclose(f);

                return GLUS_FALSE;
        	}
        }

        if (strncmp(buffer, "vt", 2) == 0)
        {
            if (numberTexCoords == GLUS_MAX_ATTRIBUTES)
            {
            	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                fclose(f);

                return GLUS_FALSE;
            }

            sscanf(buffer, "%s %f %f", identifier, &s, &t);

            texCoords[2 * numberTexCoords + 0] = s;
            texCoords[2 * numberTexCoords + 1] = t;

            numberTexCoords++;
        }
        else if (strncmp(buffer, "vn", 2) == 0)
        {
            if (numberNormals == GLUS_MAX_ATTRIBUTES)
            {
            	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                fclose(f);

                return GLUS_FALSE;
            }

            sscanf(buffer, "%s %f %f %f", identifier, &x, &y, &z);

            normals[3 * numberNormals + 0] = x;
            normals[3 * numberNormals + 1] = y;
            normals[3 * numberNormals + 2] = z;

            numberNormals++;
        }
        else if (strncmp(buffer, "v", 1) == 0)
        {
            if (numberVertices == GLUS_MAX_ATTRIBUTES)
            {
            	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                fclose(f);

                return GLUS_FALSE;
            }

            sscanf(buffer, "%s %f %f %f", identifier, &x, &y, &z);

            vertices[4 * numberVertices + 0] = x;
            vertices[4 * numberVertices + 1] = y;
            vertices[4 * numberVertices + 2] = z;
            vertices[4 * numberVertices + 3] = 1.0f;

            numberVertices++;
        }
        else if (strncmp(buffer, "f", 1) == 0)
        {
            GLUSchar* token;

            GLUSint vIndex, vtIndex, vnIndex;

            GLUSuint edgeCount = 0;

            token = strtok(buffer, " \t");
            token = strtok(0, " \n");

            if (!token)
            {
            	continue;
            }

            // Check faces
			if (strstr(token, "//") != 0)
			{
				facesEncoding = 2;
			}
			else if (strstr(token, "/") == 0)
			{
				facesEncoding = 0;
			}
			else if (strstr(token, "/") != 0)
			{
				GLUSchar* c = strstr(token, "/");

				c++;
				
				if (!c)
				{
					continue;
				}
				
				if (strstr(c, "/") == 0)
				{
					facesEncoding = 1;
				}
				else
				{
					facesEncoding = 3;
				}
			}

            while (token != 0)
            {
                vIndex = -1;
                vtIndex = -1;
                vnIndex = -1;

                switch (facesEncoding)
                {
                    case 0:
                        sscanf(token, "%d", &vIndex);
                        break;
                    case 1:
                        sscanf(token, "%d/%d", &vIndex, &vtIndex);
                        break;
                    case 2:
                        sscanf(token, "%d//%d", &vIndex, &vnIndex);
                        break;
                    case 3:
                        sscanf(token, "%d/%d/%d", &vIndex, &vtIndex, &vnIndex);
                        break;
                }

                vIndex--;
                vtIndex--;
                vnIndex--;

                if (vIndex >= 0)
                {
                    if (edgeCount < 3)
                    {
                        if (totalNumberVertices >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleVertices[4*totalNumberVertices], &vertices[4*vIndex], 4*sizeof(GLUSfloat));

                        totalNumberVertices++;
                    }
                    else
                    {
                        if (totalNumberVertices >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleVertices[4*(totalNumberVertices)], &triangleVertices[4*(totalNumberVertices-edgeCount)], 4*sizeof(GLUSfloat));
                        memcpy(&triangleVertices[4*(totalNumberVertices+1)], &triangleVertices[4*(totalNumberVertices-1)], 4*sizeof(GLUSfloat));
                        memcpy(&triangleVertices[4*(totalNumberVertices+2)], &vertices[4*vIndex], 4*sizeof(GLUSfloat));

                        totalNumberVertices += 3;
                    }
                }
                if (vnIndex >= 0)
                {
                    if (edgeCount < 3)
                    {
                        if (totalNumberNormals >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleNormals[3*totalNumberNormals], &normals[3*vnIndex], 3*sizeof(GLUSfloat));

                        totalNumberNormals++;
                    }
                    else
                    {
                        if (totalNumberNormals >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleNormals[3*(totalNumberNormals)], &triangleNormals[3*(totalNumberNormals-edgeCount)], 3*sizeof(GLUSfloat));
                        memcpy(&triangleNormals[3*(totalNumberNormals+1)], &triangleNormals[3*(totalNumberNormals-1)], 3*sizeof(GLUSfloat));
                        memcpy(&triangleNormals[3*(totalNumberNormals+2)], &normals[3*vnIndex], 3*sizeof(GLUSfloat));

                        totalNumberNormals += 3;
                    }
                }
                if (vtIndex >= 0)
                {
                    if (edgeCount < 3)
                    {
                        if (totalNumberTexCoords >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleTexCoords[2*totalNumberTexCoords], &texCoords[2*vtIndex], 2*sizeof(GLUSfloat));

                        totalNumberTexCoords++;
                    }
                    else
                    {
                        if (totalNumberTexCoords >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
                        {
                        	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

                            fclose(f);

                            return GL_FALSE;
                        }

                        memcpy(&triangleTexCoords[2*(totalNumberTexCoords)], &triangleTexCoords[2*(totalNumberTexCoords-edgeCount)], 2*sizeof(GLUSfloat));
                        memcpy(&triangleTexCoords[2*(totalNumberTexCoords+1)], &triangleTexCoords[2*(totalNumberTexCoords-1)], 2*sizeof(GLUSfloat));
                        memcpy(&triangleTexCoords[2*(totalNumberTexCoords+2)], &texCoords[2*vtIndex], 2*sizeof(GLUSfloat));

                        totalNumberTexCoords += 3;
                    }
                }

                edgeCount++;

                token = strtok(0, " \n");
            }
        }
    }

    fclose(f);

    result = glusCopyObjData(shape, totalNumberVertices, triangleVertices, totalNumberNormals, triangleNormals, totalNumberTexCoords, triangleTexCoords);

    glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

    if (result)
    {
    	glusCalculateTangentSpacef(shape);
    }

    return result;
}
static GLUSboolean glusParseObjFile(const GLUSchar* filename, GLUSshape* shape, GLUSwavefront* wavefront)
{
	GLUSboolean result;

	FILE* f;

	GLUSchar buffer[GLUS_BUFFERSIZE];
	GLUSchar identifier[7];

	GLUSfloat x, y, z;
	GLUSfloat s, t;

	GLUSfloat* vertices = 0;
	GLUSfloat* normals = 0;
	GLUSfloat* texCoords = 0;

	GLUSuint numberVertices = 0;
	GLUSuint numberNormals = 0;
	GLUSuint numberTexCoords = 0;

	GLUSfloat* triangleVertices = 0;
	GLUSfloat* triangleNormals = 0;
	GLUSfloat* triangleTexCoords = 0;

	GLUSuint totalNumberVertices = 0;
	GLUSuint totalNumberNormals = 0;
	GLUSuint totalNumberTexCoords = 0;

	GLUSuint facesEncoding = 0;

	// Material and groups

	GLUSchar name[GLUS_MAX_STRING];

	GLUSuint numberIndicesGroup = 0;
	GLUSuint numberMaterials = 0;
	GLUSuint numberGroups = 0;

	GLUSgroupList* currentGroupList = 0;

	// Objects

	GLUSuint numberObjects = 0;

	if (!filename || !shape)
	{
		return GLUS_FALSE;
	}

	memset(shape, 0, sizeof(GLUSshape));

	f = fopen(filename, "r");

	if (!f)
	{
		return GLUS_FALSE;
	}

	if (!glusMallocTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords))
	{
		glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

		fclose(f);

		return GLUS_FALSE;
	}

	while (!feof(f))
	{
		if (fgets(buffer, GLUS_BUFFERSIZE, f) == 0)
		{
			if (ferror(f))
			{
				glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

				fclose(f);

				return GLUS_FALSE;
			}
		}

		if (wavefront)
		{
			if (strncmp(buffer, "mtllib", 6) == 0)
			{
				sscanf(buffer, "%s %s", identifier, name);

				if (numberMaterials == 0)
				{
					wavefront->materials = 0;
				}

				if (!glusLoadMaterial(name, &wavefront->materials))
				{
					glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

					fclose(f);

					return GLUS_FALSE;
				}

				numberMaterials++;
			}
			else if (strncmp(buffer, "usemtl", 6) == 0)
			{
				if (!currentGroupList || currentGroupList->group.materialName[0] != '\0')
				{
					GLUSgroupList* newGroupList;

					newGroupList = (GLUSgroupList*)malloc(sizeof(GLUSgroupList));

					if (!newGroupList)
					{
						glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

						fclose(f);

						return GLUS_FALSE;
					}

					memset(newGroupList, 0, sizeof(GLUSgroupList));

					strcpy(newGroupList->group.name, name);

					if (numberGroups == 0)
					{
						wavefront->groups = newGroupList;
					}
					else
					{
						if (!currentGroupList)
						{
							free(newGroupList);

							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GLUS_FALSE;
						}

						currentGroupList->next = newGroupList;

						currentGroupList->group.numberIndices = numberIndicesGroup;
						numberIndicesGroup = 0;
					}

					currentGroupList = newGroupList;

					numberGroups++;
				}

				//

				sscanf(buffer, "%s %s", identifier, name);

				strcpy(currentGroupList->group.materialName, name);
			}
			else if (strncmp(buffer, "g", 1) == 0)
			{
				GLUSgroupList* newGroupList;

				sscanf(buffer, "%s %s", identifier, name);

				newGroupList = (GLUSgroupList*)malloc(sizeof(GLUSgroupList));

				if (!newGroupList)
				{
					glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

					fclose(f);

					return GLUS_FALSE;
				}

				memset(newGroupList, 0, sizeof(GLUSgroupList));

				strcpy(newGroupList->group.name, name);

				if (numberGroups == 0)
				{
					wavefront->groups = newGroupList;
				}
				else
				{
					if (!currentGroupList)
					{
						free(newGroupList);

						glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

						fclose(f);

						return GLUS_FALSE;
					}

					currentGroupList->next = newGroupList;

					currentGroupList->group.numberIndices = numberIndicesGroup;
					numberIndicesGroup = 0;
				}

				currentGroupList = newGroupList;

				numberGroups++;
			}
		}

		if (strncmp(buffer, "o", 1) == 0)
		{
			if (numberObjects == GLUS_MAX_OBJECTS)
			{
				glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

				fclose(f);

				return GLUS_FALSE;
			}

			numberObjects++;
		}
		else if (strncmp(buffer, "vt", 2) == 0)
		{
			if (numberTexCoords == GLUS_MAX_ATTRIBUTES)
			{
				glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

				fclose(f);

				return GLUS_FALSE;
			}

			sscanf(buffer, "%s %f %f", identifier, &s, &t);

			texCoords[2 * numberTexCoords + 0] = s;
			texCoords[2 * numberTexCoords + 1] = t;

			numberTexCoords++;
		}
		else if (strncmp(buffer, "vn", 2) == 0)
		{
			if (numberNormals == GLUS_MAX_ATTRIBUTES)
			{
				glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

				fclose(f);

				return GLUS_FALSE;
			}

			sscanf(buffer, "%s %f %f %f", identifier, &x, &y, &z);

			normals[3 * numberNormals + 0] = x;
			normals[3 * numberNormals + 1] = y;
			normals[3 * numberNormals + 2] = z;

			numberNormals++;
		}
		else if (strncmp(buffer, "v", 1) == 0)
		{
			if (numberVertices == GLUS_MAX_ATTRIBUTES)
			{
				glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

				fclose(f);

				return GLUS_FALSE;
			}

			sscanf(buffer, "%s %f %f %f", identifier, &x, &y, &z);

			vertices[4 * numberVertices + 0] = x;
			vertices[4 * numberVertices + 1] = y;
			vertices[4 * numberVertices + 2] = z;
			vertices[4 * numberVertices + 3] = 1.0f;

			numberVertices++;
		}
		else if (strncmp(buffer, "f", 1) == 0)
		{
			GLUSchar* token;

			GLUSint vIndex, vtIndex, vnIndex;

			GLUSuint edgeCount = 0;

			token = strtok(buffer, " \t");
			token = strtok(0, " \n");

			if (!token)
			{
				continue;
			}

			// Check faces
			if (strstr(token, "//") != 0)
			{
				facesEncoding = 2;
			}
			else if (strstr(token, "/") == 0)
			{
				facesEncoding = 0;
			}
			else if (strstr(token, "/") != 0)
			{
				GLUSchar* c = strstr(token, "/");

				c++;

				if (!c)
				{
					continue;
				}

				if (strstr(c, "/") == 0)
				{
					facesEncoding = 1;
				}
				else
				{
					facesEncoding = 3;
				}
			}

			while (token != 0)
			{
				vIndex = -1;
				vtIndex = -1;
				vnIndex = -1;

				switch (facesEncoding)
				{
					case 0:
						sscanf(token, "%d", &vIndex);
					break;
					case 1:
						sscanf(token, "%d/%d", &vIndex, &vtIndex);
					break;
					case 2:
						sscanf(token, "%d//%d", &vIndex, &vnIndex);
					break;
					case 3:
						sscanf(token, "%d/%d/%d", &vIndex, &vtIndex, &vnIndex);
					break;
				}

				vIndex--;
				vtIndex--;
				vnIndex--;

				if (vIndex >= 0)
				{
					if (edgeCount < 3)
					{
						if (totalNumberVertices >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleVertices[4 * totalNumberVertices], &vertices[4 * vIndex], 4 * sizeof(GLUSfloat));

						totalNumberVertices++;
						numberIndicesGroup++;
					}
					else
					{
						if (totalNumberVertices >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleVertices[4 * (totalNumberVertices)], &triangleVertices[4 * (totalNumberVertices - edgeCount)], 4 * sizeof(GLUSfloat));
						memcpy(&triangleVertices[4 * (totalNumberVertices + 1)], &triangleVertices[4 * (totalNumberVertices - 1)], 4 * sizeof(GLUSfloat));
						memcpy(&triangleVertices[4 * (totalNumberVertices + 2)], &vertices[4 * vIndex], 4 * sizeof(GLUSfloat));

						totalNumberVertices += 3;
						numberIndicesGroup += 3;
					}
				}
				if (vnIndex >= 0)
				{
					if (edgeCount < 3)
					{
						if (totalNumberNormals >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleNormals[3 * totalNumberNormals], &normals[3 * vnIndex], 3 * sizeof(GLUSfloat));

						totalNumberNormals++;
					}
					else
					{
						if (totalNumberNormals >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleNormals[3 * (totalNumberNormals)], &triangleNormals[3 * (totalNumberNormals - edgeCount)], 3 * sizeof(GLUSfloat));
						memcpy(&triangleNormals[3 * (totalNumberNormals + 1)], &triangleNormals[3 * (totalNumberNormals - 1)], 3 * sizeof(GLUSfloat));
						memcpy(&triangleNormals[3 * (totalNumberNormals + 2)], &normals[3 * vnIndex], 3 * sizeof(GLUSfloat));

						totalNumberNormals += 3;
					}
				}
				if (vtIndex >= 0)
				{
					if (edgeCount < 3)
					{
						if (totalNumberTexCoords >= GLUS_MAX_TRIANGLE_ATTRIBUTES)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleTexCoords[2 * totalNumberTexCoords], &texCoords[2 * vtIndex], 2 * sizeof(GLUSfloat));

						totalNumberTexCoords++;
					}
					else
					{
						if (totalNumberTexCoords >= GLUS_MAX_TRIANGLE_ATTRIBUTES - 2)
						{
							glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

							fclose(f);

							return GL_FALSE;
						}

						memcpy(&triangleTexCoords[2 * (totalNumberTexCoords)], &triangleTexCoords[2 * (totalNumberTexCoords - edgeCount)], 2 * sizeof(GLUSfloat));
						memcpy(&triangleTexCoords[2 * (totalNumberTexCoords + 1)], &triangleTexCoords[2 * (totalNumberTexCoords - 1)], 2 * sizeof(GLUSfloat));
						memcpy(&triangleTexCoords[2 * (totalNumberTexCoords + 2)], &texCoords[2 * vtIndex], 2 * sizeof(GLUSfloat));

						totalNumberTexCoords += 3;
					}
				}

				edgeCount++;

				token = strtok(0, " \n");
			}
		}
	}

	fclose(f);

	if (wavefront && currentGroupList)
	{
		currentGroupList->group.numberIndices = numberIndicesGroup;
		numberIndicesGroup = 0;
	}

	result = glusCopyObjData(shape, totalNumberVertices, triangleVertices, totalNumberNormals, triangleNormals, totalNumberTexCoords, triangleTexCoords);

	glusFreeTempMemory(&vertices, &normals, &texCoords, &triangleVertices, &triangleNormals, &triangleTexCoords);

	if (result)
	{
		glusCalculateTangentSpacef(shape);
	}

	return result;
}