1
0
pl-libs/pl_stl.h

330 lines
11 KiB
C

/*
pl_stl.h
* no dependencies
* simple asci & binary stl parser
*/
// library version (format XYYZZ)
#define PL_STL_VERSION "1.0.0"
#define PL_STL_VERSION_NUM 10000
/*
Index of this file:
// [SECTION] header mess
// [SECTION] forward declarations & basic types
// [SECTION] public api
// [SECTION] structs
// [SECTION] c file
*/
//-----------------------------------------------------------------------------
// [SECTION] header mess
//-----------------------------------------------------------------------------
#ifndef PL_STL_H
#define PL_STL_H
//-----------------------------------------------------------------------------
// [SECTION] forward declarations & basic types
//-----------------------------------------------------------------------------
typedef struct _plStlInfo plStlInfo;
//-----------------------------------------------------------------------------
// [SECTION] public api
//-----------------------------------------------------------------------------
void pl_load_stl(const char* pcData, size_t szDataSize, float* afPositionStream, float* afNormalStream, uint32_t* auIndexBuffer, plStlInfo* ptInfoOut);
//-----------------------------------------------------------------------------
// [SECTION] structs
//-----------------------------------------------------------------------------
typedef struct _plStlInfo
{
size_t szPositionStreamSize;
size_t szNormalStreamSize;
size_t szIndexBufferSize;
int iPreloaded;
} plStlInfo;
#endif // PL_STL_H
//-----------------------------------------------------------------------------
// [SECTION] c file
//-----------------------------------------------------------------------------
/*
Index of this file:
// [SECTION] header mess
// [SECTION] includes
// [SECTION] internal api
// [SECTION] public api implementation
// [SECTION] internal api implementation
*/
//-----------------------------------------------------------------------------
// [SECTION] header mess
//-----------------------------------------------------------------------------
#ifdef PL_STL_IMPLEMENTATION
//-----------------------------------------------------------------------------
// [SECTION] includes
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <float.h>
//-----------------------------------------------------------------------------
// [SECTION] internal api
//-----------------------------------------------------------------------------
static bool pl__move_to_next_line(const char* pcData, size_t szDataSize, size_t* pszCurrentPos);
static char pl__move_to_first_char(const char* pcData, size_t szDataSize, size_t* pszCurrentPos);
//-----------------------------------------------------------------------------
// [SECTION] public api implementation
//-----------------------------------------------------------------------------
void
pl_load_stl(const char* pcData, size_t szDataSize, float* afPositionStream, float* afNormalStream, uint32_t* auIndexBuffer, plStlInfo* ptInfoOut)
{
plStlInfo _tInternalInfo = {0};
if(ptInfoOut == NULL)
ptInfoOut = &_tInternalInfo;
bool bAsci = strncmp(pcData, "solid", 5) == 0;
size_t szFacetCount = ptInfoOut->iPreloaded ? ptInfoOut->szIndexBufferSize / 3 : 0;
size_t szCurrentCursor = 0;
size_t szVertexCount = ptInfoOut->iPreloaded ? ptInfoOut->szIndexBufferSize : 0;
if(!ptInfoOut->iPreloaded)
{
// find number of vertices & facets
if(bAsci)
{
while(pl__move_to_next_line(pcData, szDataSize, &szCurrentCursor))
{
const char cFirstChar = pl__move_to_first_char(pcData, szDataSize, &szCurrentCursor);
switch(cFirstChar)
{
case 'v': szVertexCount++; break;
case 'f': szFacetCount++; break;
default: break;
}
}
}
else
{
szFacetCount = *(unsigned int*)&pcData[80];
szVertexCount = szFacetCount * 3;
}
ptInfoOut->iPreloaded = 1;
}
ptInfoOut->szIndexBufferSize = szFacetCount * 3;
ptInfoOut->szPositionStreamSize = szVertexCount * 3;
ptInfoOut->szNormalStreamSize = szVertexCount * 3;
// fill index buffer if provided
if(auIndexBuffer)
{
for(size_t i = 0; i < ptInfoOut->szIndexBufferSize; i++)
{
auIndexBuffer[i] = (uint32_t)i;
}
}
// reset cursor
szCurrentCursor = 0;
size_t szVertexStream0Pos = 0;
// fill vertex stream 0 if provided
if(afPositionStream)
{
if(bAsci)
{
while(pl__move_to_next_line(pcData, szDataSize, &szCurrentCursor))
{
const char cFirstChar = pl__move_to_first_char(pcData, szDataSize, &szCurrentCursor);
if(cFirstChar == 'v')
{
szCurrentCursor += 6;
const char* pcReturnString = &pcData[szCurrentCursor];
char* pcEnd = NULL;
afPositionStream[szVertexStream0Pos] = strtof(pcReturnString, &pcEnd);
afPositionStream[szVertexStream0Pos + 1] = strtof(pcEnd, &pcEnd);
afPositionStream[szVertexStream0Pos + 2] = strtof(pcEnd, &pcEnd);
afPositionStream += 3;
}
}
}
else
{
szCurrentCursor = 84;
float afFacetBuffer[12] = {0};
for(int facet = 0; facet < szFacetCount; facet++)
{
memcpy(afFacetBuffer, &pcData[szCurrentCursor], 48);
// vertex 0
afPositionStream[szVertexStream0Pos] = afFacetBuffer[3];
afPositionStream[szVertexStream0Pos + 1] = afFacetBuffer[4];
afPositionStream[szVertexStream0Pos + 2] = afFacetBuffer[5];
szVertexStream0Pos += 3;
// vertex 1
afPositionStream[szVertexStream0Pos] = afFacetBuffer[6];
afPositionStream[szVertexStream0Pos + 1] = afFacetBuffer[7];
afPositionStream[szVertexStream0Pos + 2] = afFacetBuffer[8];
szVertexStream0Pos += 3;
// vertex 2
afPositionStream[szVertexStream0Pos] = afFacetBuffer[9];
afPositionStream[szVertexStream0Pos + 1] = afFacetBuffer[10];
afPositionStream[szVertexStream0Pos + 2] = afFacetBuffer[11];
szVertexStream0Pos += 3;
szCurrentCursor += 50;
}
}
}
szCurrentCursor = 0;
size_t szVertexStream1Pos = 0;
const size_t szStride = 3;
if(afNormalStream)
{
if(bAsci)
{
while(pl__move_to_next_line(pcData, szDataSize, &szCurrentCursor))
{
const char cFirstChar = pl__move_to_first_char(pcData, szDataSize, &szCurrentCursor);
if(cFirstChar == 'f')
{
szCurrentCursor += 12;
const char* pcReturnString = &pcData[szCurrentCursor];
char* pcEnd = NULL;
const float fNx = strtof(pcReturnString, &pcEnd);
const float fNy = strtof(pcEnd, &pcEnd);
const float fNz = strtof(pcEnd, &pcEnd);
// vertex 0
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
// vertex 1
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
// vertex 2
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
}
}
}
else
{
szCurrentCursor = 84;
float afFacetBuffer[12] = {0};
for(uint32_t i = 0; i < szFacetCount; i++)
{
memcpy(afFacetBuffer, &pcData[szCurrentCursor], 48);
const float fNx = afFacetBuffer[0];
const float fNy = afFacetBuffer[1];
const float fNz = afFacetBuffer[2];
// vertex 0
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
// vertex 1
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
// vertex 2
afNormalStream[szVertexStream1Pos] = fNx;
afNormalStream[szVertexStream1Pos + 1] = fNy;
afNormalStream[szVertexStream1Pos + 2] = fNz;
szVertexStream1Pos += szStride;
szCurrentCursor += 50;
}
}
}
}
//-----------------------------------------------------------------------------
// [SECTION] public api implementation
//-----------------------------------------------------------------------------
static bool
pl__move_to_next_line(const char* pcData, size_t szDataSize, size_t* pszCurrentPos)
{
bool bLineFound = false;
while(*pszCurrentPos < szDataSize)
{
const char cCurrentCharacter = pcData[*pszCurrentPos];
if(cCurrentCharacter == '\n')
{
bLineFound = true;
(*pszCurrentPos)++;
break;
}
(*pszCurrentPos)++;
}
return bLineFound;
}
static char
pl__move_to_first_char(const char* pcData, size_t szDataSize, size_t* pszCurrentPos)
{
while(*pszCurrentPos < szDataSize)
{
const char cCurrentCharacter = pcData[*pszCurrentPos];
switch(cCurrentCharacter)
{
// end of line or string
case 0:
case '\n':
(*pszCurrentPos)++;
return 0;
// whitespace
case ' ':
case '\r':
case '\t': break;
// actual characters
default: return cCurrentCharacter;
}
(*pszCurrentPos)++;
}
return 0;
}
#endif // PL_STL_IMPLEMENTATION