root/cafu/trunk/Libs/MapFile.cpp

Revision 455, 10.8 KB (checked in by Carsten, 4 months ago)

Updated copyright banners (in C++ files).

Line 
1/*
2=================================================================================
3This file is part of Cafu, the open-source game engine and graphics engine
4for multiplayer, cross-platform, real-time 3D action.
5Copyright (C) 2002-2012 Carsten Fuchs Software.
6
7Cafu is free software: you can redistribute it and/or modify it under the terms
8of the GNU General Public License as published by the Free Software Foundation,
9either version 3 of the License, or (at your option) any later version.
10
11Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13PURPOSE. See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with Cafu. If not, see <http://www.gnu.org/licenses/>.
17
18For support and more information about Cafu, visit us at <http://www.cafu.de>.
19=================================================================================
20*/
21
22#include "MapFile.hpp"
23#include "ConsoleCommands/Console.hpp"
24#include "MaterialSystem/MaterialManager.hpp"
25#include "TextParser/TextParser.hpp"
26
27#include <sstream>
28
29
30using namespace cf;
31
32
33const double cf::CA3DE_SCALE=25.4;
34
35
36static void SkipGroupDef(TextParserT& TP)
37{
38    if (TP.PeekNextToken()=="Group")
39    {
40        TP.GetNextToken();  // The "Group" keyword.
41        TP.GetNextToken();  // The group number.
42    }
43}
44
45
46MapFileBrushT::MapFileBrushT(TextParserT& TP, unsigned long BrushNr)
47{
48    SkipGroupDef(TP);
49
50    while (true)
51    {
52        std::string Token=TP.GetNextToken();
53
54        if (Token=="}") break;     // End of brush
55
56        // Read the three point plane definition.
57        TP.PutBack(Token);
58        MapFilePlaneT MFPlane;
59        Vector3dT     Points[3];
60
61        for (char PointNr=0; PointNr<3; PointNr++)
62        {
63            TP.AssertAndSkipToken("(");
64            Points[PointNr].x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
65            Points[PointNr].y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
66            Points[PointNr].z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
67            TP.AssertAndSkipToken(")");
68        }
69
70        try
71        {
72            // Die Reihenfolge der Punkte (im Uhrzeigersinn) ist wichtig, damit die Normalenvektoren stets aus dem Brush HERAUS zeigen!
73            MFPlane.Plane=Plane3T<double>(Points[0], Points[1], Points[2], 0.1);
74        }
75        catch (const DivisionByZeroE&)
76        {
77            Console->Warning(cf::va("Entity ??, brush %lu: plane %lu has colinear points.\n", BrushNr, MFPlanes.Size()));
78            throw TextParserT::ParseError();
79        }
80
81
82        // Read the texture definition.
83        const std::string MaterialName=TP.GetNextToken();
84        MFPlane.Material=MaterialManager->GetMaterial(MaterialName);
85
86        if (MFPlane.Material==NULL)
87        {
88            Console->Warning(cf::va("Entity ??, Brush %lu, plane %lu: Unknown material \"%s\".", BrushNr, MFPlanes.Size(), MaterialName.c_str()));
89            throw TextParserT::ParseError();
90        }
91
92        // Begin of surface information.
93        TP.AssertAndSkipToken("(");
94
95        // Texture generation mode has to be PlaneProj (==2) for all faces of a brush.
96        TP.AssertAndSkipToken("2");
97
98        // Texture shift.
99        MFPlane.ShiftU=TP.GetNextTokenAsFloat();
100        MFPlane.ShiftV=TP.GetNextTokenAsFloat();
101
102        // The texture rotation is only relevant for CaWE. Just overread it here.
103        TP.GetNextToken();
104
105        // Texture U axis.
106        TP.AssertAndSkipToken("(");
107        MFPlane.U.x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
108        MFPlane.U.y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
109        MFPlane.U.z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
110        TP.AssertAndSkipToken(")");
111
112        // Texture V axis.
113        TP.AssertAndSkipToken("(");
114        MFPlane.V.x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
115        MFPlane.V.y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
116        MFPlane.V.z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
117        TP.AssertAndSkipToken(")");
118
119        // End of surface information.
120        TP.AssertAndSkipToken(")");
121
122        // Store plane in brush.
123        MFPlanes.PushBack(MFPlane);
124    }
125}
126
127
128MapFileBezierPatchT::MapFileBezierPatchT(TextParserT& TP)
129{
130    TP.AssertAndSkipToken("{");
131    SkipGroupDef(TP);
132
133    const std::string MaterialName=TP.GetNextToken();
134    Material=MaterialManager->GetMaterial(MaterialName);
135
136    if (Material==NULL)
137    {
138        Console->Warning("Bezier Patch: Unknown material \""+MaterialName+"\".\n");
139        throw TextParserT::ParseError();
140    }
141
142    // Skip additional surface information, as it is only relevant for CaWE.
143    TP.SkipBlock("(", ")", false);
144
145    // Dimensions
146    TP.AssertAndSkipToken("(");
147    SizeX      =TP.GetNextTokenAsInt();
148    SizeY      =TP.GetNextTokenAsInt();
149    SubdivsHorz=TP.GetNextTokenAsInt();
150    SubdivsVert=TP.GetNextTokenAsInt();
151    TP.AssertAndSkipToken(")");
152
153    for (unsigned long y=0; y<SizeY; y++)
154        for (unsigned long x=0; x<SizeX; x++)
155        {
156            TP.AssertAndSkipToken("(");
157
158            for (unsigned long Coord=0; Coord<5; Coord++)
159            {
160                ControlPoints.PushBack(TP.GetNextTokenAsFloat());
161
162                if (Coord<3) ControlPoints[ControlPoints.Size()-1]*=float(CA3DE_SCALE);
163            }
164
165            TP.AssertAndSkipToken(")");
166        }
167
168    TP.AssertAndSkipToken("}");
169}
170
171
172MapFileTerrainT::MapFileTerrainT(TextParserT& TP)
173{
174    TP.AssertAndSkipToken("{");
175    SkipGroupDef(TP);
176
177    const std::string MaterialName=TP.GetNextToken();
178    Material=MaterialManager->GetMaterial(MaterialName);
179
180    TP.AssertAndSkipToken("(");
181    Bounds.Min.x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
182    Bounds.Min.y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
183    Bounds.Min.z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
184    TP.AssertAndSkipToken(")");
185
186    TP.AssertAndSkipToken("(");
187    Bounds.Max.x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
188    Bounds.Max.y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
189    Bounds.Max.z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
190    TP.AssertAndSkipToken(")");
191
192    TP.AssertAndSkipToken("(");
193    SideLength=TP.GetNextTokenAsInt();
194    TP.AssertAndSkipToken(")");
195
196    HeightData.Clear();
197    HeightData.PushBackEmpty(SideLength*SideLength);
198
199    for (unsigned long i=0; i<HeightData.Size(); i++)
200        HeightData[i]=TP.GetNextTokenAsInt();
201
202    TP.AssertAndSkipToken("}");
203}
204
205
206MapFilePlantT::MapFilePlantT(TextParserT& TP)
207{
208    TP.AssertAndSkipToken("{");
209    SkipGroupDef(TP);
210
211    DescrFileName=TP.GetNextToken();
212    RandomSeed   =TP.GetNextTokenAsInt();
213
214    TP.AssertAndSkipToken("(");
215    Position.x=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
216    Position.y=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
217    Position.z=TP.GetNextTokenAsFloat()*CA3DE_SCALE;
218    TP.AssertAndSkipToken(")");
219
220    TP.AssertAndSkipToken("(");
221    Angles.x=TP.GetNextTokenAsFloat();
222    Angles.y=TP.GetNextTokenAsFloat();
223    Angles.z=TP.GetNextTokenAsFloat();
224    TP.AssertAndSkipToken(")");
225
226    TP.AssertAndSkipToken("}");
227}
228
229
230MapFileModelT::MapFileModelT(TextParserT& TP)
231{
232    TP.AssertAndSkipToken("{");
233    SkipGroupDef(TP);
234
235    Model    =TP.GetNextToken();
236    CollModel=TP.GetNextToken();
237    Label    =TP.GetNextToken();
238
239    TP.AssertAndSkipToken("(");
240    Origin.x=TP.GetNextTokenAsFloat()*float(CA3DE_SCALE);
241    Origin.y=TP.GetNextTokenAsFloat()*float(CA3DE_SCALE);
242    Origin.z=TP.GetNextTokenAsFloat()*float(CA3DE_SCALE);
243    TP.AssertAndSkipToken(")");
244
245    TP.AssertAndSkipToken("(");
246    Angles.x=TP.GetNextTokenAsFloat();
247    Angles.y=TP.GetNextTokenAsFloat();
248    Angles.z=TP.GetNextTokenAsFloat();
249    TP.AssertAndSkipToken(")");
250
251    Scale         =TP.GetNextTokenAsFloat()*float(CA3DE_SCALE);
252    SeqNumber     =TP.GetNextTokenAsInt();
253    FrameOffset   =TP.GetNextTokenAsFloat();
254    FrameTimeScale=TP.GetNextTokenAsFloat();
255    Animate       =(TP.GetNextTokenAsInt()!=0);
256
257    TP.AssertAndSkipToken("}");
258}
259
260
261MapFileEntityT::MapFileEntityT(unsigned long Index, TextParserT& TP)
262    : MFIndex(Index)
263{
264    TP.AssertAndSkipToken("{");
265    SkipGroupDef(TP);
266
267    while (true)
268    {
269        std::string Token=TP.GetNextToken();
270
271        if (Token=="}") break;          // End of Entity.
272
273        if (Token=="{")                 // Begin of Brush.
274        {
275            MFBrushes.PushBack(MapFileBrushT(TP, MFBrushes.Size()));
276        }
277        else if (Token=="PatchDef")     // Patch definition.
278        {
279            MFPatches.PushBack(MapFileBezierPatchT(TP));
280        }
281        else if (Token=="TerrainDef")   // Terrain definition.
282        {
283            MFTerrains.PushBack(MapFileTerrainT(TP));
284        }
285        else if (Token=="PlantDef")     // Plant definition.
286        {
287            MFPlants.PushBack(MapFilePlantT(TP));
288        }
289        else if (Token=="ModelDef")     // Model definition.
290        {
291            MFModels.PushBack(MapFileModelT(TP));
292        }
293        else                            // Property Pair.
294        {
295            const std::string Key  =Token;
296            const std::string Value=TP.GetNextToken();
297
298            if (Key=="{" || Key=="}" || Key=="(" || Key==")") throw TextParserT::ParseError();
299
300            MFProperties[Key]=Value;
301
302            if (Key=="light_radius")
303            {
304                // Translate light radius to Cafu units.
305                double LightRadius=atof(Value.c_str())*CA3DE_SCALE;
306
307                std::stringstream NewValue;
308
309                NewValue << int(LightRadius);
310
311                MFProperties[Key]=NewValue.str();
312            }
313        }
314    }
315}
316
317
318static void MapFileVersionError(const std::string& Msg)
319{
320    Console->Print("Bad map file version: Expected 13, "+Msg+".\n");
321    Console->Print("To fix this, you can load your cmap file into CaWE and re-save it.\n");
322    Console->Print("This will automatically update your file to the required version!\n");
323
324    Console->Warning("Bad map file version: Expected 13, "+Msg+".\n");
325    throw TextParserT::ParseError();
326}
327
328
329void cf::MapFileReadHeader(TextParserT& TP)
330{
331    if (TP.IsAtEOF())
332    {
333        Console->Warning("Unable to open map file.\n");
334        throw TextParserT::ParseError();
335    }
336
337    if (TP.PeekNextToken()!="Version")
338        MapFileVersionError("but could not find the \"Version\" keyword");
339
340    TP.AssertAndSkipToken("Version");
341    const std::string Version=TP.GetNextToken();
342
343    if (Version!="13")
344        MapFileVersionError("got "+Version);
345
346    // Skip any group definitions.
347    while (TP.PeekNextToken()=="GroupDef")
348    {
349        // Example line:
350        //   GroupDef 0 "control room" "rgb(189, 206, 184)" 1 1 0
351        for (unsigned int TokenNr=0; TokenNr<7; TokenNr++) TP.GetNextToken();
352    }
353}
Note: See TracBrowser for help on using the browser.