Implemented proper skybox loading.
[openstranded.git] / src / eal / horde3d / converter.cc
blobbc727398bcbfbb3b4d7661f452ccaffb3c3a4da4
1 /*
2 * Horde3D file format converter
4 * Copyright (C) 2009 Mathias Gottschlag
6 * This file is part of OpenStranded
8 * OpenStranded is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * OpenStranded is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with OpenStranded. If not, see <http://www.gnu.org/licenses/>.
22 #include "eal/horde3d/converter.hh"
24 #include <fstream>
25 #include <iostream>
26 #include <FreeImage.h>
27 #include <squish.h>
29 namespace eal
31 static void writeMipmap(std::ofstream &file, int level, FIBITMAP *image)
33 int width = FreeImage_GetWidth(image);
34 for (int i = 0; i < level; i++)
35 width /= 2;
36 // Resize bitmap
37 FIBITMAP *mipmap = FreeImage_Rescale(image, width, width, FILTER_BILINEAR);
38 // Convert bitmap data
39 if (width < 4) width = 4;
40 squish::u8 *targetdata = new squish::u8[width * width / 2];
41 squish::u8 *currentblock = targetdata;
42 for (int y = 0; y < width; y += 4)
44 for (int x = 0; x < width; x += 4)
46 squish::u8 source[16 * 4];
47 for (int i = 0; i < 16; i++)
49 RGBQUAD color;
50 FreeImage_GetPixelColor(mipmap, width - (x + (i % 4)) - 1, width - (y + i / 4) - 1, &color);
51 ((unsigned int*)source)[i] = *(unsigned int*)&color;
53 squish::Compress(source, currentblock, squish::kDxt1);
54 currentblock += 8;
57 // Write data
58 file.write((const char*)targetdata, width * width / 2);
59 delete[] targetdata;
60 // Delete bitmap
61 FreeImage_Unload(mipmap);
63 Horde3DConverter::Horde3DConverter(std::string basedir)
65 this->basedir = basedir;
67 FreeImage_Initialise(false);
69 Horde3DConverter::~Horde3DConverter()
73 bool
74 Horde3DConverter::convertSkybox(std::string name)
76 // Check whether file already exists
77 std::ifstream testfile((basedir + "/extra/horde3d/models/skies/" + name + ".scene.xml").c_str());
78 if (testfile)
79 return true;
80 testfile.close();
81 // Load source images
82 printf("Source: %s\n", (basedir + "/skies/" + name + "_dn.jpg").c_str());
83 FIBITMAP *dn = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_dn.jpg").c_str());
84 if (!dn) return false;
85 FIBITMAP *up = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_up.jpg").c_str());
86 FIBITMAP *bk = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_bk.jpg").c_str());
87 FIBITMAP *fr = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_fr.jpg").c_str());
88 FIBITMAP *lf = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_lf.jpg").c_str());
89 FIBITMAP *rt = FreeImage_Load(FIF_JPEG, (basedir + "/skies/" + name + "_rt.jpg").c_str());
90 // Create output image
91 int width = FreeImage_GetWidth(dn);
92 int height = FreeImage_GetHeight(dn);
93 printf("Sky: %d/%d\n", width, height);
94 // Create cube map
95 std::ofstream ddsfile;
96 ddsfile.open((basedir + "/extra/horde3d/models/skies/" + name + ".dds").c_str(), std::ofstream::binary);
97 const char *magic = "DDS ";
98 ddsfile.write(magic, 4);
99 int size = 124;
100 ddsfile.write((const char*)&size, 4);
101 int flags = 0xa1007;
102 ddsfile.write((const char*)&flags, 4);
103 ddsfile.write((const char*)&height, 4);
104 ddsfile.write((const char*)&width, 4);
105 size = width * height / 2;
106 ddsfile.write((const char*)&size, 4);
107 int depth = 0;
108 ddsfile.write((const char*)&depth, 4);
109 int mipmaps = 0;
110 int mipmapsize = width;
111 while (mipmapsize > 0)
113 mipmaps++;
114 mipmapsize /= 2;
116 ddsfile.write((const char*)&mipmaps, 4);
117 int reserved[11] = {0};
118 ddsfile.write((const char*)&reserved, 44);
119 // Color format
120 size = 32;
121 ddsfile.write((const char*)&size, 4);
122 flags = 4;
123 ddsfile.write((const char*)&flags, 4);
124 magic = "DXT1";
125 ddsfile.write(magic, 4);
126 ddsfile.write((const char*)&reserved, 20);
127 // Capabilities
128 int caps = 0x00401008;
129 ddsfile.write((const char*)&caps, 4);
130 caps = 0xfe00;
131 ddsfile.write((const char*)&caps, 4);
132 ddsfile.write((const char*)&reserved, 8);
133 ddsfile.write((const char*)&reserved, 4);
134 // Image data
135 FIBITMAP *rt2 = FreeImage_ConvertTo32Bits(rt);
136 for (int i = 0; i < mipmaps; i++)
138 writeMipmap(ddsfile, i, rt2);
140 FIBITMAP *lf2 = FreeImage_ConvertTo32Bits(lf);
141 for (int i = 0; i < mipmaps; i++)
143 writeMipmap(ddsfile, i, lf2);
145 FIBITMAP *up2 = FreeImage_RotateClassic(up, 270);
146 FreeImage_Unload(up);
147 up = up2;
148 up2 = FreeImage_ConvertTo32Bits(up);
149 for (int i = 0; i < mipmaps; i++)
151 writeMipmap(ddsfile, i, up2);
153 FIBITMAP *dn2 = FreeImage_ConvertTo32Bits(dn);
154 for (int i = 0; i < mipmaps; i++)
156 writeMipmap(ddsfile, i, dn2);
158 FIBITMAP *fr2 = FreeImage_ConvertTo32Bits(fr);
159 for (int i = 0; i < mipmaps; i++)
161 writeMipmap(ddsfile, i, fr2);
163 FIBITMAP *bk2 = FreeImage_ConvertTo32Bits(bk);
164 for (int i = 0; i < mipmaps; i++)
166 writeMipmap(ddsfile, i, bk2);
168 ddsfile.close();
169 // Free used memory
170 FreeImage_Unload(dn2);
171 FreeImage_Unload(up2);
172 FreeImage_Unload(bk2);
173 FreeImage_Unload(fr2);
174 FreeImage_Unload(lf2);
175 FreeImage_Unload(rt2);
176 FreeImage_Unload(dn);
177 FreeImage_Unload(up);
178 FreeImage_Unload(bk);
179 FreeImage_Unload(fr);
180 FreeImage_Unload(lf);
181 FreeImage_Unload(rt);
182 // Create material file
183 std::ofstream material((basedir + "/extra/horde3d/models/skies/" + name + ".material.xml").c_str());
184 material << "<Material>\n";
185 material << "\t<Shader source=\"shaders/skybox.shader\"/>\n";
186 material << "\t<Sampler name=\"albedoMap\" map=\"models/skies/" << name << ".dds\" />\n";
187 material << "</Material>\n";
188 material.close();
189 // Create model file
190 std::ofstream model((basedir + "/extra/horde3d/models/skies/" + name + ".scene.xml").c_str());
191 model << "<Model name=\"skybox_" << name << "\" geometry=\"models/skybox/skybox.geo\">\n";
192 model << "\t<Mesh name=\"Box01\" material=\"models/skies/" << name << ".material.xml\" tx=\"0\""
193 " ty=\"0\" tz=\"-1\" rx=\"-90\" ry=\"0\" rz=\"-180\" sx=\"2\" sy=\"2\" sz=\"2\""
194 " batchStart=\"0\" batchCount=\"36\" vertRStart=\"0\" vertREnd=\"23\" />\n";
195 model << "</Model>\n";
196 model.close();
197 return true;