Browse Source

Re-added utils

Thomas Buck 10 years ago
parent
commit
b04d417e70

+ 71
- 0
include/utils/math.h View File

@@ -0,0 +1,71 @@
1
+/*!
2
+ *
3
+ * \file include/utils/math.h
4
+ * \brief Vector and Matrix math
5
+ *
6
+ * \author Mongoose
7
+ */
8
+
9
+#include <math.h>
10
+
11
+#ifndef _UTILS_MATH_H
12
+#define _UTILS_MATH_H
13
+
14
+#define HEL_PI           ((float)M_PI) //!< pi
15
+#define HEL_2_PI         (HEL_PI * 2.0f) //!< pi*2
16
+#define HEL_PI_OVER_4    (HEL_PI / 4.0f) //!< pi/4
17
+#define HEL_PI_OVER_180  (HEL_PI / 180.0f) //!< pi/180
18
+#define HEL_180_OVER_PI  (180.0f / HEL_PI) //!< 180/pi
19
+
20
+#define HEL_RAD_TO_DEG(x) ((x) * HEL_180_OVER_PI) //!< Convert radians to degrees
21
+#define HEL_DEG_TO_RAD(x) ((x) * HEL_PI_OVER_180) //!< Convert degrees to radians
22
+
23
+typedef float vec_t;        //!< 1D Vector, aka float
24
+typedef float vec2_t[2];    //!< 2D Vector
25
+typedef float vec3_t[3];    //!< 3D Vector
26
+typedef float vec4_t[4];    //!< 4D Vector
27
+typedef vec_t matrix_t[16]; //!< Used as _Column_major_ in every class now!
28
+
29
+/*!
30
+ * \brief Compare two floats with an Epsilon.
31
+ * \param a first float
32
+ * \param b second float
33
+ * \returns true if a and b are probably the same.
34
+ */
35
+bool equalEpsilon(vec_t a, vec_t b);
36
+
37
+/*!
38
+ * \brief Calculate Intersection of a line and a polygon
39
+ * \param intersect Where the intersection is stored, if it exists
40
+ * \param p1 First point of line segment
41
+ * \param p2 Second point of line segment
42
+ * \param polygon polygon vertex array (0 to 2 are used)
43
+ * \returns 0 if there is no intersection
44
+ */
45
+int helIntersectionLineAndPolygon(vec3_t intersect, vec3_t p1, vec3_t p2, vec3_t *polygon);
46
+
47
+/*!
48
+ * \brief Calculate the length of a line segment / the distance between two points
49
+ * \param a First point
50
+ * \param b Second point
51
+ * \returns distance/length
52
+ */
53
+vec_t helDist3v(vec3_t a, vec3_t b);
54
+
55
+/*!
56
+ * \brief Calculates the midpoint between two points / of a line segment
57
+ * \param a First point
58
+ * \param b Second point
59
+ * \param mid Midpoint will be stored here
60
+ */
61
+void helMidpoint3v(vec3_t a, vec3_t b, vec3_t mid);
62
+
63
+/*!
64
+ * \brief Calculates a pseudo-random number
65
+ * \param from Lower bound of resulting number
66
+ * \param to Upper bound
67
+ * \returns random number
68
+ */
69
+vec_t helRandomNum(vec_t from, vec_t to);
70
+
71
+#endif

+ 61
- 0
include/utils/strings.h View File

@@ -0,0 +1,61 @@
1
+/*!
2
+ * \file include/utils/strings.h
3
+ * \brief String handling utilities
4
+ *
5
+ * \author xythobuz
6
+ * \author Mongoose
7
+ */
8
+
9
+#ifndef _UTILS_STRINGS_H_
10
+#define _UTILS_STRINGS_H_
11
+
12
+/*!
13
+ * \brief Check if a string ends with another string.
14
+ * \param str string to check
15
+ * \param suffix suffix for which to check
16
+ * \returns true if str ends with suffix
17
+ */
18
+bool stringEndsWith(const char *str, const char *suffix);
19
+
20
+/*!
21
+ * \brief Generates a buffered string for the printf call
22
+ * \param string format string like for printf
23
+ * \param args arguments matching format string
24
+ * \returns string in a buffer
25
+ */
26
+char *bufferString(const char *string, va_list args) __attribute__((format(printf, 1, 0)));
27
+
28
+/*!
29
+ * \brief Generates a buffered string for the printf call
30
+ * \param string format string like for printf
31
+ * \returns string in a buffer
32
+ */
33
+char *bufferString(const char *string, ...) __attribute__((format(printf, 1, 2)));
34
+
35
+/*!
36
+ * \brief Expansion of unix home enviroment char.
37
+ * Also makes sure string ends in "end" char.
38
+ * \param path path string
39
+ * \param end end character. 0 appends no additional char
40
+ * \returns allocated string of path with expansions
41
+ */
42
+char *fullPath(const char *path, char end);
43
+
44
+/*!
45
+ * \brief Checks if Command matches Symbol.
46
+ * Returns the rest of the argument list back in command buffer, if any
47
+ * \param symbol command string
48
+ * \param command with arguments
49
+ * \returns true if command matches symbol
50
+ */
51
+bool rc_command(const char *symbol, char *command);
52
+
53
+/*!
54
+ * \brief Interpret a string as a bool
55
+ * \param buffer "true" or "false"
56
+ * \param val is set to boolean interpretation of buffer
57
+ * \returns -1 for null string, -2 if string is not "true" or "false"
58
+ */
59
+int rc_get_bool(const char *buffer, bool *val);
60
+
61
+#endif

+ 89
- 0
include/utils/tga.h View File

@@ -0,0 +1,89 @@
1
+/*!
2
+ * \file include/utils/tga.h
3
+ * \brief TGA image reader/writer
4
+ *
5
+ * \author Mongoose
6
+ * \author xythobuz
7
+ */
8
+#ifndef _UTILS_TGA_H
9
+#define _UTILS_TGA_H
10
+
11
+/*!
12
+ * \brief Possible TGA image types
13
+ */
14
+typedef enum {
15
+    TGA_TYPE__NO_DATA    = 0,
16
+    TGA_TYPE__MAPPED     = 1,
17
+    TGA_TYPE__COLOR      = 2,
18
+    TGA_TYPE__GREYSCALE  = 3,
19
+    TGA_TYPE__MAPPED_RLE = 9,
20
+    TGA_TYPE__COLOR_RLE  = 10
21
+    // TGA_TYPE__GREYSCALE_COMPRESSED  = 11,
22
+    // TGA_TYPE__COLOR_HUFFMAN_DELTA_RLE  = 32,
23
+    // TGA_TYPE__COLOR_HUFFMAN_DELTA_RLE_4PASS  = 33
24
+} tga_type_t;
25
+
26
+/*!
27
+ * \brief Data structure representing TGA file header
28
+ */
29
+typedef struct {
30
+    unsigned char comment_lenght;       //!< Number of bytes in comment
31
+    unsigned char colormap_type;        //!< 0 No colormap; 1 Has colormap
32
+    unsigned char image_type;           //!< 1 Colormapped; 2 Unmapped; 9 Colormapped RLE; 10 Unmapped RLE
33
+    unsigned short colormap_index;      //!< Index of first color map entry
34
+    unsigned short colormap_lenght;     //!< Number of color map entries
35
+    unsigned char colormap_bbp;         //!< 16, 24, or 32 bits per pixel format
36
+    unsigned short origin_x;            //!< X coor of lower-left corner
37
+    unsigned short origin_y;            //!< Y coor of lower-left corner
38
+    unsigned short width;               //!< Width in pixels
39
+    unsigned short height;              //!< Height in pixels
40
+    unsigned char bpp;                  //!< Number of bits in a pixel index
41
+    unsigned char desc_flags;           //!< Various magic bits
42
+} tga_t;
43
+
44
+/*!
45
+ * \brief Check if a file is a valid TGA image
46
+ * \param f file to be checked
47
+ * \returns 0 if valid, else error condition
48
+ */
49
+int tgaCheck(FILE *f);
50
+
51
+/*!
52
+ * \brief Load a TGA image from file
53
+ * \param f valid image file
54
+ * \param image Where the pixmap will be stored (or NULL)
55
+ * \param width where the width will be stored
56
+ * \param height where the height will be stored
57
+ * \param type where the type will be stored (tga_type_t)
58
+ * \returns 0 on success, else error condition
59
+ */
60
+int tgaLoad(FILE *f, unsigned char **image,
61
+                unsigned int *width, unsigned int *height, char *type);
62
+
63
+/*!
64
+ * \brief Save a pixel buffer into a file on disk
65
+ * \param f file in which image will be saved
66
+ * \param image pixmap to be stored
67
+ * \param width width of pixmap/image
68
+ * \param height height of pixmap/image
69
+ * \param type tga type to use
70
+ * \returns 0 on success, else error condition
71
+ */
72
+int tgaSave(FILE *f, unsigned char *image,
73
+                unsigned int width, unsigned int height, char type);
74
+
75
+/*!
76
+ * \brief Save a pixel buffer into a file on disk
77
+ * \param image pixmap to be stored
78
+ * \param width width of pixmap/image
79
+ * \param height height of pixmap/image
80
+ * \param type tga type to use
81
+ * \param s format string for file path/name
82
+ * \returns 0 on success, else error condition
83
+ */
84
+int tgaSaveFilename(unsigned char *image,
85
+                        unsigned int width, unsigned int height,
86
+                        char type, const char *s, ...)
87
+    __attribute__((format(printf, 5, 6)));
88
+
89
+#endif

+ 32
- 0
include/utils/time.h View File

@@ -0,0 +1,32 @@
1
+/*!
2
+ * \file include/utils/time.h
3
+ * \brief Time handling utilities
4
+ *
5
+ * \author xythobuz
6
+ * \author Mongoose
7
+ */
8
+
9
+#ifndef _UTILS_TIME_H_
10
+#define _UTILS_TIME_H_
11
+
12
+#if defined(linux) || defined(__APPLE__)
13
+#include <time.h>
14
+#include <sys/time.h>
15
+#endif
16
+
17
+extern struct timeval system_timer_start; //!< System timer start time
18
+extern struct timeval system_timer_stop; //!< System timer last read time
19
+extern struct timezone system_timer_tz; //!< System timer timezone info
20
+
21
+/*!
22
+ * \brief Read the system timer
23
+ * \returns number of ticks
24
+ */
25
+unsigned int systemTimerGet();
26
+
27
+/*!
28
+ * \brief Reset the system timer
29
+ */
30
+void systemTimerReset();
31
+
32
+#endif

+ 2
- 2
src/CMakeLists.txt View File

@@ -66,7 +66,7 @@ set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${OpenRaider_CXX_FLAGS} ${O
66 66
 set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${OpenRaider_CXX_FLAGS} ${OpenRaider_CXX_FLAGS_RELEASE}")
67 67
 
68 68
 # Add utils directory
69
-# add_subdirectory (utils)
69
+add_subdirectory (utils)
70 70
 
71 71
 # Add Executable
72 72
 add_executable (OpenRaider MACOSX_BUNDLE ${SRCS})
@@ -148,7 +148,7 @@ include_directories (SYSTEM ${ZLIB_INCLUDE_DIRS})
148 148
 set (LIBS ${LIBS} ${ZLIB_LIBRARIES})
149 149
 
150 150
 # Add utils Library
151
-# set (LIBS ${LIBS} utilities)
151
+set (LIBS ${LIBS} utilities)
152 152
 
153 153
 # Link to all found libs
154 154
 target_link_libraries (OpenRaider ${LIBS})

+ 11
- 0
src/utils/CMakeLists.txt View File

@@ -0,0 +1,11 @@
1
+# Source files
2
+set (UTIL_SRCS ${UTIL_SRCS} "math.cpp")
3
+set (UTIL_SRCS ${UTIL_SRCS} "strings.cpp")
4
+set (UTIL_SRCS ${UTIL_SRCS} "tga.cpp")
5
+set (UTIL_SRCS ${UTIL_SRCS} "time.cpp")
6
+
7
+# Include directory
8
+include_directories ("${PROJECT_SOURCE_DIR}/include")
9
+
10
+# Add library
11
+add_library (utilities ${UTIL_SRCS})

+ 137
- 0
src/utils/math.cpp View File

@@ -0,0 +1,137 @@
1
+/*!
2
+ *
3
+ * \file src/utils/math.cpp
4
+ * \brief Vector and Matrix math
5
+ *
6
+ * \author Mongoose
7
+ */
8
+
9
+#include <stdlib.h>
10
+#include <math.h>
11
+#include <float.h>
12
+#include <assert.h>
13
+
14
+#include "utils/Vector3d.h"
15
+#include "utils/Matrix.h"
16
+#include "utils/math.h"
17
+
18
+bool equalEpsilon(vec_t a, vec_t b) {
19
+    vec_t epsilon = FLT_EPSILON;
20
+    if (fabs(a - b) <= (fmax(fabs(a), fabs(b)) * epsilon))
21
+        return true;
22
+    return false;
23
+}
24
+
25
+
26
+inline vec_t square(vec_t a)
27
+{
28
+    return a * a;
29
+}
30
+
31
+
32
+int helIntersectionLineAndPolygon(vec3_t intersect,
33
+        vec3_t p1, vec3_t p2,
34
+        vec3_t *polygon)
35
+{
36
+    assert(polygon != NULL);
37
+
38
+    //  vec3_t normal, a, b;
39
+    Vector3d a, b, normal, pA, pB;
40
+    vec_t d, denominator, mu;
41
+
42
+
43
+    pA = Vector3d(p1);
44
+    pB = Vector3d(p2);
45
+
46
+    // Find normal
47
+    a = Vector3d(polygon[1]) - Vector3d(polygon[0]);
48
+    b = Vector3d(polygon[2]) - Vector3d(polygon[0]);
49
+    normal = Vector3d::cross(a, b);
50
+    normal.normalize();
51
+
52
+    // find D
53
+    //d = (normal[0] * polygon[0][0] -
54
+    //    normal[1] * polygon[0][1] -
55
+    //    normal[2] * polygon[0][2]);
56
+    d = (normal.mVec[0] * polygon[0][0] -
57
+            normal.mVec[1] * polygon[0][1] -
58
+            normal.mVec[2] * polygon[0][2]);
59
+
60
+    // line segment parallel to plane?
61
+    a = pB - pA;
62
+
63
+    //denominator = (normal[0] * a[0] +
64
+    //                  normal[1] * a[1] +
65
+    //                  normal[2] * a[2]);
66
+    denominator = Vector3d::dot(normal, a);
67
+
68
+    if (denominator > 0.0)
69
+        return 0;
70
+
71
+    // Line segment contains intercept point?
72
+    //mu = - ((d + normal[0] * p1[0] + normal[1] * p1[1] + normal[2] * p1[2]) /
73
+    //        denominator);
74
+    mu = -((d + Vector3d::dot(normal, pA)) / denominator);
75
+
76
+    if (mu < 0.0 || mu > 1.0)
77
+        return 0;
78
+
79
+    //intersect[0] = p1[0] + mu * a[0];
80
+    //intersect[1] = p1[1] + mu * a[1];
81
+    //intersect[2] = p1[2] + mu * a[2];
82
+    b = pA + (a * mu);
83
+    intersect[0] = b.mVec[0];
84
+    intersect[1] = b.mVec[1];
85
+    intersect[2] = b.mVec[2];
86
+
87
+
88
+    // See if the intercept is bound by polygon by winding number
89
+    // assume convex polygons here for sure
90
+    double theta = Vector3d::dot(b - Vector3d(polygon[0]), normal); // b = intersect
91
+
92
+    if (theta >= 90.0) // Yeah I know
93
+        return 0;
94
+
95
+    return 1;
96
+}
97
+
98
+
99
+vec_t helDist3v(vec3_t a, vec3_t b)
100
+{
101
+    return (sqrtf( ((b[0] - a[0]) * (b[0] - a[0])) +
102
+                ((b[1] - a[1]) * (b[1] - a[1])) +
103
+                ((b[2] - a[2]) * (b[2] - a[2]))));
104
+}
105
+
106
+
107
+void helMidpoint3v(vec3_t a, vec3_t b, vec3_t mid)
108
+{
109
+    mid[0] = (a[0] + b[0]) / 2.0f;
110
+    mid[1] = (a[1] + b[1]) / 2.0f;
111
+    mid[2] = (a[2] + b[2]) / 2.0f;
112
+}
113
+
114
+
115
+vec_t helNorm4v(vec4_t v)
116
+{
117
+    return (sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] + v[3]*v[3]));
118
+}
119
+
120
+
121
+vec_t helNorm3v(vec3_t v)
122
+{
123
+    return (sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]));
124
+}
125
+
126
+
127
+vec_t helNorm2v(vec2_t v)
128
+{
129
+    return (sqrtf(v[0]*v[0] + v[1]*v[1]));
130
+}
131
+
132
+
133
+vec_t helRandomNum(vec_t from, vec_t to)
134
+{
135
+    return from + ((to - from) * rand() / (RAND_MAX + 1.0f));
136
+}
137
+

+ 171
- 0
src/utils/strings.cpp View File

@@ -0,0 +1,171 @@
1
+/*!
2
+ * \file include/utils/strings.h
3
+ * \brief String handling utilities
4
+ *
5
+ * \author xythobuz
6
+ * \author Mongoose
7
+ */
8
+
9
+#include <cstdarg>
10
+#include <cstdlib>
11
+#include <stdio.h>
12
+#include <string.h>
13
+#include <assert.h>
14
+
15
+#if defined(unix) || defined(__APPLE__)
16
+#include <wordexp.h>
17
+#endif
18
+
19
+#include "utils/strings.h"
20
+
21
+bool stringEndsWith(const char *str, const char *suffix) {
22
+    assert(str != NULL);
23
+    assert(suffix != NULL);
24
+
25
+    size_t lenstr = strlen(str);
26
+    size_t lensuffix = strlen(suffix);
27
+
28
+    if (lensuffix > lenstr)
29
+        return false;
30
+
31
+    return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
32
+}
33
+
34
+char *bufferString(const char *string, va_list args) {
35
+    int sz = 60;
36
+    int n;
37
+    char *text;
38
+
39
+    assert(string != NULL);
40
+    assert(string[0] != '\0');
41
+
42
+    text = new char[sz];
43
+
44
+    n = vsnprintf(text, sz, string, args);
45
+
46
+    if (n < 0) {
47
+        delete [] text;
48
+        return NULL; // encoding error
49
+    } else if (n >= sz) {
50
+        sz = n + 1; // buffer too small
51
+        delete [] text;
52
+        text = new char[sz];
53
+        n = vsnprintf(text, sz, string, args);
54
+    }
55
+
56
+    return text;
57
+}
58
+
59
+char *bufferString(const char *string, ...) {
60
+    va_list args;
61
+    va_start(args, string);
62
+    char *text = bufferString(string, args);
63
+    va_end(args);
64
+    return text;
65
+}
66
+
67
+char *fullPath(const char *path, char end) {
68
+    unsigned int lenPath, offset;
69
+    wordexp_t word;
70
+    char *dir;
71
+
72
+    assert(path != NULL);
73
+    assert(path[0] != '\0');
74
+
75
+    if (path[0] == '~') {
76
+#if defined(unix) || defined(__APPLE__)
77
+#ifdef __APPLE__
78
+        // Workaround for Mac OS X. See:
79
+        // http://stackoverflow.com/questions/20534788/why-does-wordexp-fail-with-wrde-syntax-on-os-x
80
+        signal(SIGCHLD, SIG_DFL);
81
+#endif
82
+        // Expand string into segments
83
+        int res = wordexp(path, &word, 0);
84
+#ifdef __APPLE__
85
+        signal(SIGCHLD, SIG_IGN);
86
+#endif
87
+        if (res != 0) {
88
+            printf("fullPath> wordexp() failed: %d\n", res);
89
+            return NULL;
90
+        }
91
+
92
+        // Get length of complete string
93
+        lenPath = 0;
94
+        for (unsigned int i = 0; i < word.we_wordc; i++) {
95
+            lenPath += strlen(word.we_wordv[i]);
96
+        }
97
+
98
+        // Allocate new string
99
+        dir = new char[lenPath + 2]; // space for end char
100
+
101
+        // Copy segments into new string
102
+        offset = 0;
103
+        for (unsigned int i = 0; i < word.we_wordc; i++) {
104
+            unsigned int len = strlen(word.we_wordv[i]);
105
+            strncpy(dir + offset, word.we_wordv[i], len);
106
+            offset += len;
107
+        }
108
+
109
+        wordfree(&word);
110
+#else
111
+        printf("WARNING: Tilde expansion not supported on this platform!\n");
112
+        lenPath = strlen(path);
113
+        dir = new char[lenPath + 2]; // space for end char
114
+        strncpy(dir, path, lenPath);
115
+#endif
116
+    } else {
117
+        lenPath = strlen(path);
118
+        dir = new char[lenPath + 2]; // space for end char
119
+        strncpy(dir, path, lenPath);
120
+    }
121
+
122
+    // Make sure ends in "end" char
123
+    if ((lenPath > 0) && (end != 0) && (dir[lenPath - 1] != end)) {
124
+        dir[lenPath] = end;
125
+        dir[lenPath + 1] = 0;
126
+    } else {
127
+        dir[lenPath] = 0;
128
+    }
129
+
130
+    return dir;
131
+}
132
+
133
+bool rc_command(const char *symbol, char *command) {
134
+    assert(symbol != NULL);
135
+    assert(symbol[0] != '\0');
136
+    assert(command != NULL);
137
+    assert(command[0] != '\0');
138
+
139
+    int lens = strlen(symbol);
140
+
141
+    if (strncmp(command, symbol, lens) == 0) {
142
+        int lenc = strlen(command);
143
+
144
+        //! \fixme Should ignore whitespace, but only if it is really there...?
145
+        // lens+1 skips '=' or ' '
146
+        for (int i = 0, j = lens+1; j < lenc; ++i, ++j) {
147
+            command[i] = command[j];
148
+            command[i+1] = 0;
149
+        }
150
+
151
+        return true;
152
+    }
153
+
154
+    return false;
155
+}
156
+
157
+int rc_get_bool(const char *buffer, bool *val) {
158
+    assert(buffer != NULL);
159
+    assert(buffer[0] != '\0');
160
+    assert(val != NULL);
161
+
162
+    if ((buffer[0] == '1') || (strncmp(buffer, "true", 4) == 0))
163
+        *val = true;
164
+    else if ((buffer[0] == '0') || (strncmp(buffer, "false", 5) == 0))
165
+        *val = false;
166
+    else
167
+        return -2;
168
+
169
+    return 0;
170
+}
171
+

+ 382
- 0
src/utils/tga.cpp View File

@@ -0,0 +1,382 @@
1
+/*!
2
+ * \file src/utils/tga.cpp
3
+ * \brief TGA image reader/writer
4
+ *
5
+ * \todo type should pass more info (2 bits for RGBA|RGB|GREY; val for depth)
6
+ *
7
+ * \author Mongoose
8
+ * \author xythobuz
9
+ */
10
+
11
+#include <stdio.h>
12
+#include <string.h>
13
+#include <stdarg.h>
14
+#include <assert.h>
15
+
16
+#include "utils/tga.h"
17
+
18
+int tgaCheck(FILE *f) {
19
+    char buffer[10];
20
+
21
+    assert(f != NULL);
22
+
23
+    /* Read the header */
24
+    fseek(f, 0, SEEK_SET);
25
+    fread(buffer, 8, 1, f);
26
+
27
+    // buffer[1] = 0 - Means not color mapped (1 would mean mapped)
28
+    if (!(buffer[1] == 0 && (buffer[2] == TGA_TYPE__COLOR ||
29
+                    //buffer[2] == TGA_TYPE__GREYSCALE ||
30
+                    buffer[2] == TGA_TYPE__COLOR_RLE))) {
31
+        printf("tgaCheck> Inavlid or unknown TGA format.\n");
32
+        return -2;
33
+    }
34
+    return 0;
35
+}
36
+
37
+int tgaLoad(FILE *f, unsigned char **image, unsigned int *width, unsigned int *height, char *type) {
38
+    tga_t header;
39
+    char comment[256];
40
+    unsigned char pixel[4];
41
+    unsigned char *swap_row = NULL;
42
+    unsigned char tmp, packet;
43
+    bool must_flip = 0;
44
+    unsigned int size;
45
+    unsigned int i, j;
46
+
47
+    assert(f != NULL);
48
+    assert(image != NULL);
49
+    assert(width != NULL);
50
+    assert(height != NULL);
51
+    assert(type != NULL);
52
+
53
+    fseek(f, 0, SEEK_SET);
54
+
55
+    // Read TGA header
56
+    fread(&header.comment_lenght, 1, 1, f);
57
+    fread(&header.colormap_type, 1, 1, f);
58
+    fread(&header.image_type, 1, 1, f);
59
+    fread(&header.colormap_index, 2, 1, f);
60
+    fread(&header.colormap_lenght, 2, 1, f);
61
+    fread(&header.colormap_bbp, 1, 1, f);
62
+
63
+    fread(&tmp, 1, 1, f);
64
+    header.origin_x = tmp;
65
+    fread(&tmp, 1, 1, f);
66
+    header.origin_x += tmp * 256;
67
+
68
+    fread(&tmp, 1, 1, f);
69
+    header.origin_y = tmp;
70
+    fread(&tmp, 1, 1, f);
71
+    header.origin_y += tmp * 256;
72
+
73
+    fread(&tmp, 1, 1, f);
74
+    header.width = tmp;
75
+    fread(&tmp, 1, 1, f);
76
+    header.width += tmp * 256;
77
+
78
+    fread(&tmp, 1, 1, f);
79
+    header.height = tmp;
80
+    fread(&tmp, 1, 1, f);
81
+    header.height += tmp * 256;
82
+
83
+    fread(&header.bpp, 1, 1, f);
84
+    fread(&header.desc_flags, 1, 1, f);
85
+
86
+    *width = header.width;
87
+    *height = header.height;
88
+
89
+    switch (header.bpp) {
90
+        case 32:
91
+            *type = 2; //32;
92
+            break;
93
+        case 24:
94
+            *type = 1; //24;
95
+            break;
96
+        case 8:
97
+        default:
98
+            *type = 0; //8;
99
+            break;
100
+    }
101
+
102
+#ifdef DEBUG_TGA
103
+    printf("TGA [%ix%i@%ibpp, %it, %ix, %iy, %uf]\n",
104
+            header.width, header.height, header.bpp, header.image_type,
105
+            header.origin_x, header.origin_y,
106
+            header.desc_flags);
107
+#endif
108
+
109
+    // Comments can be 0 - 255
110
+    if (header.comment_lenght) {
111
+        fread(&comment, 1, header.comment_lenght, f);
112
+        for (i = 0; i < 255; ++i) {
113
+            if (!(comment[i] > 32 && comment[i] < 127))
114
+                comment[i] = 183; // print a dot for invalid text
115
+        }
116
+        comment[255] = 0;
117
+        printf("Comment: '%s'\n", comment);
118
+    }
119
+
120
+    *image = NULL;
121
+    size = header.width * header.height;
122
+
123
+    if (!size || (!(header.colormap_type == 0 && (header.image_type == 2 || header.image_type == 10)))) {
124
+        fprintf(stderr, "tgaLoad> Unknown image format.\n");
125
+        return -2;
126
+    }
127
+
128
+    // Mongoose: Added 'screen origin bit' support back here
129
+    if (!(header.desc_flags & 32)) {
130
+        must_flip = true;
131
+    }
132
+
133
+    switch (header.bpp) {
134
+        case 32:
135
+            size *= 4;
136
+            *image = new unsigned char [size];
137
+            switch (header.image_type) {
138
+                case TGA_TYPE__COLOR_RLE:
139
+                    for (i = 0; i < size;) {
140
+                        fread(&packet, 1, 1, f);
141
+                        if (packet & 0x80) { // Run Length
142
+                            packet = (packet &0x7F) + 1;
143
+                            fread(&pixel, 4, 1, f);
144
+                            for (j = 0; j < packet; j++) {
145
+                                (*image)[i++] = pixel[2];
146
+                                (*image)[i++] = pixel[1];
147
+                                (*image)[i++] = pixel[0];
148
+                                (*image)[i++] = pixel[3];
149
+                            }
150
+                        } else { // RAW
151
+                            packet = (packet &0x7F) + 1;
152
+                            for (j = 0; j < packet; j++) {
153
+                                fread(&pixel, 4, 1, f);
154
+                                (*image)[i++] = pixel[2];
155
+                                (*image)[i++] = pixel[1];
156
+                                (*image)[i++] = pixel[0];
157
+                                (*image)[i++] = pixel[3];
158
+                            }
159
+                        }
160
+                    }
161
+                    break;
162
+                case TGA_TYPE__COLOR:
163
+                    if (fread((*image), size, 1, f) < 1) {
164
+                        fprintf(stderr, "tgaLoad> Image fread failed.\n");
165
+                        delete [] *image;
166
+                        return -4;
167
+                    }
168
+                    for (i = 0; i < size; i += 4) {
169
+                        tmp = (*image)[i];
170
+                        (*image)[i] = (*image)[i + 2];
171
+                        (*image)[i + 2] = tmp;
172
+                    }
173
+                    break;
174
+                default:
175
+                    ;
176
+            }
177
+            if (must_flip) {
178
+                swap_row = new unsigned char [header.width * 4];
179
+                for (i = 0, j = header.height-1; (int)i < header.height/2; i++, j--) {
180
+                    memcpy(swap_row, &(*image)[i*header.width*4], header.width*4);
181
+                    memcpy(&(*image)[i*header.width*4], &(*image)[j*header.width*4],
182
+                            header.width*4);
183
+                    memcpy(&(*image)[j*header.width*4], swap_row, header.width*4);
184
+                }
185
+                delete [] swap_row;
186
+            }
187
+            break;
188
+        case 24:
189
+            size *= 3;
190
+            *image = new unsigned char [size];
191
+            switch (header.image_type) {
192
+                case TGA_TYPE__COLOR_RLE:
193
+                    for (i = 0; i < size;) {
194
+                        fread(&packet, 1, 1, f);
195
+                        if (packet & 0x80) { // Run Length
196
+                            packet = (packet &0x7F) + 1;
197
+                            fread(&pixel, 3, 1, f);
198
+                            for (j = 0; j < packet; j++) {
199
+                                (*image)[i++] = pixel[2];
200
+                                (*image)[i++] = pixel[1];
201
+                                (*image)[i++] = pixel[0];
202
+                            }
203
+                        } else { // RAW
204
+                            packet = (packet &0x7F) + 1;
205
+                            for (j = 0; j < packet; j++) {
206
+                                fread(&pixel, 3, 1, f);
207
+                                (*image)[i++] = pixel[2];
208
+                                (*image)[i++] = pixel[1];
209
+                                (*image)[i++] = pixel[0];
210
+                            }
211
+                        }
212
+                    }
213
+                    break;
214
+                case TGA_TYPE__COLOR:
215
+                    if (fread((*image), size, 1, f) < 1) {
216
+                        fprintf(stderr, "tgaLoad> Image fread failed.\n");
217
+                        delete [] *image;
218
+                        return -4;
219
+                    }
220
+                    for (i = 0; i < size; i += 3) {
221
+                        tmp = (*image)[i];
222
+                        (*image)[i] = (*image)[i + 2];
223
+                        (*image)[i + 2] = tmp;
224
+                    }
225
+                    break;
226
+                default:
227
+                    ;
228
+            }
229
+            if (must_flip) {
230
+                swap_row = new unsigned char [header.width * 3];
231
+                for (i = 0, j = header.height - 1; (int)i < header.height / 2; i++, j--) {
232
+                    memcpy(swap_row, &(*image)[i*header.width*3], header.width*3);
233
+                    memcpy(&(*image)[i*header.width*3], &(*image)[j*header.width*3],
234
+                            header.width*3);
235
+                    memcpy(&(*image)[j*header.width*3], swap_row, header.width*3);
236
+                }
237
+                delete [] swap_row;
238
+            }
239
+            break;
240
+        case 8:
241
+            printf("tgaLoad> 8bpp Not implemented\n");
242
+            break;
243
+        default:
244
+            ;
245
+    }
246
+
247
+#ifdef DEBUG_TGA
248
+    char c;
249
+    printf("TGA Comment: ");
250
+    while (fread(&c, 1, 1, f) == 1) {
251
+        printf("%c", c);
252
+    }
253
+    printf("\n");
254
+#endif
255
+
256
+    return 0;
257
+}
258
+
259
+int tgaSave(FILE *f, unsigned char *image, unsigned int width, unsigned int height, char type) {
260
+    tga_t header;
261
+    unsigned int size;
262
+    char comment[64];
263
+    //unsigned int i;
264
+    //unsigned char tmp;
265
+
266
+    assert(f != NULL);
267
+    assert(image != NULL);
268
+    assert(width > 0);
269
+    assert(height > 0);
270
+
271
+    strncpy(comment, "OpenRaider TGA", 63);
272
+    comment[63] = 0;
273
+
274
+    header.comment_lenght = (unsigned char)strlen(comment);
275
+    header.colormap_type = 0;
276
+
277
+    // No colormaps
278
+    header.colormap_index = 0;
279
+    header.colormap_lenght = 0;
280
+    header.colormap_bbp = 0;
281
+
282
+    header.origin_x = header.origin_y = 0;
283
+    header.width = (unsigned short)width;
284
+    header.height = (unsigned short)height;
285
+
286
+    header.desc_flags = 0;
287
+
288
+    switch (type) {
289
+        case 4:
290
+            header.image_type = TGA_TYPE__COLOR;
291
+            header.desc_flags = 32;
292
+            header.bpp = 32;
293
+            break;
294
+        case 2:
295
+            header.bpp = 32;
296
+            break;
297
+        case 1:
298
+            header.image_type = TGA_TYPE__GREYSCALE;
299
+            header.bpp = 8;
300
+            break;
301
+        default:
302
+            header.image_type = TGA_TYPE__COLOR;
303
+            header.bpp = 24;
304
+    }
305
+
306
+    // Write TGA header
307
+    fwrite(&header.comment_lenght, 1, 1, f);
308
+    fwrite(&header.colormap_type, 1, 1, f);
309
+    fwrite(&header.image_type, 1, 1, f);
310
+    fwrite(&header.colormap_index, 2, 1, f);
311
+    fwrite(&header.colormap_lenght, 2, 1, f);
312
+    fwrite(&header.colormap_bbp, 1, 1, f);
313
+    fwrite(&header.origin_x, 2, 1, f);
314
+    fwrite(&header.origin_y, 2, 1, f);
315
+    fwrite(&header.width, 2, 1, f);
316
+    fwrite(&header.height, 2, 1, f);
317
+    fwrite(&header.bpp, 1, 1, f);
318
+    fwrite(&header.desc_flags, 1, 1, f);
319
+
320
+    // Write comment
321
+    fwrite(&comment, 1, header.comment_lenght, f);
322
+
323
+    switch (header.bpp) {
324
+        case 32:
325
+            size = header.width * header.height * 4;
326
+
327
+            //for (i = 0; i < size; i += 4)
328
+            //{
329
+            //  tmp = image[i];
330
+            //  image[i] = image[i + 2];
331
+            //  image[i + 2] = tmp;
332
+            //}
333
+            break;
334
+        case 24:
335
+            size = header.width * header.height * 3;
336
+
337
+            //for (i = 0; i < size; i += 3)
338
+            //{
339
+            //  tmp = image[i];
340
+            //  image[i] = image[i + 2];
341
+            //  image[i + 2] = tmp;
342
+            //}
343
+            break;
344
+        case 8:
345
+        default:
346
+            size = header.width * header.height;
347
+            break;
348
+    }
349
+
350
+    // Write image data
351
+    if (fwrite(image, size, 1, f) < 1) {
352
+        perror("tgaSave> Disk write failed.\n");
353
+        return -2;
354
+    }
355
+    return 0;
356
+}
357
+
358
+int tgaSaveFilename(unsigned char *image, unsigned int width, unsigned int height, char type, const char *s, ...) {
359
+    char buffer[1024];
360
+    FILE *f;
361
+    int v;
362
+    va_list args;
363
+
364
+    assert(image != NULL);
365
+    assert(width > 0);
366
+    assert(height > 0);
367
+    assert(s != NULL);
368
+    assert(s[0] != '\0');
369
+
370
+    va_start(args, s);
371
+    vsnprintf(buffer, 1023, s, args);
372
+    va_end(args);
373
+    f = fopen(buffer, "wb");
374
+    if (!f) {
375
+        perror(buffer);
376
+        return -1;
377
+    }
378
+    v = tgaSave(f, image, width, height, type);
379
+    fclose(f);
380
+    return v;
381
+}
382
+

+ 33
- 0
src/utils/time.cpp View File

@@ -0,0 +1,33 @@
1
+/*!
2
+ * \file include/utils/time.h
3
+ * \brief Time handling utilities
4
+ *
5
+ * \author xythobuz
6
+ * \author Mongoose
7
+ */
8
+
9
+#include "utils/time.h"
10
+
11
+struct timeval system_timer_start;
12
+struct timeval system_timer_stop;
13
+struct timezone system_timer_tz;
14
+
15
+unsigned int systemTimerGet() {
16
+    gettimeofday(&system_timer_stop, &system_timer_tz);
17
+
18
+    if (system_timer_start.tv_usec > system_timer_stop.tv_usec) {
19
+        system_timer_stop.tv_usec += 1000000;
20
+        system_timer_stop.tv_sec--;
21
+    }
22
+
23
+    system_timer_stop.tv_usec -= system_timer_start.tv_usec;
24
+    system_timer_stop.tv_sec -= system_timer_start.tv_sec;
25
+
26
+    return ((system_timer_stop.tv_sec - system_timer_start.tv_sec) * 1000)
27
+        + ((system_timer_stop.tv_usec - system_timer_start.tv_usec) / 1000);
28
+}
29
+
30
+void systemTimerReset() {
31
+    gettimeofday(&system_timer_start, &system_timer_tz);
32
+}
33
+

Loading…
Cancel
Save