#ifndef _INCLUDED_L3_WIRE_H #define _INCLUDED_L3_WIRE_H // *3D wireframe graphics* Copyright (C) Krzysztof Bosak 1999-09-24...2000-11-21 // All rights reserved. // kbosak@box43.pl // http://www.kbosak.prv.pl #include #include #include "l3_vec.h" ///////////////////////////////////////////////////////////////////// struct Transform3DH { double e11, e21, e31, t1;// Any value is perfect, stay public. double e12, e22, e32, t2;// Any value is perfect, stay public. double e13, e23, e33, t3;// Any value is perfect, stay public. inline Transform3DH(); inline void SetIdentity(); inline void ScaleX(double scaling_factor); inline void ScaleY(double scaling_factor); inline void ScaleZ(double scaling_factor); inline void Scale(double scaling_factor); inline void Scale(const Vector3D& scaling_factor); inline void MirrorX(); inline void MirrorY(); inline void MirrorZ(); inline void RotateX(double rotation_angle); inline void RotateY(double rotation_angle); inline void RotateZ(double rotation_angle); inline void RotateXYZ(const Vector3D& rotation_angle); inline void ShearXY(double shear_x, double shear_y); inline void ShearYZ(double shear_y, double shear_z); inline void ShearXZ(double shear_x, double shear_z); inline void Translate(const Vector3D& translation_vector); inline void Transform(const Transform3DH& transform); }; inline Transform3DH::Transform3DH() { SetIdentity(); } inline void Transform3DH::SetIdentity() { e11=1; e21=0; e31=0; t1=0; e12=0; e22=1; e32=0; t2=0; e13=0; e23=0; e33=1; t3=0; } inline void Transform3DH::ScaleX(double scaling_factor) { e11*=scaling_factor; e21*=scaling_factor; e31*=scaling_factor; t1*=scaling_factor; } inline void Transform3DH::ScaleY(double scaling_factor) { e12*=scaling_factor; e22*=scaling_factor; e23*=scaling_factor; t2*=scaling_factor; } inline void Transform3DH::ScaleZ(double scaling_factor) { e13*=scaling_factor; e23*=scaling_factor; e33*=scaling_factor; t3*=scaling_factor; } inline void Transform3DH::Scale(double scaling_factor) { ScaleX(scaling_factor); ScaleY(scaling_factor); ScaleZ(scaling_factor); } inline void Transform3DH::Scale(const Vector3D& scaling_factor) { ScaleX(scaling_factor.x); ScaleY(scaling_factor.y); ScaleZ(scaling_factor.z); } inline void Transform3DH::MirrorX() { ScaleX(-1); } inline void Transform3DH::MirrorY() { ScaleY(-1); } inline void Transform3DH::MirrorZ() { ScaleZ(-1); } inline void Transform3DH::RotateX(double rotation_angle) { const double sa=sin(rotation_angle); const double ca=cos(rotation_angle); const double temp1=e21*ca-e31*sa; const double temp2=e22*ca-e32*sa; const double temp3=e23*ca-e33*sa; const double temp4=e21*sa+e31*ca; const double temp5=e22*sa+e32*ca; const double temp6=e23*sa+e33*ca; e21=temp1; e22=temp2; e23=temp3; e31=temp4; e32=temp5; e33=temp6; const double temp_t2=ca*t2+sa*t3; t3=-sa*t2+ca*t3; t2=temp_t2; } inline void Transform3DH::RotateY(double rotation_angle) { const double sa=sin(rotation_angle); const double ca=cos(rotation_angle); const double temp1=e11*ca-e31*sa; const double temp2=e12*ca-e32*sa; const double temp3=e13*ca-e33*sa; const double temp4=e11*sa+e31*ca; const double temp5=e12*sa+e32*ca; const double temp6=e13*sa+e33*ca; e11=temp1; e12=temp2; e13=temp3; e31=temp4; e32=temp5; e33=temp6; const double temp_t1=ca*t1+sa*t3; t3=-sa*t1+ca*t3; t1=temp_t1; } inline void Transform3DH::RotateZ(double rotation_angle) { const double sa=sin(rotation_angle); const double ca=cos(rotation_angle); const double temp1=e11*ca-e21*sa; const double temp2=e12*ca-e22*sa; const double temp3=e13*ca-e23*sa; const double temp4=e11*sa+e21*ca; const double temp5=e12*sa+e22*ca; const double temp6=e13*sa+e23*ca; e11=temp1; e12=temp2; e13=temp3; e21=temp4; e22=temp5; e23=temp6; const double temp_t1=ca*t1+sa*t2; t2=-sa*t1+ca*t2; t1=temp_t1; } inline void Transform3DH::RotateXYZ(const Vector3D& rotation_angle) { RotateX(rotation_angle.x); RotateY(rotation_angle.y); RotateZ(rotation_angle.z); } inline void Transform3DH::ShearXY(double shear_x, double shear_y) { e11+=shear_x*e13; e21+=shear_x*e23; e31+=shear_x*e33; t1+=shear_x*t3; e12+=shear_y*e13; e22+=shear_y*e23; e32+=shear_y*e33; t2+=shear_y*t3; } inline void Transform3DH::ShearYZ(double shear_y, double shear_z) { e12+=shear_y*e11; e22+=shear_y*e21; e32+=shear_y*e31; t2+=shear_y*t1; e13+=shear_z*e11; e23+=shear_z*e21; e33+=shear_z*e31; t3+=shear_z*t1; } inline void Transform3DH::ShearXZ(double shear_x, double shear_z) { e11+=shear_x*e12; e21+=shear_x*e22; e31+=shear_x*e32; t1+=shear_x*t2; e13+=shear_z*e12; e23+=shear_z*e22; e33+=shear_z*e32; t3+=shear_z*t2; } inline void Transform3DH::Translate(const Vector3D& translation_vector) { t1+=translation_vector.x; t2+=translation_vector.y; t3+=translation_vector.z; } inline void Transform3DH::Transform(const Transform3DH& transform) { const double temp_e11=transform.e11*e11+transform.e21*e12+transform.e31*e13; const double temp_e12=transform.e12*e11+transform.e22*e12+transform.e32*e13; const double temp_e13=transform.e13*e11+transform.e23*e12+transform.e33*e13; const double temp_e21=transform.e11*e21+transform.e21*e22+transform.e31*e23; const double temp_e22=transform.e12*e21+transform.e22*e22+transform.e32*e23; const double temp_e23=transform.e13*e21+transform.e23*e22+transform.e33*e23; const double temp_e31=transform.e11*e31+transform.e21*e32+transform.e31*e33; const double temp_e32=transform.e12*e31+transform.e22*e32+transform.e32*e33; const double temp_e33=transform.e13*e31+transform.e23*e32+transform.e33*e33; const double temp_t1=transform.e11*t1+transform.e21*t2+transform.e31*t3+transform.t1; const double temp_t2=transform.e12*t1+transform.e22*t2+transform.e32*t3+transform.t2; const double temp_t3=transform.e13*t1+transform.e23*t2+transform.e33*t3+transform.t3; e11=temp_e11; e12=temp_e12; e13=temp_e13; e21=temp_e21; e22=temp_e22; e23=temp_e23; e31=temp_e31; e32=temp_e32; e33=temp_e33; t1=temp_t1; t2=temp_t2; t3=temp_t3; } ///////////////////////////////////////////////////////////////////////////// struct Vector3DH: public Vector3D { double w;// Any value is perfect, stay public. inline Vector3DH(); inline Vector3DH(double x, double y, double z); inline Vector3DH(double x, double y, double z, double w_); inline void Homogenize(); inline void Transform(const Transform3DH& transform); }; inline Vector3DH::Vector3DH() :w(1) { } inline Vector3DH::Vector3DH(double x, double y, double z) :Vector3D(x, y, z), w(1) { } inline Vector3DH::Vector3DH(double x, double y, double z, double w_) :Vector3D(x, y, z), w(w_) { assert(w!=0); } inline void Vector3DH::Homogenize() { assert(w!=0); if(w==1) return; const double mul=1/w; x*=mul; y*=mul; z*=mul; w=1; } inline void Vector3DH::Transform(const Transform3DH& transform) { assert(w!=0); const double temp1=transform.e11*x+transform.e21*y+transform.e31*z+transform.t1*w; const double temp2=transform.e12*x+transform.e22*y+transform.e32*z+transform.t2*w; z=transform.e13*x+transform.e23*y+transform.e33*z+transform.t3*w; x=temp1; y=temp2; } ///////////////////////////////////////////////////////////////////// struct Triangle3DH { Vector3DH v1;// Any value is perfect, stay public. Vector3DH v2;// Any value is perfect, stay public. Vector3DH v3;// Any value is perfect, stay public. inline Triangle3DH(); inline Triangle3DH(const Vector3DH& v1_, const Vector3DH& v2_, const Vector3DH& v3_); inline void Homogenize(); inline void Scale(double scaling_factor); inline void Translate(const Vector3D& vector); inline void RotateX(double angle); inline void RotateY(double angle); inline void RotateZ(double angle); inline void RotateX(double sa, double ca); inline void RotateY(double sa, double ca); inline void RotateZ(double sa, double ca); inline void Transform(const Transform3DH& transform); }; inline Triangle3DH::Triangle3DH() { } inline Triangle3DH::Triangle3DH(const Vector3DH& v1_, const Vector3DH& v2_, const Vector3DH& v3_) : v1(v1_), v2(v2_), v3(v3_) { } inline void Triangle3DH::Homogenize() { v1.Homogenize(); v2.Homogenize(); v3.Homogenize(); } inline void Triangle3DH::Scale(double scaling_factor) { v1*=scaling_factor; v2*=scaling_factor; v3*=scaling_factor; } inline void Triangle3DH::Translate(const Vector3D& vector) { v1+=vector; v2+=vector; v3+=vector; } inline void Triangle3DH::RotateX(double angle) { const double sa=sin(angle); const double ca=cos(angle); v1.RotateX(sa, ca); v2.RotateX(sa, ca); v3.RotateX(sa, ca); } inline void Triangle3DH::RotateY(double angle) { const double sa=sin(angle); const double ca=cos(angle); v1.RotateY(sa, ca); v2.RotateY(sa, ca); v3.RotateY(sa, ca); } inline void Triangle3DH::RotateZ(double angle) { const double sa=sin(angle); const double ca=cos(angle); v1.RotateZ(sa, ca); v2.RotateZ(sa, ca); v3.RotateZ(sa, ca); } inline void Triangle3DH::RotateX(double sa, double ca) { v1.RotateX(sa, ca); v2.RotateX(sa, ca); v3.RotateX(sa, ca); } inline void Triangle3DH::RotateY(double sa, double ca) { v1.RotateY(sa, ca); v2.RotateY(sa, ca); v3.RotateY(sa, ca); } inline void Triangle3DH::RotateZ(double sa, double ca) { v1.RotateZ(sa, ca); v2.RotateZ(sa, ca); v3.RotateZ(sa, ca); } inline void Triangle3DH::Transform(const Transform3DH& transform) { v1.Transform(transform); v2.Transform(transform); v3.Transform(transform); } ///////////////////////////////////////////////////////////////////// struct WireFramePoint2D { double x;// Any value is perfect, stay public. double y;// Any value is perfect, stay public. inline WireFramePoint2D() { } inline WireFramePoint2D(double xarg, double yarg) : x(xarg), y(yarg) { } }; ///////////////////////////////////////////////////////////////////// class WireFrameObject { private: basearray _triangle; basearray _subobject; public: inline explicit WireFrameObject(int triangles); inline void AddSubObject(WireFrameObject* subobject); inline int TotalTriangles() const; inline const Triangle3DH& Triangle(int triangle_index) const; inline void SetTriangle(int triangle_index, const Triangle3DH& triangle); inline void Transform(const Transform3DH& transform); inline void TransformAtReference(const Transform3DH& transform, const Vector3D& reference); inline void OrthogonalProjection(basearray& result_points, const WireFramePoint2D& center) const; inline void PerspectiveProjection(basearray& result_points, const WireFramePoint2D& center, double screen_distance, double viewer_distance) const; }; inline WireFrameObject::WireFrameObject(int triangles) : _triangle(triangles) { assert(triangles>0); } inline void WireFrameObject::AddSubObject(WireFrameObject* subobject) { assert(subobject!=NULL); assert(subobject!=this); _subobject.resize(_subobject.size()+1); _subobject[_subobject.size()-1]=subobject; } inline int WireFrameObject::TotalTriangles() const { return _triangle.size(); } inline const Triangle3DH& WireFrameObject::Triangle(int triangle_index) const { return _triangle[triangle_index]; } inline void WireFrameObject::SetTriangle(int triangle_index, const Triangle3DH& triangle) { _triangle[triangle_index]=triangle; } inline void WireFrameObject::Transform(const Transform3DH& transform) { const int maxi=_triangle.size(); for(int i=0; iTransform(transform); } inline void WireFrameObject::TransformAtReference(const Transform3DH& transform, const Vector3D& reference) { Transform3DH full_transform; full_transform.Translate(-reference); full_transform.Transform(transform); full_transform.Translate(reference); const int maxi=_triangle.size(); for(int i=0; iTransform(full_transform); } inline void WireFrameObject::OrthogonalProjection(basearray& result_points, const WireFramePoint2D& center) const { const int maxi=_triangle.size(); result_points.setsize(maxi*3); int fill_counter=0; const double cx=center.x; const double cy=center.y; for(int i=0; i& result_points, const WireFramePoint2D& center, double screen_distance, double viewer_distance) const { const int maxi=_triangle.size(); result_points.setsize(maxi*3); int fill_counter=0; const double cx=center.x; const double cy=center.y; for(int i=0; i