00001 /*
00002 File: RadPane.cc
00003
00004 Function: Display pane for radiosity mesh
00005
00006 Author: Andrew Willmott
00007
00008 Notes:
00009 */
00010
00011 #include "RadPane.h"
00012 #include "RadMethod.h"
00013 #include "HierRad.h"
00014 #include "HRMesh.h"
00015
00016 #include "gcl/Scene.h"
00017 #include "gcl/Camera.h"
00018
00019 Void FormsScenePane::SetParent(Form *newParent)
00020 {
00021 parent = newParent;
00022 }
00023
00024
00025 // --- RadScenePane class -----------------------------------------------------
00026
00027
00028 RadScenePane::RadScenePane(Bool doubleBuf) : FormsScenePane(doubleBuf)
00029 {
00030 selPatch[0] = 0;
00031 selPatch[1] = 0;
00032 selElem[0] = 0;
00033 selElem[1] = 0;
00034 enabled = false;
00035 }
00036
00037 static scGroup *lastScene = 0;
00038
00039 Void RadScenePane::SetScene(scScenePtr scene)
00040 {
00041 Int i;
00042
00043 enabled = false;
00044 selPatch[0] = 0;
00045 selPatch[1] = 0;
00046 ScenePane::SetScene(scene);
00047 mesh = gRadControl->radObject;
00048
00049
00050 enabled = true;
00051 Redraw();
00052 }
00053
00054 Void RadScenePane::Redraw()
00055 {
00056 if (enabled)
00057 ScenePane::Redraw();
00058 }
00059
00060 Void RadScenePane::StartDrag(Coord c, Int modifiers)
00061 {
00062 if (modifiers & wmButton3)
00063 inverseTransform = inv(itsCamera->ProjMatrix() *
00064 itsCamera->ModelMatrix());
00065 ScenePane::StartDrag(c, modifiers);
00066 }
00067
00068 Void RadScenePane::EndDrag(Coord c, Int modifiers)
00069 {
00070 ScenePane::EndDrag(c, modifiers);
00071
00072
00073 if (parent)
00074 parent->Event(msgPick);
00075 }
00076
00077 Void RadScenePane::Drag(Coord c, Int modifiers)
00078 {
00079 offset = c - dragStart;
00080
00081 if (modifiersStart & wmButton3)
00082 {
00083 if (modifiersStart & wmControl)
00084 ComplexityDrag();
00085 else
00086 SelectDrag();
00087 }
00088 else
00089 ScenePane::Drag(c, modifiers);
00090 }
00091
00092 Void RadScenePane::SelectDrag()
00093 {
00094 if (!mesh)
00095 return;
00096
00097 RadElem *pickedElem;
00098 HRElem *pickedHRElem;
00099 Point p, from;
00100 Vector dir;
00101 Coord coord, start;
00102 Int i, which;
00103 Int levelsUp = (Int) (8.0 * sqrt(len(offset)));
00104
00105 // selecting light source or receiver
00106 which = 0;
00107 if (modifiersStart & wmShift)
00108 which++;
00109
00110 // de-highlight previous selection
00111 if (selPatch[which])
00112 {
00113 if (which == 0)
00114 gRadControl->pvData = 0;
00115 selPatch[which]->SetHighlight(0);
00116 selPatch[which] = 0;
00117 }
00118 if (selElem[which])
00119 {
00120 if (which == 0)
00121 gRadControl->pvData = 0;
00122 selElem[which]->SetHighlight(0);
00123 selElem[which] = 0;
00124 }
00125
00126 if (modifiersStart & wmAlt)
00127 return;
00128
00129 start[0] = 2.0 * dragStart[0] - 1.0;
00130 start[1] = 2.0 * dragStart[1] - 1.0;
00131
00132 FindWorldRay(start, inverseTransform, from, dir);
00133
00134 if (gRadControl->method != kHierarchical &&
00135 (pickedElem = mesh->ClosestIntersection(from, dir, p)))
00136 {
00137 coord = pickedElem->FindCoord(p);
00138
00139 if (selPatch[which])
00140 selPatch[which]->SetHighlight(0);
00141 else if (selElem[which])
00142 selElem[which]->SetHighlight(0);
00143
00144 if (gRadControl->method == kProgSubstruct)
00145 {
00146 selPatch[which] = pickedElem->FindContainer(coord);
00147
00148 // if this is a light, select a patch rather than an element.
00149 if (which == 1)
00150 levelsUp = 1000;
00151
00152 for (i = 0; i < levelsUp && ((HierElem*) selPatch[which])->parent;
00153 i++)
00154 selPatch[which] = ((HierElem*) selPatch[which])->parent;
00155
00156 if (i < levelsUp)
00157 if (which == 0)
00158 // jump to the container element
00159 selPatch[which] = pickedElem;
00160 }
00161 else
00162 {
00163 if (levelsUp < 3)
00164 selPatch[which] = pickedElem->FindContainer(coord);
00165 else
00166 selPatch[which] = pickedElem;
00167 }
00168
00169 if (selPatch[which])
00170 selPatch[which]->SetHighlight(2 + which);
00171 else
00172 {
00173 cerr << "Bad coord: " << coord << endl;
00174 _Error("(SelectDrag) Bad Coordinate");
00175 }
00176 gRadControl->pvData = 0;
00177 }
00178 else if (gRadControl->method == kHierarchical &&
00179 (pickedHRElem = ((HierRad*) mesh)->ClosestHRIntersection(from, dir, p)))
00180
00181 {
00182 HierElem *patchElem = 0;
00183
00184 if (selPatch[which])
00185 selPatch[which]->SetHighlight(0);
00186 else if (selElem[which])
00187 selElem[which]->SetHighlight(0);
00188
00189 i = 0;
00190
00191 if (pickedHRElem->IsPatch())
00192 {
00193 patchElem = dynamic_cast<HRMeshElem*>(pickedHRElem);
00194 coord = patchElem->FindCoord(p);
00195 patchElem = dynamic_cast<HierElem*>(patchElem->FindContainer(coord));
00196
00197 for (; i < levelsUp && patchElem->parent; i++)
00198 patchElem = patchElem->parent;
00199
00200 pickedHRElem = dynamic_cast<HRMeshElem*>(patchElem);
00201 }
00202
00203 // continue up HR hierarchy
00204 for (; i < levelsUp && pickedHRElem->eltParent; i++)
00205 pickedHRElem = pickedHRElem->eltParent;
00206
00207 if (pickedHRElem->IsPatch())
00208 {
00209 selPatch[which] = patchElem;
00210 selElem[which] = pickedHRElem;
00211 }
00212 else
00213 {
00214 selPatch[which] = 0;
00215 selElem[which] = pickedHRElem;
00216 }
00217 pickedHRElem->SetHighlight(2 + which);
00218 gRadControl->pvData = pickedHRElem;
00219 }
00220
00221 Redraw();
00222 }