initial
git-svn-id: svn://svn.icculus.org/netradiant/trunk@1 61c419a2-8eb2-4b30-bcec-8cead039b335
This commit is contained in:
295
libs/pivot.h
Normal file
295
libs/pivot.h
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
Copyright (C) 2001-2006, William Joseph.
|
||||
All Rights Reserved.
|
||||
|
||||
This file is part of GtkRadiant.
|
||||
|
||||
GtkRadiant is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
GtkRadiant is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GtkRadiant; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(INCLUDED_PIVOT_H)
|
||||
#define INCLUDED_PIVOT_H
|
||||
|
||||
#include "math/matrix.h"
|
||||
|
||||
|
||||
inline void billboard_viewplaneOriented(Matrix4& rotation, const Matrix4& world2screen)
|
||||
{
|
||||
#if 1
|
||||
rotation = g_matrix4_identity;
|
||||
Vector3 x(vector3_normalised(vector4_to_vector3(world2screen.x())));
|
||||
Vector3 y(vector3_normalised(vector4_to_vector3(world2screen.y())));
|
||||
Vector3 z(vector3_normalised(vector4_to_vector3(world2screen.z())));
|
||||
vector4_to_vector3(rotation.y()) = Vector3(x.y(), y.y(), z.y());
|
||||
vector4_to_vector3(rotation.z()) = vector3_negated(Vector3(x.z(), y.z(), z.z()));
|
||||
vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
|
||||
vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
|
||||
#else
|
||||
Matrix4 screen2world(matrix4_full_inverse(world2screen));
|
||||
|
||||
Vector3 near_(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(0, 0, -1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Vector3 far_(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(0, 0, 1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Vector3 up(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(0, 1, -1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
rotation = g_matrix4_identity;
|
||||
vector4_to_vector3(rotation.y()) = vector3_normalised(vector3_subtracted(up, near_));
|
||||
vector4_to_vector3(rotation.z()) = vector3_normalised(vector3_subtracted(near_, far_));
|
||||
vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
|
||||
vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void billboard_viewpointOriented(Matrix4& rotation, const Matrix4& world2screen)
|
||||
{
|
||||
Matrix4 screen2world(matrix4_full_inverse(world2screen));
|
||||
|
||||
#if 1
|
||||
rotation = g_matrix4_identity;
|
||||
vector4_to_vector3(rotation.y()) = vector3_normalised(vector4_to_vector3(screen2world.y()));
|
||||
vector4_to_vector3(rotation.z()) = vector3_negated(vector3_normalised(vector4_to_vector3(screen2world.z())));
|
||||
vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
|
||||
vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
|
||||
#else
|
||||
Vector3 near_(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15], -1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Vector3 far_(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15], 1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
Vector3 up(
|
||||
vector4_projected(
|
||||
matrix4_transformed_vector4(
|
||||
screen2world,
|
||||
Vector4(world2screen[12] / world2screen[15], world2screen[13] / world2screen[15] + 1, -1, 1)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
rotation = g_matrix4_identity;
|
||||
vector4_to_vector3(rotation.y()) = vector3_normalised(vector3_subtracted(up, near_));
|
||||
vector4_to_vector3(rotation.z()) = vector3_normalised(vector3_subtracted(near_, far_));
|
||||
vector4_to_vector3(rotation.x()) = vector3_normalised(vector3_cross(vector4_to_vector3(rotation.y()), vector4_to_vector3(rotation.z())));
|
||||
vector4_to_vector3(rotation.y()) = vector3_cross(vector4_to_vector3(rotation.z()), vector4_to_vector3(rotation.x()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
inline void ConstructObject2Screen(Matrix4& object2screen, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device, const Matrix4& device2screen)
|
||||
{
|
||||
object2screen = device2screen;
|
||||
matrix4_multiply_by_matrix4(object2screen, view2device);
|
||||
matrix4_multiply_by_matrix4(object2screen, world2view);
|
||||
matrix4_multiply_by_matrix4(object2screen, object2world);
|
||||
}
|
||||
|
||||
inline void ConstructObject2Device(Matrix4& object2screen, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device)
|
||||
{
|
||||
object2screen = view2device;
|
||||
matrix4_multiply_by_matrix4(object2screen, world2view);
|
||||
matrix4_multiply_by_matrix4(object2screen, object2world);
|
||||
}
|
||||
|
||||
inline void ConstructDevice2Object(Matrix4& device2object, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device)
|
||||
{
|
||||
ConstructObject2Device(device2object, object2world, world2view, view2device);
|
||||
matrix4_full_invert(device2object);
|
||||
}
|
||||
|
||||
//! S = ( Inverse(Object2Screen *post ScaleOf(Object2Screen) ) *post Object2Screen
|
||||
inline void pivot_scale(Matrix4& scale, const Matrix4& pivot2screen)
|
||||
{
|
||||
Matrix4 pre_scale(g_matrix4_identity);
|
||||
pre_scale[0] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.x())));
|
||||
pre_scale[5] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.y())));
|
||||
pre_scale[10] = static_cast<float>(vector3_length(vector4_to_vector3(pivot2screen.z())));
|
||||
|
||||
scale = pivot2screen;
|
||||
matrix4_multiply_by_matrix4(scale, pre_scale);
|
||||
matrix4_full_invert(scale);
|
||||
matrix4_multiply_by_matrix4(scale, pivot2screen);
|
||||
}
|
||||
|
||||
// scale by (inverse) W
|
||||
inline void pivot_perspective(Matrix4& scale, const Matrix4& pivot2screen)
|
||||
{
|
||||
scale = g_matrix4_identity;
|
||||
scale[0] = scale[5] = scale[10] = pivot2screen[15];
|
||||
}
|
||||
|
||||
inline void ConstructDevice2Manip(Matrix4& device2manip, const Matrix4& object2world, const Matrix4& world2view, const Matrix4& view2device, const Matrix4& device2screen)
|
||||
{
|
||||
Matrix4 pivot2screen;
|
||||
ConstructObject2Screen(pivot2screen, object2world, world2view, view2device, device2screen);
|
||||
|
||||
ConstructObject2Device(device2manip, object2world, world2view, view2device);
|
||||
|
||||
Matrix4 scale;
|
||||
pivot_scale(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(device2manip, scale);
|
||||
pivot_perspective(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(device2manip, scale);
|
||||
|
||||
matrix4_full_invert(device2manip);
|
||||
}
|
||||
|
||||
inline void Pivot2World_worldSpace(Matrix4& manip2world, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
|
||||
{
|
||||
manip2world = pivot2world;
|
||||
|
||||
Matrix4 pivot2screen;
|
||||
ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
|
||||
|
||||
Matrix4 scale;
|
||||
pivot_scale(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
pivot_perspective(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
}
|
||||
|
||||
inline void Pivot2World_viewpointSpace(Matrix4& manip2world, Vector3& axis, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
|
||||
{
|
||||
manip2world = pivot2world;
|
||||
|
||||
Matrix4 pivot2screen;
|
||||
ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
|
||||
|
||||
Matrix4 scale;
|
||||
pivot_scale(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
|
||||
billboard_viewpointOriented(scale, pivot2screen);
|
||||
axis = vector4_to_vector3(scale.z());
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
|
||||
pivot_perspective(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
}
|
||||
|
||||
inline void Pivot2World_viewplaneSpace(Matrix4& manip2world, const Matrix4& pivot2world, const Matrix4& modelview, const Matrix4& projection, const Matrix4& viewport)
|
||||
{
|
||||
manip2world = pivot2world;
|
||||
|
||||
Matrix4 pivot2screen;
|
||||
ConstructObject2Screen(pivot2screen, pivot2world, modelview, projection, viewport);
|
||||
|
||||
Matrix4 scale;
|
||||
pivot_scale(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
|
||||
billboard_viewplaneOriented(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
|
||||
pivot_perspective(scale, pivot2screen);
|
||||
matrix4_multiply_by_matrix4(manip2world, scale);
|
||||
}
|
||||
|
||||
|
||||
#include "renderable.h"
|
||||
#include "cullable.h"
|
||||
#include "render.h"
|
||||
|
||||
const Colour4b g_colour_x(255, 0, 0, 255);
|
||||
const Colour4b g_colour_y(0, 255, 0, 255);
|
||||
const Colour4b g_colour_z(0, 0, 255, 255);
|
||||
|
||||
class Shader;
|
||||
|
||||
class RenderablePivot : public OpenGLRenderable
|
||||
{
|
||||
VertexBuffer<PointVertex> m_vertices;
|
||||
public:
|
||||
mutable Matrix4 m_localToWorld;
|
||||
typedef Static<Shader*> StaticShader;
|
||||
static Shader* getShader()
|
||||
{
|
||||
return StaticShader::instance();
|
||||
}
|
||||
|
||||
RenderablePivot()
|
||||
{
|
||||
m_vertices.reserve(6);
|
||||
|
||||
m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_x));
|
||||
m_vertices.push_back(PointVertex(Vertex3f(16, 0, 0), g_colour_x));
|
||||
|
||||
m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_y));
|
||||
m_vertices.push_back(PointVertex(Vertex3f(0, 16, 0), g_colour_y));
|
||||
|
||||
m_vertices.push_back(PointVertex(Vertex3f(0, 0, 0), g_colour_z));
|
||||
m_vertices.push_back(PointVertex(Vertex3f(0, 0, 16), g_colour_z));
|
||||
}
|
||||
|
||||
void render(RenderStateFlags state) const
|
||||
{
|
||||
if(m_vertices.size() == 0) return;
|
||||
if(m_vertices.data() == 0) return;
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(PointVertex), &m_vertices.data()->vertex);
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PointVertex), &m_vertices.data()->colour);
|
||||
glDrawArrays(GL_LINES, 0, m_vertices.size());
|
||||
}
|
||||
|
||||
void render(Renderer& renderer, const VolumeTest& volume, const Matrix4& localToWorld) const
|
||||
{
|
||||
renderer.PushState();
|
||||
|
||||
Pivot2World_worldSpace(m_localToWorld, localToWorld, volume.GetModelview(), volume.GetProjection(), volume.GetViewport());
|
||||
|
||||
renderer.Highlight(Renderer::ePrimitive, false);
|
||||
renderer.SetState(getShader(), Renderer::eWireframeOnly);
|
||||
renderer.SetState(getShader(), Renderer::eFullMaterials);
|
||||
renderer.addRenderable(*this, m_localToWorld);
|
||||
|
||||
renderer.PopState();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user