2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #if !defined(INCLUDED_PIVOT_H)
23 #define INCLUDED_PIVOT_H
25 #include "math/matrix.h"
28 inline void billboard_viewplaneOriented(Matrix4& rotation, const Matrix4& world2screen)
31 rotation = g_matrix4_identity;
32 Vector3 x(vector3_normalised(vector4_to_vector3(world2screen.x())));
33 Vector3 y(vector3_normalised(vector4_to_vector3(world2screen.y())));
34 Vector3 z(vector3_normalised(vector4_to_vector3(world2screen.z())));
35 vector4_to_vector3(rotation.y()) = Vector3(x.y(), y.y(), z.y());
36 vector4_to_vector3(rotation.z()) = vector3_negated(Vector3(x.z(), y.z(), z.z()));
37 vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
38 vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
40 Matrix4 screen2world(matrix4_full_inverse(world2screen));
44 matrix4_transformed_vector4(
53 matrix4_transformed_vector4(
62 matrix4_transformed_vector4(
69 rotation = g_matrix4_identity;
70 vector4_to_vector3(rotation.y()) = vector3_normalised(vector3_subtracted(up, near_));
71 vector4_to_vector3(rotation.z()) = vector3_normalised(vector3_subtracted(near_, far_));
72 vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
73 vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
77 inline void billboard_viewpointOriented(Matrix4& rotation, const Matrix4& world2screen)
79 Matrix4 screen2world(matrix4_full_inverse(world2screen));
82 rotation = g_matrix4_identity;
83 vector4_to_vector3(rotation.y()) = vector3_normalised(vector4_to_vector3(screen2world.y()));
84 vector4_to_vector3(rotation.z()) = vector3_negated(vector3_normalised(vector4_to_vector3(screen2world.z())));
85 vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
86 vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
90 matrix4_transformed_vector4(
92 Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15], -1, 1)
99 matrix4_transformed_vector4(
101 Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15], 1, 1)
108 matrix4_transformed_vector4(
110 Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15] + 1, -1, 1)
115 rotation = g_matrix4_identity;
116 vector4_to_vector3(rotation.y()) = vector3_normalised(vector3_subtracted(up, near_));
117 vector4_to_vector3(rotation.z()) = vector3_normalised(vector3_subtracted(near_, far_));
118 vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
119 vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
124 inline void ConstructObject2Screen(Matrix4& object2screen, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device, const Matrix4& device2screen)
126 object2screen = device2screen;
127 matrix4_multiply_by_matrix4(object2screen, view2device);
128 matrix4_multiply_by_matrix4(object2screen, world2view);
129 matrix4_multiply_by_matrix4(object2screen, object2world);
132 inline void ConstructObject2Device(Matrix4& object2screen, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device)
134 object2screen = view2device;
135 matrix4_multiply_by_matrix4(object2screen, world2view);
136 matrix4_multiply_by_matrix4(object2screen, object2world);
139 inline void ConstructDevice2Object(Matrix4& device2object, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device)
141 ConstructObject2Device(device2object, object2world, world2view, view2device);
142 matrix4_full_invert(device2object);
145 //! S = ( Inverse(Object2Screen *post ScaleOf(Object2Screen) ) *post Object2Screen
146 inline void pivot_scale(Matrix4& scale, const Matrix4& pivot2screen)
148 Matrix4 pre_scale(g_matrix4_identity);
149 pre_scale[0] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.x())));
150 pre_scale[5] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.y())));
151 pre_scale[10] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.z())));
153 scale = pivot2screen;
154 matrix4_multiply_by_matrix4(scale, pre_scale);
155 matrix4_full_invert(scale);
156 matrix4_multiply_by_matrix4(scale, pivot2screen);
159 // scale by (inverse) W
160 inline void pivot_perspective(Matrix4& scale, const Matrix4& pivot2screen)
162 scale = g_matrix4_identity;
163 scale[0] = scale[5] = scale[10] = pivot2screen[15];
166 inline void ConstructDevice2Manip(Matrix4& device2manip, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device, const Matrix4& device2screen)
168 Matrix4 pivot2screen;
169 ConstructObject2Screen(pivot2screen, object2world, world2view, view2device, device2screen);
171 ConstructObject2Device(device2manip, object2world, world2view, view2device);
174 pivot_scale(scale, pivot2screen);
175 matrix4_multiply_by_matrix4(device2manip, scale);
176 pivot_perspective(scale, pivot2screen);
177 matrix4_multiply_by_matrix4(device2manip, scale);
179 matrix4_full_invert(device2manip);
182 inline void Pivot2World_worldSpace(Matrix4& manip2world, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
184 manip2world = pivot2world;
186 Matrix4 pivot2screen;
187 ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
190 pivot_scale(scale, pivot2screen);
191 matrix4_multiply_by_matrix4(manip2world, scale);
192 pivot_perspective(scale, pivot2screen);
193 matrix4_multiply_by_matrix4(manip2world, scale);
196 inline void Pivot2World_viewpointSpace(Matrix4& manip2world, Vector3& axis, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
198 manip2world = pivot2world;
200 Matrix4 pivot2screen;
201 ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
204 pivot_scale(scale, pivot2screen);
205 matrix4_multiply_by_matrix4(manip2world, scale);
207 billboard_viewpointOriented(scale, pivot2screen);
208 axis = vector4_to_vector3(scale.z());
209 matrix4_multiply_by_matrix4(manip2world, scale);
211 pivot_perspective(scale, pivot2screen);
212 matrix4_multiply_by_matrix4(manip2world, scale);
215 inline void Pivot2World_viewplaneSpace(Matrix4& manip2world, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
217 manip2world = pivot2world;
219 Matrix4 pivot2screen;
220 ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
223 pivot_scale(scale, pivot2screen);
224 matrix4_multiply_by_matrix4(manip2world, scale);
226 billboard_viewplaneOriented(scale, pivot2screen);
227 matrix4_multiply_by_matrix4(manip2world, scale);
229 pivot_perspective(scale, pivot2screen);
230 matrix4_multiply_by_matrix4(manip2world, scale);
234 #include "renderable.h"
235 #include "cullable.h"
238 const Colour4b g_colour_x(255, 0, 0, 255);
239 const Colour4b g_colour_y(0, 255, 0, 255);
240 const Colour4b g_colour_z(0, 0, 255, 255);
244 class RenderablePivot : public OpenGLRenderable
246 VertexBuffer<PointVertex> m_vertices;
248 mutable Matrix4 m_localToWorld;
249 typedef Static<Shader*> StaticShader;
250 static Shader* getShader()
252 return StaticShader::instance();
257 m_vertices.reserve(6);
259 m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_x));
260 m_vertices.push_back(PointVertex(Vertex3f(16, 0, 0), g_colour_x));
262 m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_y));
263 m_vertices.push_back(PointVertex(Vertex3f(0, 16, 0), g_colour_y));
265 m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_z));
266 m_vertices.push_back(PointVertex(Vertex3f(0, 0, 16), g_colour_z));
269 void render(RenderStateFlags state) const
271 if(m_vertices.size() == 0) return;
272 if(m_vertices.data() == 0) return;
273 glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices.data()->vertex);
274 glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices.data()->colour);
275 glDrawArrays(GL_LINES, 0, m_vertices.size());
278 void render(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
280 renderer.PushState();
282 Pivot2World_worldSpace(m_localToWorld, localToWorld, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
284 renderer.Highlight(Renderer::ePrimitive, false);
285 renderer.SetState(getShader(), Renderer::eWireframeOnly);
286 renderer.SetState(getShader(), Renderer::eFullMaterials);
287 renderer.addRenderable(*this, m_localToWorld);