]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_light_state.cpp
Initial vogl checkin
[vogl] / src / voglcommon / vogl_light_state.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_light_state.cpp
27 #include "vogl_light_state.h"
28
29 vogl_light_state::vogl_light_state()
30     : m_valid(false)
31 {
32     VOGL_FUNC_TRACER
33 }
34
35 vogl_light_state::~vogl_light_state()
36 {
37     VOGL_FUNC_TRACER
38 }
39
40 bool vogl_light_state::snapshot(const vogl_context_info &context_info)
41 {
42     VOGL_FUNC_TRACER
43
44     clear();
45
46     VOGL_CHECK_GL_ERROR;
47
48     bool any_gl_errors = false;
49
50     m_lights.resize(context_info.get_max_lights());
51     for (uint light = 0; light < context_info.get_max_lights(); light++)
52     {
53 #define GET_FLOAT(light, pname)                                            \
54     do                                                                     \
55     {                                                                      \
56         float values[4] = { 0, 0, 0, 0 };                                  \
57         GL_ENTRYPOINT(glGetLightfv)(get_light_enum(light), pname, values); \
58         if (vogl_check_gl_error())                                          \
59             any_gl_errors = true;                                          \
60         m_lights[light].insert(pname, 0, values, sizeof(values[0]));       \
61     } while (0)
62         GET_FLOAT(light, GL_CONSTANT_ATTENUATION);
63         GET_FLOAT(light, GL_LINEAR_ATTENUATION);
64         GET_FLOAT(light, GL_QUADRATIC_ATTENUATION);
65         GET_FLOAT(light, GL_SPOT_EXPONENT);
66         GET_FLOAT(light, GL_SPOT_CUTOFF);
67         GET_FLOAT(light, GL_AMBIENT);
68         GET_FLOAT(light, GL_DIFFUSE);
69         GET_FLOAT(light, GL_SPECULAR);
70         GET_FLOAT(light, GL_POSITION);
71         GET_FLOAT(light, GL_SPOT_DIRECTION);
72 #undef GET_FLOAT
73     }
74
75     if (any_gl_errors)
76     {
77         clear();
78
79         vogl_error_printf("%s: GL error while enumerating light params\n", VOGL_METHOD_NAME);
80
81         return false;
82     }
83
84     m_valid = true;
85
86     return true;
87 }
88
89 bool vogl_light_state::set_light_parameter(uint light, GLenum pname) const
90 {
91     VOGL_FUNC_TRACER
92
93     GLenum light_enum = get_light_enum(light);
94
95     const vogl_state_data *pData = m_lights[light].find(pname);
96     if (!pData)
97         return false;
98
99     enum
100     {
101         cMaxElements = 4
102     };
103     if (pData->get_num_elements() > cMaxElements)
104     {
105         VOGL_ASSERT_ALWAYS;
106         return false;
107     }
108
109     if ((pData->get_data_type() == cSTFloat) || (pData->get_data_type() == cSTDouble))
110     {
111         float fvals[cMaxElements];
112         pData->get_float(fvals);
113         if (pData->get_num_elements() == 1)
114             GL_ENTRYPOINT(glLightf)(light_enum, pname, fvals[0]);
115         else
116             GL_ENTRYPOINT(glLightfv)(light_enum, pname, fvals);
117     }
118     else
119     {
120         int ivals[cMaxElements];
121         pData->get_int(ivals);
122         if (pData->get_num_elements() == 1)
123             GL_ENTRYPOINT(glLighti)(light_enum, pname, ivals[0]);
124         else
125             GL_ENTRYPOINT(glLightiv)(light_enum, pname, ivals);
126     }
127
128     return !vogl_check_gl_error();
129 }
130
131 bool vogl_light_state::restore(const vogl_context_info &context_info) const
132 {
133     VOGL_FUNC_TRACER
134
135     if (!m_valid)
136     {
137         VOGL_ASSERT_ALWAYS;
138     }
139
140     const uint num_lights = math::minimum<uint>(m_lights.size(), context_info.get_max_lights());
141     if (m_lights.size() > context_info.get_max_lights())
142     {
143         vogl_warning_printf("%s: Object has %u lights, but the context only supports %u lights!\n", VOGL_METHOD_NAME, m_lights.size(), context_info.get_max_lights());
144     }
145
146     for (uint light = 0; light < num_lights; light++)
147     {
148 #define SET_FLOAT(light, pname) set_light_parameter(light, pname)
149         SET_FLOAT(light, GL_CONSTANT_ATTENUATION);
150         SET_FLOAT(light, GL_LINEAR_ATTENUATION);
151         SET_FLOAT(light, GL_QUADRATIC_ATTENUATION);
152         SET_FLOAT(light, GL_SPOT_EXPONENT);
153         SET_FLOAT(light, GL_SPOT_CUTOFF);
154         SET_FLOAT(light, GL_AMBIENT);
155         SET_FLOAT(light, GL_DIFFUSE);
156         SET_FLOAT(light, GL_SPECULAR);
157         SET_FLOAT(light, GL_POSITION);
158         SET_FLOAT(light, GL_SPOT_DIRECTION);
159 #undef SET_FLOAT
160     }
161
162     return !vogl_check_gl_error();
163 }
164
165 void vogl_light_state::clear()
166 {
167     m_lights.clear();
168     m_valid = false;
169 }
170
171 bool vogl_light_state::serialize(json_node &node, vogl_blob_manager &blob_manager) const
172 {
173     VOGL_FUNC_TRACER
174
175     if (!m_valid)
176     {
177         VOGL_ASSERT_ALWAYS;
178         return false;
179     }
180
181     json_node &light_array_node = node.add_array("lights");
182     for (uint i = 0; i < m_lights.size(); i++)
183         if (!m_lights[i].serialize(light_array_node.add_object(), blob_manager))
184             return false;
185
186     return true;
187 }
188
189 bool vogl_light_state::deserialize(const json_node &node, const vogl_blob_manager &blob_manager)
190 {
191     VOGL_FUNC_TRACER
192
193     clear();
194
195     const json_node *pLight_array_node = node.find_child_array("lights");
196     if (!pLight_array_node)
197         return false;
198     if (!pLight_array_node->are_all_children_objects())
199         return false;
200
201     m_lights.resize(pLight_array_node->size());
202
203     for (uint i = 0; i < m_lights.size(); i++)
204     {
205         if (!m_lights[i].deserialize(*pLight_array_node->get_child(i), blob_manager))
206         {
207             clear();
208             return false;
209         }
210     }
211
212     m_valid = true;
213
214     return true;
215 }