1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 #include <cstdlib>
34 #include <cmath>
35 
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif /* HAVE_CONFIG_H */
39 
40 #include <Inventor/system/gl.h>
41 #include <Inventor/C/glue/gl.h>
42 #include <Inventor/C/tidbits.h>
43 
44 #include "glue/glp.h"
45 #include "tidbitsp.h"
46 
47 // *************************************************************************
48 
49 #define COIN_DEFAULT_CUBEMAP_SIZE 64
50 
51 // *************************************************************************
52 
53 /*
54   Based on code from "Simple Bump Mapping Tutorial"
55   http://www.paulsprojects.net
56 */
57 
58 /*
59   Convert a [-1,1] vector to a [0,1] vector.
60 */
coin_pack_to_01(float * v)61 static void coin_pack_to_01(float * v)
62 {
63   float len = (float) sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
64 
65   /* normalize */
66   if (len != 0.0f) {
67     len = 1.0f / len;
68     v[0] *= len;
69     v[1] *= len;
70     v[2] *= len;
71   }
72   v[0] = 0.5f * v[0] + 0.5f;
73   v[1] = 0.5f * v[1] + 0.5f;
74   v[2] = 0.5f * v[2] + 0.5f;
75 }
76 
77 static void
coin_create_normalization_cube_map(const int size)78 coin_create_normalization_cube_map(const int size)
79 {
80   int i, j;
81 
82   float offset = 0.5f;
83   float halfsize = size * 0.5f;
84   float tmpvec[3];
85   unsigned char * ptr;
86   unsigned char * data = (unsigned char*) malloc(size*size*3);
87 
88   /* positive x */
89   ptr = data;
90   for(j = 0; j < size; j++) {
91     for(i = 0; i < size; i++) {
92       tmpvec[0] = halfsize;
93       tmpvec[1] = -(((float)j)+offset-halfsize);
94       tmpvec[2] = -(((float)i)+offset-halfsize);
95 
96       coin_pack_to_01(tmpvec);
97 
98       ptr[0]=(unsigned char)(tmpvec[0]*255);
99       ptr[1]=(unsigned char)(tmpvec[1]*255);
100       ptr[2]=(unsigned char)(tmpvec[2]*255);
101 
102       ptr += 3;
103     }
104   }
105   glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
106                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
107 
108   /* negative x */
109   ptr = data;
110 
111   for(j = 0; j < size; j++) {
112     for(i = 0; i < size; i++) {
113       tmpvec[0] = -halfsize;
114       tmpvec[1] = -(((float)j)+offset-halfsize);
115       tmpvec[2] = (((float)i)+offset-halfsize);
116 
117       coin_pack_to_01(tmpvec);
118 
119       ptr[0]=(unsigned char)(tmpvec[0]*255);
120       ptr[1]=(unsigned char)(tmpvec[1]*255);
121       ptr[2]=(unsigned char)(tmpvec[2]*255);
122 
123       ptr += 3;
124     }
125   }
126   glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
127                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
128 
129   /* positive y */
130   ptr=data;
131 
132   for(j = 0; j < size; j++) {
133       for(i = 0; i < size; i++) {
134         tmpvec[0] = ((float)i)+offset-halfsize;
135         tmpvec[1] = halfsize;
136         tmpvec[2] = ((float)j)+offset-halfsize;
137 
138         coin_pack_to_01(tmpvec);
139 
140         ptr[0]=(unsigned char)(tmpvec[0]*255);
141         ptr[1]=(unsigned char)(tmpvec[1]*255);
142         ptr[2]=(unsigned char)(tmpvec[2]*255);
143 
144         ptr += 3;
145       }
146   }
147   glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
148                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
149 
150   /* negative y */
151   ptr = data;
152 
153   for(j = 0; j < size; j++) {
154     for(i = 0; i < size; i++) {
155       tmpvec[0] = ((float)i)+offset-halfsize;
156       tmpvec[1] = -halfsize;
157       tmpvec[2] = -(((float)j)+offset-halfsize);
158 
159       coin_pack_to_01(tmpvec);
160 
161       ptr[0]=(unsigned char)(tmpvec[0]*255);
162       ptr[1]=(unsigned char)(tmpvec[1]*255);
163       ptr[2]=(unsigned char)(tmpvec[2]*255);
164 
165       ptr += 3;
166     }
167   }
168   glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
169                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
170 
171   /* positive z */
172   ptr = data;
173 
174   for(j = 0; j < size; j++) {
175     for(i = 0; i < size; i++) {
176       tmpvec[0] = ((float)i)+offset-halfsize;
177       tmpvec[1] = -(((float)j)+offset-halfsize);
178       tmpvec[2] = halfsize;
179 
180       coin_pack_to_01(tmpvec);
181 
182       ptr[0]=(unsigned char)(tmpvec[0]*255);
183       ptr[1]=(unsigned char)(tmpvec[1]*255);
184       ptr[2]=(unsigned char)(tmpvec[2]*255);
185 
186       ptr += 3;
187     }
188   }
189   glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
190                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
191 
192   /* negative z */
193   ptr=data;
194 
195   for(j = 0; j < size; j++) {
196     for(i = 0; i < size; i++) {
197       tmpvec[0] = -(((float)i)+offset-halfsize);
198       tmpvec[1] = -(((float)j)+offset-halfsize);
199       tmpvec[2] = -halfsize;
200 
201       coin_pack_to_01(tmpvec);
202 
203       ptr[0]=(unsigned char)(tmpvec[0]*255);
204       ptr[1]=(unsigned char)(tmpvec[1]*255);
205       ptr[2]=(unsigned char)(tmpvec[2]*255);
206 
207       ptr += 3;
208     }
209   }
210   glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
211                0, 3, size, size, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
212 
213   free(data);
214 }
215 
216 void
coin_apply_normalization_cube_map(const cc_glglue * glue)217 coin_apply_normalization_cube_map(const cc_glglue * glue)
218 {
219   if (glue->normalizationcubemap == 0) {
220     GLuint * dst = (GLuint*) &glue->normalizationcubemap;
221     static int CUBEMAP_SIZE = -1;
222     if (CUBEMAP_SIZE < 0) {
223       const char * env = coin_getenv("COIN_NORMALIZATION_CUBEMAP_SIZE");
224       CUBEMAP_SIZE = COIN_DEFAULT_CUBEMAP_SIZE;
225       if (env) {
226         int size = atoi(env);
227         if (size >= 2 && coin_is_power_of_two((uint32_t) size)) {
228           CUBEMAP_SIZE = size;
229         }
230       }
231     }
232     cc_glglue_glGenTextures(glue, 1, dst);
233     cc_glglue_glBindTexture(glue, GL_TEXTURE_CUBE_MAP, *dst);
234     coin_create_normalization_cube_map(CUBEMAP_SIZE);
235     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
236     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
237     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
238     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
239     glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
240   }
241   cc_glglue_glBindTexture(glue, GL_TEXTURE_CUBE_MAP,
242                           glue->normalizationcubemap);
243 }
244 
245 #undef COIN_DEFAULT_CUBEMAP_SIZE
246