diff options
Diffstat (limited to 'Magic2/ModelView.cpp')
-rw-r--r-- | Magic2/ModelView.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/Magic2/ModelView.cpp b/Magic2/ModelView.cpp new file mode 100644 index 0000000..68ab304 --- /dev/null +++ b/Magic2/ModelView.cpp @@ -0,0 +1,441 @@ +/* Starshatter OpenSource Distribution + Copyright (c) 1997-2004, Destroyer Studios LLC. + All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name "Destroyer Studios" nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + SUBSYSTEM: Magic.exe + FILE: ModelView.cpp + AUTHOR: John DiCamillo + + + OVERVIEW + ======== + Implementation of the ModelView class +*/ + +#include "stdafx.h" +#include "Magic.h" + +#include "MagicDoc.h" +#include "ModelView.h" +#include "Grid.h" +#include "Selector.h" +#include "Selection.h" + +#include "ActiveWindow.h" +#include "Color.h" +#include "Light.h" +#include "Scene.h" +#include "Screen.h" +#include "Shadow.h" +#include "Solid.h" +#include "Video.h" + +DWORD GetRealTime(); + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static ModelView* views[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +// +--------------------------------------------------------------------+ + +ModelView::ModelView(Window* c, Scene* s, DWORD m) + : CameraView(c, 0, s), view_mode(100), fill_mode(FILL_WIRE), + grid(0), az(-PI/4), el(PI/4) +{ + UseCamera(&cam); + SetViewMode(m); +} + +ModelView::~ModelView() +{ + if (views[view_mode] == this) + views[view_mode] = 0; +} + +// +--------------------------------------------------------------------+ + +void +ModelView::SetViewMode(DWORD m) +{ + if (view_mode != m) { + view_mode = m; + + double x = 1e3 * sin(az) * cos(el); + double y = 1e3 * cos(az) * cos(el); + double z = 1e3 * sin(el); + + switch (view_mode) { + case VIEW_PLAN: + cam.LookAt(Point(0,0,0), + Point(0,1e3,0), + Point(0,0,1)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_FRONT: + cam.LookAt(Point(0,0,0), + Point(0,0,1e3), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_SIDE: + cam.LookAt(Point(0,0,0), + Point(1e3,0,0), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_ORTHOGONAL); + SetFieldOfView(1.75); + break; + + case VIEW_PROJECT: + cam.LookAt(Point(0,0,0), + Point(x,z,y), + Point(0,1,0)); + SetProjectionType(Video::PROJECTION_PERSPECTIVE); + SetFieldOfView(1.75); + break; + } + + views[view_mode] = this; + } +} + +ModelView* +ModelView::FindView(DWORD mode) +{ + if (mode >= 0 && mode < 8) + return views[mode]; + + return 0; +} + +// +--------------------------------------------------------------------+ + +void +ModelView::MoveTo(Point pos) +{ + switch (view_mode) { + case VIEW_PLAN: + cam.LookAt( pos - Point(0,1e3,0), + pos, + Point(0,0,1)); + break; + + case VIEW_FRONT: + cam.LookAt( pos - Point(0,0,1e3), + pos, + Point(0,1,0)); + break; + + case VIEW_SIDE: + cam.LookAt( pos - Point(1e3,0,0), + pos, + Point(0,1,0)); + break; + } +} + +void +ModelView::MoveBy(double dx, double dy) +{ + Point pos = cam.Pos(); + + dx *= 2.00/GetFieldOfView(); + dy *= 2.00/GetFieldOfView(); + + switch (view_mode) { + case VIEW_PLAN: + pos.x -= dx; + pos.z += dy; + + cam.LookAt( pos - Point(0,1e3,0), + pos, + Point(0,0,1)); + break; + + case VIEW_FRONT: + pos.x += dx; + pos.y += dy; + + cam.LookAt( pos - Point(0,0,1e3), + pos, + Point(0,1,0)); + break; + + case VIEW_SIDE: + pos.z -= dx; + pos.y += dy; + + cam.LookAt( pos - Point(1e3,0,0), + pos, + Point(0,1,0)); + break; + } +} + +void +ModelView::SpinBy(double phi, double theta) +{ + const double limit = (0.43 * PI); + + Point pos = cam.Pos(); + double len = pos.length(); + + az += phi; + el += theta; + + if (az > PI) + az = -2*PI + az; + + else if (az < -PI) + az = 2*PI + az; + + if (el > limit) + el = limit; + else if (el < -limit) + el = -limit; + + double x = len * sin(az) * cos(el); + double y = len * cos(az) * cos(el); + double z = len * sin(el); + + cam.LookAt(Point(0,0,0), Point(x,z,y), Point(0,1,0)); +} + +void +ModelView::UseGrid(Grid* g) +{ + grid = g; +} + +void +ModelView::ZoomNormal() +{ + DWORD v = view_mode; // remember current view mode + view_mode = 100; // force set view mode to setup the view + az = -PI/4; // if this happens to be a perspective view, + el = PI/4; // reset the spin to the original 3/4ths view + + SetViewMode(v); // restore default view params for this mode +} + +// +--------------------------------------------------------------------+ + +void +ModelView::RenderScene() +{ + // activate all lights: + ListIter<Light> light_iter = scene->Lights(); + + while (++light_iter) { + Light* light = light_iter.value(); + light->SetActive(true); + } + + video->SetLights(scene->Lights()); + + RenderGrid(); + + + bool old_shadows = video->IsShadowEnabled(); + bool old_bumps = video->IsBumpMapEnabled(); + + if (fill_mode != FILL_TEXTURE) { + video->SetShadowEnabled(false); + video->SetBumpMapEnabled(false); + CameraView::RenderScene(); + } + + else { + CameraView::RenderScene(); + } + + const char* title = "ModelView"; + switch (view_mode) { + case VIEW_PLAN: title = "Top"; break; + case VIEW_FRONT: title = "Front"; break; + case VIEW_SIDE: title = "Right Side"; break; + case VIEW_PROJECT: title = "Perspective"; break; + } + + int len = strlen(title); + Rect r(6,4,200,20); + + r.x += window->GetRect().x; + r.y += window->GetRect().y; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::Black); + + r.x--; + r.y--; + + video->DrawText(title, len, r, DT_LEFT|DT_SINGLELINE, Color::White); + video->SetShadowEnabled(old_shadows); + video->SetBumpMapEnabled(old_bumps); +} + +// +--------------------------------------------------------------------+ + +void +ModelView::Render(Graphic* g, DWORD flags) +{ + if (!g) + return; + + if (!strcmp(g->Name(), "Selector")) { + Selector* selector = (Selector*) g; + + if (selector->GetViewMode() != (int) view_mode) + return; + } + + else if (!strcmp(g->Name(), "Selection")) { + Selection* selection = (Selection*) g; + selection->UseView(this); + } + + if (fill_mode == FILL_WIRE) { + Material m; + video->UseMaterial(&m); + video->SetRenderState(Video::Z_ENABLE, FALSE); + + if (g->IsSolid()) { + m.Kd = ColorValue(0.0f, 0.0f, 0.0f, 0.5f); + m.Ke = ColorValue(0.8f, 0.8f, 0.9f, 1.0f); + m.blend = Video::BLEND_ALPHA; + m.luminous = true; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + g->Render(video, flags); + } + + m.Ka = Color::Black; + m.Kd = Color::Black; + m.Ks = Color::Black; + m.Ke = Color::Black; + m.blend = Video::BLEND_SOLID; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_WIREFRAME); + + g->Render(video, flags); + video->UseMaterial(0); + } + + else if (fill_mode == FILL_SOLID) { + if (g->IsSolid() && flags != Graphic::RENDER_SOLID) + return; + + Material m; + video->UseMaterial(&m); + video->SetRenderState(Video::Z_ENABLE, TRUE); + + m.Kd = ColorValue(0.5f, 0.5f, 0.5f, 1.0f); + m.blend = Video::BLEND_SOLID; + + video->SetRenderState(Video::FILL_MODE, Video::FILL_SOLID); + + if (g->IsSolid()) { + MarkVisibleLights(g, flags); + video->SetLights(scene->Lights()); + } + + g->Render(video, flags); + video->UseMaterial(0); + } + + else if (fill_mode == FILL_TEXTURE) { + video->SetRenderState(Video::Z_ENABLE, TRUE); + video->UseMaterial(0); + + if (g->IsSolid()) { + MarkVisibleLights(g, flags); + video->SetLights(scene->Lights()); + } + + g->Render(video, flags); + } +} + +void +ModelView::RenderGrid() +{ + if (!grid || !grid->IsShow()) + return; + + int plane = Grid::GRID_XZ; + + if (view_mode == VIEW_FRONT) + plane = Grid::GRID_XY; + + else if (view_mode == VIEW_SIDE) + plane = Grid::GRID_YZ; + + grid->ShowPlane(plane); + grid->MoveTo(camera_loc * -1); + grid->ShowReference(view_mode != VIEW_PROJECT); + grid->Render(video, Graphic::RENDER_SOLID); + + video->SetRenderState(Video::Z_ENABLE, TRUE); + video->SetRenderState(Video::LIGHTING_ENABLE, TRUE); + video->UseMaterial(0); +} + +// +--------------------------------------------------------------------+ + +CPoint +ModelView::ProjectPoint(Vec3& p) +{ + CPoint result; + + switch (view_mode) { + case VIEW_PLAN: + case VIEW_FRONT: + case VIEW_SIDE: + case VIEW_PROJECT: { + Vec3 pt = p; + projector.Transform(pt); + projector.Project(pt, false); + + result.x = (LONG) (pt.x + GetWindow()->X()); + result.y = (LONG) (pt.y + GetWindow()->Y()); + } + break; + + default: + result.x = 0; + result.y = 0; + break; + } + + return result; +} |