19 #ifndef _CY_HAIR_FILE_H_INCLUDED_
20 #define _CY_HAIR_FILE_H_INCLUDED_
28 #include <luxrays/utils/exportdefs.h>
34 #define CY_HAIR_FILE_SEGMENTS_BIT 1
35 #define CY_HAIR_FILE_POINTS_BIT 2
36 #define CY_HAIR_FILE_THICKNESS_BIT 4
37 #define CY_HAIR_FILE_TRANSPARENCY_BIT 8
38 #define CY_HAIR_FILE_COLORS_BIT 16
39 #define CY_HAIR_FILE_UVS_BIT 32
41 #define CY_HAIR_FILE_INFO_SIZE 88
44 #define CY_HAIR_FILE_ERROR_CANT_OPEN_FILE -1
45 #define CY_HAIR_FILE_ERROR_CANT_READ_HEADER -2
46 #define CY_HAIR_FILE_ERROR_WRONG_SIGNATURE -3
47 #define CY_HAIR_FILE_ERROR_READING_SEGMENTS -4
48 #define CY_HAIR_FILE_ERROR_READING_POINTS -5
49 #define CY_HAIR_FILE_ERROR_READING_THICKNESS -6
50 #define CY_HAIR_FILE_ERROR_READING_TRANSPARENCY -7
51 #define CY_HAIR_FILE_ERROR_READING_COLORS -8
52 #define CY_HAIR_FILE_ERROR_READING_UVS -9
78 cyHairFile() : segments(NULL), points(NULL), thickness(NULL), transparency(NULL), colors(NULL), uvs(NULL) { Initialize(); }
111 if ( segments )
delete [] segments;
112 if ( points )
delete [] points;
113 if ( colors )
delete [] colors;
114 if ( thickness )
delete [] thickness;
115 if ( transparency )
delete [] transparency;
116 if ( uvs )
delete [] uvs;
117 header.signature[0] =
'H';
118 header.signature[1] =
'A';
119 header.signature[2] =
'I';
120 header.signature[3] =
'R';
121 header.hair_count = 0;
122 header.point_count = 0;
124 header.d_segments = 0;
125 header.d_thickness = 1.0f;
126 header.d_transparency = 0.0f;
127 header.d_color[0] = 1.0f;
128 header.d_color[1] = 1.0f;
129 header.d_color[2] = 1.0f;
136 header.hair_count = count;
139 segments =
new unsigned short[ header.hair_count ];
146 header.point_count = count;
149 points =
new float[ header.point_count*3 ];
153 thickness =
new float[ header.point_count ];
155 if ( transparency ) {
156 delete [] transparency;
157 transparency =
new float[ header.point_count ];
161 colors =
new float[ header.point_count*3 ];
165 uvs =
new float[ header.point_count*2 ];
174 header.arrays = array_types;
199 void SetDefaultColor(
float r,
float g,
float b ) { header.d_color[0]=r; header.d_color[1]=g; header.d_color[2]=b; }
210 fp = fopen( filename,
"rb" );
216 #define _CY_FAILED_RETURN(errorno) { Initialize(); fclose( fp ); return errorno; }
227 segments =
new unsigned short[ header.hair_count ];
228 size_t readcount = fread( segments,
sizeof(
unsigned short), header.hair_count, fp );
234 points =
new float[ header.point_count*3 ];
235 size_t readcount = fread( points,
sizeof(
float), header.point_count*3, fp );
241 thickness =
new float[ header.point_count ];
242 size_t readcount = fread( thickness,
sizeof(
float), header.point_count, fp );
248 transparency =
new float[ header.point_count ];
249 size_t readcount = fread( transparency,
sizeof(
float), header.point_count, fp );
255 colors =
new float[ header.point_count*3 ];
256 size_t readcount = fread( colors,
sizeof(
float), header.point_count*3, fp );
262 uvs =
new float[ header.point_count*2 ];
263 size_t readcount = fread( uvs,
sizeof(
float), header.point_count*2, fp );
269 return header.hair_count;
276 fp = fopen( filename,
"wb" );
277 if ( fp == NULL )
return -1;
288 if ( header.arrays &
CY_HAIR_FILE_UVS_BIT ) fwrite( uvs,
sizeof(
float), header.point_count*2, fp );
292 return header.hair_count;
305 if ( dir==NULL || header.point_count<=0 || points==NULL )
return 0;
308 for (
unsigned int i=0; i<header.hair_count; i++ ) {
309 int s = (segments) ? segments[i] : header.d_segments;
313 ComputeDirection( &dir[(p+1)*3], len0, len1, &points[p*3], &points[(p+1)*3], &points[(p+2)*3] );
317 d0[0] = points[(p+1)*3] - dir[(p+1)*3] *len0*0.3333f - points[p*3];
318 d0[1] = points[(p+1)*3+1] - dir[(p+1)*3+1]*len0*0.3333f - points[p*3+1];
319 d0[2] = points[(p+1)*3+2] - dir[(p+1)*3+2]*len0*0.3333f - points[p*3+2];
320 float d0lensq = d0[0]*d0[0] + d0[1]*d0[1] + d0[2]*d0[2];
321 float d0len = ( d0lensq > 0 ) ? (
float) sqrt(d0lensq) : 1.0f;
322 dir[p*3] = d0[0] / d0len;
323 dir[p*3+1] = d0[1] / d0len;
324 dir[p*3+2] = d0[2] / d0len;
330 for (
int t=2; t<s; t++, p++ ) {
331 ComputeDirection( &dir[p*3], len0, len1, &points[(p-1)*3], &points[p*3], &points[(p+1)*3] );
335 d0[0] = - points[(p-1)*3] + dir[(p-1)*3] *len1*0.3333f + points[p*3];
336 d0[1] = - points[(p-1)*3+1] + dir[(p-1)*3+1]*len1*0.3333f + points[p*3+1];
337 d0[2] = - points[(p-1)*3+2] + dir[(p-1)*3+2]*len1*0.3333f + points[p*3+2];
338 d0lensq = d0[0]*d0[0] + d0[1]*d0[1] + d0[2]*d0[2];
339 d0len = ( d0lensq > 0 ) ? (
float) sqrt(d0lensq) : 1.0f;
340 dir[p*3] = d0[0] / d0len;
341 dir[p*3+1] = d0[1] / d0len;
342 dir[p*3+2] = d0[2] / d0len;
345 }
else if ( s > 0 ) {
348 d0[0] = points[(p+1)*3] - points[p*3];
349 d0[1] = points[(p+1)*3+1] - points[p*3+1];
350 d0[2] = points[(p+1)*3+2] - points[p*3+2];
351 float d0lensq = d0[0]*d0[0] + d0[1]*d0[1] + d0[2]*d0[2];
352 float d0len = ( d0lensq > 0 ) ? (
float) sqrt(d0lensq) : 1.0f;
353 dir[p*3] = d0[0] / d0len;
354 dir[p*3+1] = d0[1] / d0len;
355 dir[p*3+2] = d0[2] / d0len;
356 dir[(p+1)*3] = dir[p*3];
357 dir[(p+1)*3+1] = dir[p*3+1];
358 dir[(p+1)*3+2] = dir[p*3+2];
380 float ComputeDirection(
float *d,
float &d0len,
float &d1len,
const float *p0,
const float *p1,
const float *p2 )
384 d0[0] = p1[0] - p0[0];
385 d0[1] = p1[1] - p0[1];
386 d0[2] = p1[2] - p0[2];
387 float d0lensq = d0[0]*d0[0] + d0[1]*d0[1] + d0[2]*d0[2];
388 d0len = ( d0lensq > 0 ) ? (
float) sqrt(d0lensq) : 1.0f;
392 d1[0] = p2[0] - p1[0];
393 d1[1] = p2[1] - p1[1];
394 d1[2] = p2[2] - p1[2];
395 float d1lensq = d1[0]*d1[0] + d1[1]*d1[1] + d1[2]*d1[2];
396 d1len = ( d1lensq > 0 ) ? (
float) sqrt(d1lensq) : 1.0f;
399 d0[0] *= d1len / d0len;
400 d0[1] *= d1len / d0len;
401 d0[2] *= d1len / d0len;
404 d[0] = d0[0] + d1[0];
405 d[1] = d0[1] + d1[1];
406 d[2] = d0[2] + d1[2];
407 float dlensq = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
408 float dlen = ( dlensq > 0 ) ? (
float) sqrt(dlensq) : 1.0f;
void SetDefaultTransparency(float t)
Sets default hair strand transparency, which is used if transparency array does not exist...
#define CY_HAIR_FILE_UVS_BIT
const float * GetPointsArray() const
Returns points array (xyz coordinates of each hair point).
#define _CY_FAILED_RETURN(errorno)
void SetDefaultThickness(float t)
Sets default hair strand thickness, which is used if thickness array does not exist.
const unsigned short * GetSegmentsArray() const
Returns segments array (segment count for each hair strand).
#define CY_HAIR_FILE_ERROR_READING_POINTS
void SetPointCount(int count)
#define CY_HAIR_FILE_ERROR_CANT_READ_HEADER
#define CY_HAIR_FILE_ERROR_CANT_OPEN_FILE
const cyHairFileHeader & GetHeader() const
Use this method to access header data.
#define CY_HAIR_FILE_ERROR_READING_THICKNESS
void Initialize()
Deletes all arrays and initializes the header data.
#define CY_HAIR_FILE_THICKNESS_BIT
#define CY_HAIR_FILE_TRANSPARENCY_BIT
float * GetThicknessArray()
Returns thickness array (thickness at each hair point}.
float * GetColorsArray()
Returns colors array (rgb color at each hair point).
void SetDefaultColor(float r, float g, float b)
Sets default hair color, which is used if color array does not exist.
float * GetTransparencyArray()
Returns transparency array (transparency at each hair point).
const float * GetColorsArray() const
Returns colors array (rgb color at each hair point).
float ComputeDirection(float *d, float &d0len, float &d1len, const float *p0, const float *p1, const float *p2)
const float * GetTransparencyArray() const
Returns transparency array (transparency at each hair point).
#define CY_HAIR_FILE_COLORS_BIT
int LoadFromFile(const char *filename)
Loads hair data from the given HAIR file.
#define CY_HAIR_FILE_ERROR_READING_UVS
int FillDirectionArray(float *dir)
#define CY_HAIR_FILE_ERROR_READING_SEGMENTS
#define CY_HAIR_FILE_INFO_SIZE
unsigned short * segments
int SaveToFile(const char *filename) const
Saves hair data to the given HAIR file.
void SetDefaultSegmentCount(int s)
Sets default number of segments for all hair strands, which is used if segments array does not exist...
void SetArrays(int array_types)
#define CY_HAIR_FILE_SEGMENTS_BIT
#define CY_HAIR_FILE_ERROR_WRONG_SIGNATURE
unsigned short * GetSegmentsArray()
Returns segments array (segment count for each hair strand).
cyHairFileHeader HairFileHeader
#define CY_HAIR_FILE_POINTS_BIT
float * GetUVsArray()
Returns uvs array (uv at each hair point).
void SetHairCount(int count)
Sets the hair count, re-allocates segments array if necessary.
const float * GetThicknessArray() const
Returns thickness array (thickness at each hair point}.
float * GetPointsArray()
Returns points array (xyz coordinates of each hair point).
#define CY_HAIR_FILE_ERROR_READING_COLORS
const float * GetUVsArray() const
Returns uvs array (uv at each hair point).
#define CY_HAIR_FILE_ERROR_READING_TRANSPARENCY