|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program 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 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
#include "HeadSpin.h"
|
|
|
|
#include "plRealTimeLightBase.h"
|
|
|
|
#include "iparamm2.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "decomp.h"
|
|
|
|
#include "hsv.h"
|
|
|
|
#include "target.h"
|
|
|
|
#include "MaxPlasmaMtls/Layers/plLayerTex.h"
|
|
|
|
#include "MaxPlasmaMtls/Layers/plLayerTexBitmapPB.h"
|
|
|
|
|
|
|
|
|
|
|
|
static int GetTargetPoint(TimeValue t, INode *inode, Point3& p)
|
|
|
|
{
|
|
|
|
Matrix3 tmat;
|
|
|
|
if (inode->GetTargetTM(t,tmat))
|
|
|
|
{
|
|
|
|
p = tmat.GetTrans();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// plBaseLightProc Functions ////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// This class provides the base functionality for all the dialog procs for
|
|
|
|
// the ParamBlock rollouts for each light
|
|
|
|
|
|
|
|
void plBaseLightProc::ILoadComboBox( HWND hComboBox, const char *names[] )
|
|
|
|
{
|
|
|
|
SendMessage(hComboBox, CB_RESETCONTENT, 0, 0);
|
|
|
|
for (int i = 0; names[i]; i++)
|
|
|
|
SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)names[i]);
|
|
|
|
SendMessage(hComboBox, CB_SETCURSEL, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plBaseLightProc::IBuildLightMesh( plRTLightBase *base, float coneSize )
|
|
|
|
{
|
|
|
|
base->BuildSpotMesh( coneSize );
|
|
|
|
base->fMesh = base->spotMesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL plBaseLightProc::DlgProc( TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|
|
|
{
|
|
|
|
IParamBlock2 *pb = map->GetParamBlock();
|
|
|
|
plRTLightBase *gl = (plRTLightBase *) pb->GetOwner();
|
|
|
|
|
|
|
|
|
|
|
|
switch( msg )
|
|
|
|
{
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
{
|
|
|
|
HWND DecayTypeCombo = GetDlgItem(hWnd, IDC_LIGHT_DECAY);
|
|
|
|
HWND ShadowStateCombo = GetDlgItem(hWnd, IDC_SHADOW_TYPE);
|
|
|
|
|
|
|
|
map->Invalidate(plRTLightBase::kProjMapTexButton);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// plLightTexPBAccessor Class Functions /////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
plLightTexPBAccessor plLightTexPBAccessor::fAccessor;
|
|
|
|
|
|
|
|
void plLightTexPBAccessor::Set( PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t )
|
|
|
|
{
|
|
|
|
plRTLightBase* Obj = (plRTLightBase*)owner;
|
|
|
|
IParamBlock2 *pb = Obj->fLightPB;
|
|
|
|
|
|
|
|
switch (id)
|
|
|
|
{
|
|
|
|
case plRTLightBase::kProjMapTexButton:
|
|
|
|
if (1) //(val.bm)->bm)
|
|
|
|
{
|
|
|
|
if (pb->GetMap())
|
|
|
|
pb->GetMap()->Invalidate(plRTLightBase::kProjMapTexButton);
|
|
|
|
//pb->SetValue(plRTLightBase::kProjMapTexButton, Obj->fIP->GetTime(), val.bm);
|
|
|
|
PBBitmap* ThisMap = val.bm;
|
|
|
|
Obj->SetProjMap(&ThisMap->bi);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plLightTexPBAccessor::Get( PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Mouse creation callback class for this plug-in
|
|
|
|
|
|
|
|
class RTLightMouseCallBack : public CreateMouseCallBack
|
|
|
|
{
|
|
|
|
plRTLightBase *ob;
|
|
|
|
public:
|
|
|
|
int proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat);
|
|
|
|
void SetObj(plRTLightBase *obj) { ob = obj; }
|
|
|
|
};
|
|
|
|
static RTLightMouseCallBack gRTMouseCallback;
|
|
|
|
|
|
|
|
|
|
|
|
int RTLightMouseCallBack::proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat)
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case MOUSE_POINT:
|
|
|
|
case MOUSE_MOVE:
|
|
|
|
switch (point)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
|
|
|
|
if (msg == MOUSE_POINT)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOUSE_ABORT:
|
|
|
|
return CREATE_ABORT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CREATE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static RTLightMouseCallBack sRTBaseLgtCreateCB;
|
|
|
|
|
|
|
|
CreateMouseCallBack* plRTLightBase::GetCreateMouseCallBack()
|
|
|
|
{
|
|
|
|
sRTBaseLgtCreateCB.SetObj(this);
|
|
|
|
|
|
|
|
return &sRTBaseLgtCreateCB;
|
|
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
plRTLightBase::plRTLightBase() : fIP(nil), fClassDesc(nil), fLightPB(nil)
|
|
|
|
{
|
|
|
|
fColor = Color(0.5f, 0.5f, 1.f);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetHSVColor(TimeValue t, Point3 &hsv)
|
|
|
|
{
|
|
|
|
DWORD rgb = HSVtoRGB ((int)(hsv[0]*255.0f), (int)(hsv[1]*255.0f), (int)(hsv[2]*255.0f));
|
|
|
|
Point3 temp = fLightPB->GetPoint3(kLightColor, t);
|
|
|
|
Point3 rgbf;
|
|
|
|
rgbf[0] = temp.x / 255.0f;
|
|
|
|
rgbf[1] = temp.y / 255.0f;
|
|
|
|
rgbf[2] = temp.z / 255.0f;
|
|
|
|
SetRGBColor(t, rgbf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Point3 plRTLightBase::GetHSVColor(TimeValue t, Interval& b)
|
|
|
|
{
|
|
|
|
int h, s, v;
|
|
|
|
Point3 rgbf = GetRGBColor(t, b);
|
|
|
|
DWORD rgb = RGB((int)(rgbf[0]*255.0f), (int)(rgbf[1]*255.0f), (int)(rgbf[2]*255.0f));
|
|
|
|
RGBtoHSV (rgb, &h, &s, &v);
|
|
|
|
return Point3(h/255.0f, s/255.0f, v/255.0f);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FZ (0.0f)
|
|
|
|
|
|
|
|
#define SET_QUAD(face, v0, v1, v2, v3) \
|
|
|
|
staticMesh[RT_OMNI +1].faces[face].setVerts(v0, v1, v2); \
|
|
|
|
staticMesh[RT_OMNI +1].faces[face].setEdgeVisFlags(1,1,0); \
|
|
|
|
staticMesh[RT_OMNI +1].faces[face+1].setVerts(v0, v2, v3); \
|
|
|
|
staticMesh[RT_OMNI +1].faces[face+1].setEdgeVisFlags(0,1,1);
|
|
|
|
|
|
|
|
void plRTLightBase::BuildStaticMeshes()
|
|
|
|
{
|
|
|
|
if(!meshBuilt) {
|
|
|
|
int nverts = 6;
|
|
|
|
int nfaces = 8;
|
|
|
|
// Build a leetle octahedron
|
|
|
|
staticMesh[RT_OMNI].setNumVerts(nverts);
|
|
|
|
staticMesh[RT_OMNI].setNumFaces(nfaces);
|
|
|
|
float s = 8.0f;
|
|
|
|
staticMesh[RT_OMNI].setVert(0, Point3( FZ,FZ, -s));
|
|
|
|
staticMesh[RT_OMNI].setVert(1, Point3( s, FZ, FZ));
|
|
|
|
staticMesh[RT_OMNI].setVert(2, Point3( FZ, s, FZ));
|
|
|
|
staticMesh[RT_OMNI].setVert(3, Point3(-s, FZ, FZ));
|
|
|
|
staticMesh[RT_OMNI].setVert(4, Point3( FZ,-s, FZ));
|
|
|
|
staticMesh[RT_OMNI].setVert(5, Point3( FZ,FZ, s));
|
|
|
|
staticMesh[RT_OMNI].faces[0].setVerts(0,1,4);
|
|
|
|
staticMesh[RT_OMNI].faces[1].setVerts(0,4,3);
|
|
|
|
staticMesh[RT_OMNI].faces[2].setVerts(0,3,2);
|
|
|
|
staticMesh[RT_OMNI].faces[3].setVerts(0,2,1);
|
|
|
|
staticMesh[RT_OMNI].faces[4].setVerts(5,1,2);
|
|
|
|
staticMesh[RT_OMNI].faces[5].setVerts(5,2,3);
|
|
|
|
staticMesh[RT_OMNI].faces[6].setVerts(5,3,4);
|
|
|
|
staticMesh[RT_OMNI].faces[7].setVerts(5,4,1);
|
|
|
|
for (int i=0; i<nfaces; i++) {
|
|
|
|
staticMesh[RT_OMNI].faces[i].setSmGroup(i);
|
|
|
|
staticMesh[RT_OMNI].faces[i].setEdgeVisFlags(1,1,1);
|
|
|
|
}
|
|
|
|
staticMesh[RT_OMNI].buildNormals();
|
|
|
|
staticMesh[RT_OMNI].EnableEdgeList(1);
|
|
|
|
|
|
|
|
// Build an "arrow"
|
|
|
|
nverts = 13;
|
|
|
|
nfaces = 16;
|
|
|
|
staticMesh[RT_OMNI+1].setNumVerts(nverts);
|
|
|
|
staticMesh[RT_OMNI+1].setNumFaces(nfaces);
|
|
|
|
s = 4.0f;
|
|
|
|
float s4 = 16.0f;
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 0, Point3( -s,-s, FZ));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 1, Point3( s,-s, FZ));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 2, Point3( s, s, FZ));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 3, Point3( -s, s, FZ));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 4, Point3( -s,-s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 5, Point3( s,-s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 6, Point3( s, s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 7, Point3( -s, s, -s4));
|
|
|
|
s *= (float)2.0;
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 8, Point3( -s,-s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert( 9, Point3( s,-s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert(10, Point3( s, s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert(11, Point3( -s, s, -s4));
|
|
|
|
staticMesh[RT_OMNI+1].setVert(12, Point3( FZ,FZ, -s4-s));
|
|
|
|
SET_QUAD( 0, 1, 0, 4, 5);
|
|
|
|
SET_QUAD( 2, 0, 3, 7, 4);
|
|
|
|
SET_QUAD( 4, 3, 2, 6, 7);
|
|
|
|
SET_QUAD( 6, 2, 1, 5, 6);
|
|
|
|
SET_QUAD( 8, 0, 1, 2, 3);
|
|
|
|
SET_QUAD(10, 8, 9, 10, 11);
|
|
|
|
staticMesh[RT_OMNI+1].faces[12].setVerts(8,12,9);
|
|
|
|
staticMesh[RT_OMNI+1].faces[12].setEdgeVisFlags(1,1,1);
|
|
|
|
staticMesh[RT_OMNI+1].faces[13].setVerts(9,12,10);
|
|
|
|
staticMesh[RT_OMNI+1].faces[13].setEdgeVisFlags(1,1,1);
|
|
|
|
staticMesh[RT_OMNI+1].faces[14].setVerts(10,12,11);
|
|
|
|
staticMesh[RT_OMNI+1].faces[14].setEdgeVisFlags(1,1,1);
|
|
|
|
staticMesh[RT_OMNI+1].faces[15].setVerts(11,12,8);
|
|
|
|
staticMesh[RT_OMNI+1].faces[15].setEdgeVisFlags(1,1,1);
|
|
|
|
for (int i=0; i<nfaces; i++)
|
|
|
|
staticMesh[RT_OMNI+1].faces[i].setSmGroup(i);
|
|
|
|
staticMesh[RT_OMNI+1].buildNormals();
|
|
|
|
staticMesh[RT_OMNI+1].EnableEdgeList(1);
|
|
|
|
|
|
|
|
meshBuilt = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::BuildSpotMesh(float coneSize)
|
|
|
|
{
|
|
|
|
// build a cone
|
|
|
|
if(coneSize < 0.0f)
|
|
|
|
return;
|
|
|
|
int nverts = 9;
|
|
|
|
int nfaces = 8;
|
|
|
|
spotMesh.setNumVerts(nverts);
|
|
|
|
spotMesh.setNumFaces(nfaces);
|
|
|
|
double radang = 3.1415926 * coneSize / 360.0;
|
|
|
|
float h = 20.0f; // hypotenuse
|
|
|
|
float d = -h * (float)cos(radang); // dist from origin to cone circle
|
|
|
|
float r = h * (float)sin(radang); // radius of cone circle
|
|
|
|
float s = 0.70711f * r; // sin(45) * r
|
|
|
|
spotMesh.setVert(0, Point3( FZ, FZ, FZ));
|
|
|
|
spotMesh.setVert(1, Point3( -r, FZ, d));
|
|
|
|
spotMesh.setVert(2, Point3( -s, -s, d));
|
|
|
|
spotMesh.setVert(3, Point3( FZ, -r, d));
|
|
|
|
spotMesh.setVert(4, Point3( s, -s, d));
|
|
|
|
spotMesh.setVert(5, Point3( r, FZ, d));
|
|
|
|
spotMesh.setVert(6, Point3( s, s, d));
|
|
|
|
spotMesh.setVert(7, Point3( FZ, r, d));
|
|
|
|
spotMesh.setVert(8, Point3( -s, s, d));
|
|
|
|
spotMesh.faces[0].setVerts(0,1,2);
|
|
|
|
spotMesh.faces[1].setVerts(0,2,3);
|
|
|
|
spotMesh.faces[2].setVerts(0,3,4);
|
|
|
|
spotMesh.faces[3].setVerts(0,4,5);
|
|
|
|
spotMesh.faces[4].setVerts(0,5,6);
|
|
|
|
spotMesh.faces[5].setVerts(0,6,7);
|
|
|
|
spotMesh.faces[6].setVerts(0,7,8);
|
|
|
|
spotMesh.faces[7].setVerts(0,8,1);
|
|
|
|
for (int i=0; i<nfaces; i++) {
|
|
|
|
spotMesh.faces[i].setSmGroup(i);
|
|
|
|
spotMesh.faces[i].setEdgeVisFlags(1,1,1);
|
|
|
|
}
|
|
|
|
spotMesh.buildNormals();
|
|
|
|
spotMesh.EnableEdgeList(1);
|
|
|
|
//fMesh = spotMesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
plRTLightBase::~plRTLightBase()
|
|
|
|
{
|
|
|
|
DeleteAllRefsFromMe();
|
|
|
|
fLightPB = NULL;
|
|
|
|
if( fTex )
|
|
|
|
delete fTex;
|
|
|
|
}
|
|
|
|
|
|
|
|
IParamBlock2* plRTLightBase::GetParamBlock2()
|
|
|
|
{
|
|
|
|
return fLightPB;
|
|
|
|
}
|
|
|
|
|
|
|
|
IParamBlock2* plRTLightBase::GetParamBlockByID( short id )
|
|
|
|
{
|
|
|
|
if( id == fLightPB->ID() )
|
|
|
|
return fLightPB;
|
|
|
|
else
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
IParamBlock2 *plRTLightBase::GetParamBlock( int i )
|
|
|
|
{
|
|
|
|
switch( i )
|
|
|
|
{
|
|
|
|
case 0: return fLightPB;
|
|
|
|
default: return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// So our animatables will show up in the trackview
|
|
|
|
int plRTLightBase::NumSubs()
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
Animatable *plRTLightBase::SubAnim(int i)
|
|
|
|
{
|
|
|
|
return (Animatable *)fLightPB;
|
|
|
|
|
|
|
|
switch(i)
|
|
|
|
{
|
|
|
|
/* kRefProjMap,
|
|
|
|
kRefShadowProjMap,
|
|
|
|
kRefShadowType,
|
|
|
|
kRefOmniLight,
|
|
|
|
kRefSpotLight,
|
|
|
|
kRefTSpotLight,
|
|
|
|
kRefDirLight,
|
|
|
|
kRefTDirLight
|
|
|
|
*/
|
|
|
|
case kRefOmniLight:
|
|
|
|
case kRefSpotLight:
|
|
|
|
case kRefTSpotLight:
|
|
|
|
case kRefDirLight:
|
|
|
|
case kRefTDirLight:
|
|
|
|
case kRefProjDirLight:
|
|
|
|
return (Animatable*)fLightPB;
|
|
|
|
case kRefProjMap:
|
|
|
|
Texmap* MyMap;
|
|
|
|
return (Animatable*) fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER);
|
|
|
|
case kRefShadowType:
|
|
|
|
return NULL;
|
|
|
|
default: return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//return (Animatable*) fLightPB;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSTR plRTLightBase::SubAnimName(int i)
|
|
|
|
{
|
|
|
|
return fLightPB->GetLocalName();
|
|
|
|
switch(i)
|
|
|
|
{
|
|
|
|
|
|
|
|
case kRefOmniLight:return _T("");
|
|
|
|
case kRefSpotLight: return TSTR(GetString(IDS_DB_FSPOT));
|
|
|
|
case kRefTSpotLight:return _T("");
|
|
|
|
case kRefDirLight:return _T("");
|
|
|
|
case kRefTDirLight:return _T("");
|
|
|
|
case kRefProjMap: return TSTR(GetString(IDS_DS_PROJMAP));
|
|
|
|
case kRefShadowType: return _T("");
|
|
|
|
default: return _T("");
|
|
|
|
|
|
|
|
/* case PBLOCK_REF: return TSTR(GetString(IDS_RB_PARAMETERS));
|
|
|
|
case PROJMAP_REF: return TSTR(GetString(IDS_DS_PROJMAP));
|
|
|
|
case SHADPROJMAP_REF: return TSTR(GetString(IDS_DS_SHADPROJMAP));
|
|
|
|
case SHADTYPE_REF: return TSTR(GetString(IDS_DS_SHAD_GEN));
|
|
|
|
case EMITTER_REF:
|
|
|
|
if ( IsCompatibleRenderer ())
|
|
|
|
return TSTR(GetString(IDS_EMITTER));
|
|
|
|
else
|
|
|
|
return _T("");
|
|
|
|
default: return _T("");
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
RefTargetHandle plRTSpotLight::Clone(RemapDir &remap)
|
|
|
|
{
|
|
|
|
plRTLightBase *obj = new plRTSpotLight;
|
|
|
|
|
|
|
|
obj->GetParamBlock2->SetValue(kLightOn, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
// obj->fLightPB->SetValue(kLightType, t, fLightPB->GetInt(kLightType, t));
|
|
|
|
obj->fLightPB->SetValue(kLightColor, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kCastShadows, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
//obj->fLightPB->SetValue(kContrast, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
//obj->fLightPB->SetValue(kDiffSoft, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
//obj->fLightPB->SetValue(kDiffOn, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kSpec, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kSpecularColorSwatch, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kIntensity, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
|
|
|
|
if( IHasAttenuation() )
|
|
|
|
{
|
|
|
|
obj->fLightPB->SetValue(kUseAttenuationBool, t, fLightPB->GetInt(kLightType, t));
|
|
|
|
obj->fLightPB->SetValue(kAttenMaxFalloffEdit, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kAttenTypeRadio, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kShowConeBool, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kHotSpot, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kAttenMaxFalloffEdit, fLightPB->GetInt(kLightType, t));
|
|
|
|
obj->fLightPB->SetValue(kFallOff, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
|
|
|
|
obj->fLightPB->SetValue(kUseProjectorBool, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
obj->fLightPB->SetValue(kProjMapTexButton, t, fLightPB->GetInt(kLightOn, t));
|
|
|
|
}
|
|
|
|
obj->ReplaceReference(kRefSpotLight,fLightPB->Clone(remap));
|
|
|
|
/*
|
|
|
|
GeneralLight* newob = new GeneralLight(type);
|
|
|
|
newob->enable = enable;
|
|
|
|
newob->coneDisplay = coneDisplay;
|
|
|
|
newob->useLight = useLight;
|
|
|
|
newob->attenDisplay = attenDisplay;
|
|
|
|
newob->useAtten = useAtten;
|
|
|
|
newob->useAttenNear = useAttenNear;
|
|
|
|
newob->attenNearDisplay = attenNearDisplay;
|
|
|
|
newob->decayDisplay = decayDisplay;
|
|
|
|
newob->shape = shape;
|
|
|
|
newob->shadow = shadow;
|
|
|
|
newob->shadowType = shadowType;
|
|
|
|
newob->overshoot = overshoot;
|
|
|
|
newob->projector = projector;
|
|
|
|
newob->absMapBias = absMapBias;
|
|
|
|
newob->exclList = exclList;
|
|
|
|
newob->softenDiffuse = softenDiffuse;
|
|
|
|
newob->affectDiffuse = affectDiffuse;
|
|
|
|
newob->affectSpecular = affectSpecular;
|
|
|
|
newob->ambientOnly = ambientOnly;
|
|
|
|
newob->decayType = decayType;
|
|
|
|
newob->atmosShadows = atmosShadows;
|
|
|
|
newob->atmosOpacity = atmosOpacity;
|
|
|
|
newob->atmosColAmt = atmosColAmt;
|
|
|
|
newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap));
|
|
|
|
if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap));
|
|
|
|
if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap));
|
|
|
|
if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap));
|
|
|
|
if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap));
|
|
|
|
BaseClone(this, newob, remap);
|
|
|
|
return(newob);
|
|
|
|
*/
|
|
|
|
|
|
|
|
//plRTLightBase *obj = (plRTLightBase*) fClassDesc->Create(false);
|
|
|
|
//obj->ReplaceReference(kRefComp, fLightPB->Clone(remap));
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::FreeCaches()
|
|
|
|
{
|
|
|
|
// fMesh.FreeAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::BoxCircle(TimeValue t, float r, float d, Box3& box, int extraPt, Matrix3 *tm)
|
|
|
|
{
|
|
|
|
Point3 q[3*NUM_CIRC_PTS];
|
|
|
|
int npts;
|
|
|
|
float asp;
|
|
|
|
if ( 1 /*Circle Object*/) { npts = NUM_CIRC_PTS+extraPt; asp = -1.0f; }
|
|
|
|
else { npts = 4+extraPt; asp = -1.0; }
|
|
|
|
GetConePoints(t, asp , r, d, q);
|
|
|
|
box.IncludePoints(q,npts,tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::BoxDirPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm)
|
|
|
|
{
|
|
|
|
int npts;
|
|
|
|
Point3 q[3*NUM_CIRC_PTS];
|
|
|
|
npts = 1 /*Circle Object*/? GetCirXPoints(t,angle,dist,q): GetRectXPoints(t,angle,dist,q);
|
|
|
|
box.IncludePoints(q,npts,tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::BoxPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm)
|
|
|
|
{
|
|
|
|
if (IsDir())
|
|
|
|
BoxCircle(t, angle, dist, box, 0,tm);
|
|
|
|
else
|
|
|
|
BoxDirPoints(t, angle, dist, box, tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::BoxLight(TimeValue t, INode *inode, Box3& box, Matrix3 *tm)
|
|
|
|
{
|
|
|
|
Point3 pt;
|
|
|
|
float d;
|
|
|
|
if (GetTargetPoint(t, inode, pt))
|
|
|
|
{
|
|
|
|
Point3 loc = inode->GetObjectTM(t).GetTrans();
|
|
|
|
d = FLength(loc - pt) / FLength(inode->GetObjectTM(t).GetRow(2));
|
|
|
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
d = GetTDist(t);
|
|
|
|
// if(fLightPB->GetInt(kLightType) == RT_FREE_DIR)
|
|
|
|
// d = GetFallsize(t);
|
|
|
|
if(IsSpot())
|
|
|
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d);
|
|
|
|
if(IsDir())
|
|
|
|
{
|
|
|
|
d = GetFallsize(t);
|
|
|
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
// if (fLightPB->GetInt(kLightType) == RT_FREE_SPOT || fLightPB->GetInt(kLightType) == RT_TARGET_SPOT)
|
|
|
|
if((fLightPB->GetInt(kShowConeBool,t)) || (extDispFlags & EXT_DISP_ONLY_SELECTED))
|
|
|
|
{
|
|
|
|
float rad = MaxF(GetHotspot(t), GetFallsize(t));
|
|
|
|
if (IsDir())
|
|
|
|
BoxCircle(t,rad,0.0f,box,1,tm);
|
|
|
|
BoxCircle(t,rad,d,box,1,tm);
|
|
|
|
}
|
|
|
|
if( this->ClassID() == RTDIR_LIGHT_CLASSID
|
|
|
|
|| this->ClassID() == RTPDIR_LIGHT_CLASSID )
|
|
|
|
// if (fLightPB->GetInt(kLightType) == RT_FREE_DIR || fLightPB->GetInt(kLightType) == RT_TARGET_DIR)
|
|
|
|
if((extDispFlags & EXT_DISP_ONLY_SELECTED))
|
|
|
|
{
|
|
|
|
float rad = MaxF(GetHotspot(t), GetFallsize(t));
|
|
|
|
if (IsDir())
|
|
|
|
BoxCircle(t,rad,0.0f,box,1,tm);
|
|
|
|
BoxCircle(t,rad,2.82841*GetFallsize(t),box,1,tm); //hack, hack. Do 2root2 at corners...
|
|
|
|
}
|
|
|
|
BOOL dispAtten = false;
|
|
|
|
BOOL dispAttenNear = false;
|
|
|
|
BOOL dispDecay = false;
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
dispAtten = fLightPB->GetInt(kUseAttenuationBool,t);
|
|
|
|
dispAttenNear = 0; //attenNearDisplay;
|
|
|
|
|
|
|
|
dispDecay = (GetDecayType()&&(extDispFlags & EXT_DISP_ONLY_SELECTED));
|
|
|
|
}
|
|
|
|
if( dispAtten || dispDecay)
|
|
|
|
{
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
Point3 q[3*NUM_CIRC_PTS];
|
|
|
|
float rad = 0;
|
|
|
|
if (dispAtten)
|
|
|
|
rad = MaxF(GetAtten(t, ATTEN_START), GetAtten(t, ATTEN_END));
|
|
|
|
if (dispDecay) rad = MaxF(rad,0.0/*GetDecayRadius(t)*/);
|
|
|
|
GetAttenPoints(t, rad, q);
|
|
|
|
box.IncludePoints(q,3*NUM_CIRC_PTS,tm);
|
|
|
|
}
|
|
|
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
if (dispAtten)
|
|
|
|
{
|
|
|
|
BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_END), box, tm);
|
|
|
|
BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_START), box, tm);
|
|
|
|
}
|
|
|
|
if (dispDecay)
|
|
|
|
BoxPoints(t, GetFallsize(t), 0.0/*GetDecayRadius(t)*/, box, tm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int plRTLightBase::GetRectXPoints(TimeValue t, float angle, float dist, Point3 *q)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if(dist==0.0f) dist = .00001f;
|
|
|
|
float ang = DegToRad(angle)/2.0f;
|
|
|
|
float da,sn,cs,x,y,z,a;
|
|
|
|
float aspect = GetAspect(t);
|
|
|
|
float w = dist * (float)tan(ang) * (float)sqrt((double)aspect);
|
|
|
|
float h = w/aspect;
|
|
|
|
float wang = (float)atan(w/dist);
|
|
|
|
float hang = (float)atan(h/dist);
|
|
|
|
float aw = float(atan(w/dist)*cos(hang)); // half-angle of top and bottom arcs
|
|
|
|
float ah = float(atan(h/dist)*cos(wang)); // half-angle of left and right arcs
|
|
|
|
int j = 0;
|
|
|
|
|
|
|
|
// draw horizontal and vertical center lines
|
|
|
|
da = wang/float(NUM_HALF_ARC);
|
|
|
|
for(i = -NUM_HALF_ARC, a = -wang; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a));
|
|
|
|
da = hang/float(NUM_HALF_ARC);
|
|
|
|
for(i = -NUM_HALF_ARC, a = -hang; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a));
|
|
|
|
|
|
|
|
|
|
|
|
// draw top and bottom arcs
|
|
|
|
da = aw/float(NUM_HALF_ARC);
|
|
|
|
sn = (float)sin(hang);
|
|
|
|
cs = (float)cos(hang);
|
|
|
|
for (i = -NUM_HALF_ARC, a = -aw; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
{
|
|
|
|
x = dist*(float)sin(a);
|
|
|
|
z = -dist*(float)cos(a);
|
|
|
|
q[j] = Point3(x, z*sn, z*cs);
|
|
|
|
q[j+NUM_ARC_PTS] = Point3(x,-z*sn, z*cs);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
j+= NUM_ARC_PTS;
|
|
|
|
|
|
|
|
// draw left and right arcs
|
|
|
|
da = ah/float(NUM_HALF_ARC);
|
|
|
|
sn = (float)sin(wang);
|
|
|
|
cs = (float)cos(wang);
|
|
|
|
for (i = -NUM_HALF_ARC, a = -ah; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
{
|
|
|
|
y = dist*(float)sin(a);
|
|
|
|
z = -dist*(float)cos(a);
|
|
|
|
q[j] = Point3( z*sn, y, z*cs);
|
|
|
|
q[j+NUM_ARC_PTS] = Point3(-z*sn, y, z*cs);
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 6*NUM_ARC_PTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int plRTLightBase::GetCirXPoints(TimeValue t, float angle, float dist, Point3 *q)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float ang = DegToRad(angle)/2.0f;
|
|
|
|
float da = ang/float(NUM_HALF_ARC);
|
|
|
|
// first draw circle:
|
|
|
|
float d = dist*(float)cos(ang);
|
|
|
|
GetConePoints(t, -1.0f, angle, d, q);
|
|
|
|
int j=NUM_CIRC_PTS;
|
|
|
|
// then draw Arc X
|
|
|
|
float a = -ang;
|
|
|
|
for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a));
|
|
|
|
a = -ang;
|
|
|
|
for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da)
|
|
|
|
q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a));
|
|
|
|
return NUM_CIRC_PTS + 2*NUM_ARC_PTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::DrawX(TimeValue t, float asp, int npts, float dist, GraphicsWindow *gw, int indx)
|
|
|
|
{
|
|
|
|
Point3 q[3*NUM_CIRC_PTS+1];
|
|
|
|
Point3 u[2];
|
|
|
|
GetConePoints(t, asp, GetFallsize(t), dist, q);
|
|
|
|
gw->polyline(npts, q,NULL, NULL, TRUE, NULL);
|
|
|
|
u[0] = q[0]; u[1] = q[2*indx];
|
|
|
|
gw->polyline(2, u,NULL, NULL, FALSE, NULL);
|
|
|
|
u[0] = q[indx]; u[1] = q[3*indx];
|
|
|
|
gw->polyline(2, u,NULL, NULL, FALSE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::GetAttenPoints(TimeValue t, float rad, Point3 *q)
|
|
|
|
{
|
|
|
|
double a;
|
|
|
|
float sn, cs;
|
|
|
|
for(int i = 0; i < NUM_CIRC_PTS; i++)
|
|
|
|
{
|
|
|
|
a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS;
|
|
|
|
sn = rad * (float)sin(a);
|
|
|
|
cs = rad * (float)cos(a);
|
|
|
|
q[i+0*NUM_CIRC_PTS] = Point3(sn, cs, 0.0f);
|
|
|
|
q[i+1*NUM_CIRC_PTS] = Point3(sn, 0.0f, cs);
|
|
|
|
q[i+2*NUM_CIRC_PTS] = Point3(0.0f, sn, cs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Draw warped rectangle
|
|
|
|
void plRTLightBase::DrawWarpRect(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q)
|
|
|
|
{
|
|
|
|
GetRectXPoints(t, angle,dist,q);
|
|
|
|
for (int i=0; i<6; i++)
|
|
|
|
gw->polyline(NUM_ARC_PTS, q+i*NUM_ARC_PTS,NULL, NULL, FALSE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::DrawCircleX(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q)
|
|
|
|
{
|
|
|
|
GetCirXPoints(t, angle,dist,q);
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q,NULL, NULL, TRUE, NULL); // circle
|
|
|
|
gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS,NULL, NULL, FALSE, NULL); // vert arc
|
|
|
|
gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS+NUM_ARC_PTS,NULL, NULL, FALSE, NULL); // horiz arc
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::DrawSphereArcs(TimeValue t, GraphicsWindow *gw, float r, Point3 *q)
|
|
|
|
{
|
|
|
|
GetAttenPoints(t, r, q);
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL);
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q+NUM_CIRC_PTS, NULL, NULL, TRUE, NULL);
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q+2*NUM_CIRC_PTS,NULL, NULL, TRUE, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
void plRTLightBase::DrawAttenCirOrRect(TimeValue t, GraphicsWindow *gw, float dist, BOOL froze, int uicol)
|
|
|
|
{
|
|
|
|
if (!froze) gw->setColor( LINE_COLOR, GetUIColor(uicol));
|
|
|
|
if (IsDir())
|
|
|
|
{
|
|
|
|
int npts,indx;
|
|
|
|
float asp;
|
|
|
|
npts = NUM_CIRC_PTS; asp = -1.0f; indx = SEG_INDEX;
|
|
|
|
DrawX(t, asp, npts, dist, gw, indx);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Point3 q[3*NUM_CIRC_PTS+1];
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID )
|
|
|
|
DrawSphereArcs(t, gw, dist, q);
|
|
|
|
else
|
|
|
|
DrawCircleX(t, gw, GetFallsize(t),dist,q);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int plRTLightBase::DrawAtten(TimeValue t, INode *inode, GraphicsWindow *gw)
|
|
|
|
{
|
|
|
|
BOOL dispAtten = false;
|
|
|
|
BOOL dispDecay = false;
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
dispAtten = (fLightPB->GetInt(kUseAttenuationBool,t) && (extDispFlags & EXT_DISP_ONLY_SELECTED));
|
|
|
|
//BOOL dispAttenNear = (fLightPB->GetInt(kUseNearAtten) && (extDispFlags & EXT_DISP_ONLY_SELECTED))?TRUE:fLightPB->GetInt(kShowFarAttenRanges);
|
|
|
|
dispDecay = (GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED));
|
|
|
|
}
|
|
|
|
if (dispAtten || dispDecay)
|
|
|
|
{
|
|
|
|
Matrix3 tm = inode->GetObjectTM(t);
|
|
|
|
gw->setTransform(tm);
|
|
|
|
BOOL froze = inode->IsFrozen() && !inode->Dependent();
|
|
|
|
if (dispAtten)
|
|
|
|
{
|
|
|
|
DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_START), froze, COLOR_START_RANGE);
|
|
|
|
DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_END), froze, COLOR_END_RANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dispDecay)
|
|
|
|
{
|
|
|
|
DrawAttenCirOrRect(t, gw, 0.0 /*DecayRadius() Stuff here */, froze, COLOR_DECAY_RADIUS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
|
|
|
|
{
|
|
|
|
//BuildMeshes(t);
|
|
|
|
//box = fMesh.getBoundingBox();
|
|
|
|
// int nv;
|
|
|
|
// Matrix3 tm;
|
|
|
|
// GetMat(t, node,vpt,tm);
|
|
|
|
// Point3 loc = tm.GetTrans();
|
|
|
|
// nv = fMesh.getNumVerts();
|
|
|
|
// box.Init();
|
|
|
|
// if(!(extDispFlags & EXT_DISP_ZOOM_EXT))
|
|
|
|
// box.IncludePoints(fMesh.verts,nv,&tm);
|
|
|
|
// else
|
|
|
|
// box += loc;
|
|
|
|
// tm = node->GetObjectTM(t);
|
|
|
|
// BoxLight(t, node, box, &tm);
|
|
|
|
Point3 loc = node->GetObjectTM(t).GetTrans();
|
|
|
|
float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(loc) / 360.0f;
|
|
|
|
box = fMesh.getBoundingBox();
|
|
|
|
box.Scale(scaleFactor);
|
|
|
|
BoxLight(t, node, box, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
RefTargetHandle Clone(RemapDir &remap = NoRemap())
|
|
|
|
{
|
|
|
|
|
|
|
|
plRTLightBase* newOb = new plRTLightBase;
|
|
|
|
newOb->fLightPB->SetValue(kLightOn, 0, this->fLightPB->GetInt(kLightOn, 0));
|
|
|
|
newOb->fLightPB->SetValue(kLightColor, 0, this->fLightPB->GetValue(kLightColor, 0));
|
|
|
|
newOb->fLightPB->SetValue(kLightExclude, 0, this->fLightPB->GetValue(kLightExclude, 0));
|
|
|
|
newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0));
|
|
|
|
newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0));
|
|
|
|
newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0));
|
|
|
|
newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0));
|
|
|
|
newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0));
|
|
|
|
newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0));
|
|
|
|
newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0));
|
|
|
|
newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0));
|
|
|
|
newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0));
|
|
|
|
newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0));
|
|
|
|
newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0));
|
|
|
|
newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0));
|
|
|
|
newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0));
|
|
|
|
newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0));
|
|
|
|
newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0));
|
|
|
|
newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0));
|
|
|
|
newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0));
|
|
|
|
|
|
|
|
newOb->fLightPB->SetValue(kUseFarAtten, 0, this->fLightPB->GetInt(kUseFarAtten, 0));
|
|
|
|
newOb->fLightPB->SetValue(kShowFarAttenRanges, 0, this->fLightPB->GetInt(kShowFarAttenRanges, 0));
|
|
|
|
newOb->fLightPB->SetValue(kLightDecay, 0, this->fLightPB->GetInt(kLightDecay, 0));
|
|
|
|
newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0));
|
|
|
|
newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0));
|
|
|
|
newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0));
|
|
|
|
newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0));
|
|
|
|
newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0));
|
|
|
|
newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0));
|
|
|
|
newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0));
|
|
|
|
newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0));
|
|
|
|
newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0));
|
|
|
|
newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0));
|
|
|
|
newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0));
|
|
|
|
newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0));
|
|
|
|
newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0));
|
|
|
|
newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0));
|
|
|
|
newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0));
|
|
|
|
newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0));
|
|
|
|
newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0));
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
|
|
kLightType, //Inserted in v1
|
|
|
|
kLightOn, //Inserted in v1
|
|
|
|
kLightColor, //Inserted in v1
|
|
|
|
kLightExclude, //Inserted in v1
|
|
|
|
kRed, //Inserted in v1
|
|
|
|
kGreen, //Inserted in v1
|
|
|
|
kBlue, //Inserted in v1
|
|
|
|
kHue, //Inserted in v1
|
|
|
|
kSat, //Inserted in v1
|
|
|
|
kVal, //Inserted in v1
|
|
|
|
kIntensity, //Inserted in v1
|
|
|
|
kContrast, //Inserted in v1
|
|
|
|
kDiffSoft, //Inserted in v1
|
|
|
|
kDiffOn, //Inserted in v1
|
|
|
|
kSpec, //Inserted in v1
|
|
|
|
kAmbiOnly, //Inserted in v1
|
|
|
|
kStartAttenNear, //Inserted in v1
|
|
|
|
kEndAttenNear, //Inserted in v1
|
|
|
|
kUseNearAtten, //Inserted in v1
|
|
|
|
kShowNearAttenRanges,//Inserted in v1
|
|
|
|
kStartAttenFar, //Inserted in v1
|
|
|
|
kEndAttenFar, //Inserted in v1
|
|
|
|
kUseFarAtten, //Inserted in v1
|
|
|
|
kShowFarAttenRanges, //Inserted in v1
|
|
|
|
kLightDecay, //Inserted in v1
|
|
|
|
kDecayEdit, //Inserted in v1
|
|
|
|
kShowDecay, //Inserted in v1
|
|
|
|
kUseProjectBool, //Inserted in v1
|
|
|
|
kProjMapTexButton, //Inserted in v1
|
|
|
|
kShowConeBool, //Inserted in v1
|
|
|
|
kOvershootBool, //Inserted in v1
|
|
|
|
kHotSpot, //Inserted in v1
|
|
|
|
kFallOff, //Inserted in v1
|
|
|
|
kLightShapeRadio, //Inserted in v1
|
|
|
|
kAspect, //Inserted in v1
|
|
|
|
kUseProjectorBool, //Inserted in v1
|
|
|
|
kProjMapTexButton2, //Inserted in v1
|
|
|
|
kTargetDist //Inserted in v1
|
|
|
|
GeneralLight* newob = new GeneralLight(type);
|
|
|
|
newob->enable = enable;
|
|
|
|
newob->coneDisplay = coneDisplay;
|
|
|
|
newob->useLight = useLight;
|
|
|
|
newob->attenDisplay = attenDisplay;
|
|
|
|
newob->useAtten = useAtten;
|
|
|
|
newob->useAttenNear = useAttenNear;
|
|
|
|
newob->attenNearDisplay = attenNearDisplay;
|
|
|
|
newob->decayDisplay = decayDisplay;
|
|
|
|
newob->shape = shape;
|
|
|
|
newob->shadow = shadow;
|
|
|
|
newob->shadowType = shadowType;
|
|
|
|
newob->overshoot = overshoot;
|
|
|
|
newob->projector = projector;
|
|
|
|
newob->absMapBias = absMapBias;
|
|
|
|
newob->exclList = exclList;
|
|
|
|
newob->softenDiffuse = softenDiffuse;
|
|
|
|
newob->affectDiffuse = affectDiffuse;
|
|
|
|
newob->affectSpecular = affectSpecular;
|
|
|
|
newob->ambientOnly = ambientOnly;
|
|
|
|
newob->decayType = decayType;
|
|
|
|
newob->atmosShadows = atmosShadows;
|
|
|
|
newob->atmosOpacity = atmosOpacity;
|
|
|
|
newob->atmosColAmt = atmosColAmt;
|
|
|
|
newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap));
|
|
|
|
if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap));
|
|
|
|
if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap));
|
|
|
|
if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap));
|
|
|
|
if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap));
|
|
|
|
BaseClone(this, newob, remap);
|
|
|
|
return(newob);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box)
|
|
|
|
{
|
|
|
|
GetLocalBoundBox( t, node, vpt, box );
|
|
|
|
box = box * node->GetObjectTM( t );
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel )
|
|
|
|
{
|
|
|
|
box = fMesh.getBoundingBox(tm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int plRTLightBase::Display(TimeValue t, INode *node, ViewExp *vpt, int flags)
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
Matrix3 m;
|
|
|
|
// if (!enable)
|
|
|
|
// return 0;
|
|
|
|
GraphicsWindow *gw = vpt->getGW();
|
|
|
|
GetMat(t,node,vpt,m);
|
|
|
|
gw->setTransform(m);
|
|
|
|
DWORD rlim = gw->getRndLimits();
|
|
|
|
gw->setRndLimits(GW_WIREFRAME|GW_BACKCULL|(gw->getRndMode() & GW_Z_BUFFER));
|
|
|
|
if (node->Selected())
|
|
|
|
gw->setColor( LINE_COLOR, GetSelColor());
|
|
|
|
else if(!node->IsFrozen() && !node->Dependent())
|
|
|
|
{
|
|
|
|
if(fLightPB->GetInt(kLightOn))
|
|
|
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_LIGHT_OBJ));
|
|
|
|
// I un-commented this line DS 6/11/99
|
|
|
|
else
|
|
|
|
gw->setColor( LINE_COLOR, 0.0f, 0.0f, 0.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
fMesh.render( gw, gw->getMaterial(),
|
|
|
|
(flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL, COMP_ALL);
|
|
|
|
|
|
|
|
DrawConeAndLine(t, node, gw, 1);
|
|
|
|
// DrawAtten(t, node, gw);
|
|
|
|
gw->setRndLimits(rlim);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void RemoveScaling(Matrix3 &tm)
|
|
|
|
{
|
|
|
|
AffineParts ap;
|
|
|
|
decomp_affine(tm, &ap);
|
|
|
|
tm.IdentityMatrix();
|
|
|
|
tm.SetRotate(ap.q);
|
|
|
|
tm.SetTrans(ap.t);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::GetMat(TimeValue t, INode* inode, ViewExp *vpt, Matrix3& tm)
|
|
|
|
{
|
|
|
|
tm = inode->GetObjectTM(t);
|
|
|
|
// tm.NoScale();
|
|
|
|
RemoveScaling(tm);
|
|
|
|
float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/(float)360.0;
|
|
|
|
tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::GetConePoints(TimeValue t, float aspect, float angle, float dist, Point3 *q)
|
|
|
|
{
|
|
|
|
float ta = (float)tan(0.5*DegToRad(angle));
|
|
|
|
if(1 /*fLightPB->GetFloat(kAspect, t) <= 0.0f*/)
|
|
|
|
{
|
|
|
|
// CIRCULAR
|
|
|
|
float rad = dist * ta;
|
|
|
|
double a;
|
|
|
|
if(IsDir())
|
|
|
|
rad = angle;
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < NUM_CIRC_PTS; i++) {
|
|
|
|
a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS;
|
|
|
|
q[i] = Point3(rad*(float)sin(a), rad*(float)cos(a), -dist);
|
|
|
|
}
|
|
|
|
q[i] = q[0] + Point3(0.0f, 15.0f, 0.0f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// RECTANGULAR
|
|
|
|
float w = IsDir()? angle : dist * ta * (float)sqrt((double)aspect);
|
|
|
|
float h = w / aspect;
|
|
|
|
q[0] = Point3( w, h,-dist);
|
|
|
|
q[1] = Point3(-w, h,-dist);
|
|
|
|
q[2] = Point3(-w,-h,-dist);
|
|
|
|
q[3] = Point3( w,-h,-dist);
|
|
|
|
q[4] = Point3( 0.0f, h+15.0f, -dist);
|
|
|
|
q[5] = Point3( 0.0f, h, -dist);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define HOTCONE 0
|
|
|
|
#define FALLCONE 1
|
|
|
|
|
|
|
|
void plRTLightBase::DrawCone(TimeValue t, GraphicsWindow *gw, float dist)
|
|
|
|
{
|
|
|
|
Point3 q[NUM_CIRC_PTS+1], u[3];
|
|
|
|
int dirLight = IsDir();
|
|
|
|
int i;
|
|
|
|
BOOL dispAtten = false;
|
|
|
|
BOOL dispDecay = false;
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
dispAtten = (fLightPB->GetInt(kUseAttenuationBool, t) && (extDispFlags & EXT_DISP_ONLY_SELECTED));//attenDisplay;
|
|
|
|
dispDecay = (/*fLightPB->GetInt(kAttenTypeRadio, t)*/GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED));
|
|
|
|
}
|
|
|
|
if(!IsDir())
|
|
|
|
GetConePoints(t, -1.0f, GetHotspot(t), dist, q);
|
|
|
|
else
|
|
|
|
GetConePoints(t, -1.0f, 20.0, dist, q);
|
|
|
|
|
|
|
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_HOTSPOT));
|
|
|
|
if(1 /*Circular Hack*/) {
|
|
|
|
// CIRCULAR
|
|
|
|
if(GetHotspot(t) >= GetFallsize(t))
|
|
|
|
{
|
|
|
|
// draw (far) hotspot circle
|
|
|
|
u[0] = q[0];
|
|
|
|
u[1] = q[NUM_CIRC_PTS];
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL);
|
|
|
|
}
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL);
|
|
|
|
if (dirLight)
|
|
|
|
{
|
|
|
|
// draw 4 axial hotspot lines
|
|
|
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX)
|
|
|
|
{
|
|
|
|
u[0] = q[i]; u[1] = q[i]; u[1].z += dist;
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL );
|
|
|
|
}
|
|
|
|
GetConePoints(t, -1.0f, 20/*GetHotspot(t)*/, 0.0f, q);
|
|
|
|
// draw (near) hotspot circle
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// draw 4 axial lines
|
|
|
|
u[0] = Point3(0,0,0);
|
|
|
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX)
|
|
|
|
{
|
|
|
|
u[1] = q[i];
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!IsDir())
|
|
|
|
GetConePoints(t, -1.0f, GetFallsize(t), dist, q);
|
|
|
|
else
|
|
|
|
GetConePoints(t, -1.0f, 200.0, dist, q);
|
|
|
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_FALLOFF));
|
|
|
|
if(GetHotspot(t) < GetFallsize(t))
|
|
|
|
{
|
|
|
|
// draw (far) fallsize circle
|
|
|
|
u[0] = q[0]; u[1] = q[NUM_CIRC_PTS];
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL);
|
|
|
|
u[0] = Point3(0,0,0);
|
|
|
|
}
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL);
|
|
|
|
if (dirLight)
|
|
|
|
{
|
|
|
|
float dfar = q[0].z;
|
|
|
|
float dnear = 0.0f;
|
|
|
|
if (dispAtten)
|
|
|
|
{
|
|
|
|
dfar = MinF(-GetAtten(t,ATTEN_END),dfar);
|
|
|
|
/// dnear = MaxF(-GetAtten(t,ATTEN_START),dnear);
|
|
|
|
}
|
|
|
|
if (dispDecay) {
|
|
|
|
dfar = MinF(/*-GetDecayRadius(t)*/ 0.0,dfar);
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw axial fallsize lines
|
|
|
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX)
|
|
|
|
{
|
|
|
|
u[0] = q[i]; u[0].z = dfar; u[1] = q[i]; u[1].z = dnear;
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
GetConePoints(t, -1.0f, 10000.0, 0.0f, q);
|
|
|
|
// draw (near) fallsize circle
|
|
|
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float cs = (float)cos(DegToRad(GetFallsize(t)*0.5f));
|
|
|
|
float dfar = q[0].z;
|
|
|
|
if (dispAtten)
|
|
|
|
dfar = MinF(-cs*GetAtten(t,ATTEN_END),dfar);
|
|
|
|
if (dispDecay)
|
|
|
|
dfar = MinF(/*-cs*GetDecayRadius(t)*/0.0,dfar);
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX)
|
|
|
|
{
|
|
|
|
u[1] = -q[i]*dfar/dist;
|
|
|
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int plRTLightBase::DrawConeAndLine(TimeValue t, INode* inode, GraphicsWindow *gw, int drawing )
|
|
|
|
{
|
|
|
|
if(!IsSpot() && !IsDir())
|
|
|
|
return 0;
|
|
|
|
Matrix3 tm = inode->GetObjectTM(t);
|
|
|
|
gw->setTransform(tm);
|
|
|
|
gw->clearHitCode();
|
|
|
|
if( 0 )
|
|
|
|
{
|
|
|
|
Point3 pt,v[3];
|
|
|
|
if (GetTargetPoint(t, inode, pt))
|
|
|
|
{
|
|
|
|
float den = FLength(tm.GetRow(2));
|
|
|
|
float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f;
|
|
|
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist);
|
|
|
|
|
|
|
|
//fLightPB->SetValue(kTargetDist, t, dist);
|
|
|
|
//if (hSpotLight&&(currentEditLight==this)) {
|
|
|
|
// TCHAR buf[40];
|
|
|
|
// _stprintf(buf,_T("%0.3f"),targDist);
|
|
|
|
// SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf);
|
|
|
|
// }
|
|
|
|
|
|
|
|
if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED)))
|
|
|
|
DrawCone(t, gw, dist);
|
|
|
|
if(!inode->IsFrozen() && !inode->Dependent())
|
|
|
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_TARGET_LINE));
|
|
|
|
v[0] = Point3(0,0,0);
|
|
|
|
v[1] = Point3(0.0f, 0.0f, (drawing == -1)? (-0.9f * dist): -dist);
|
|
|
|
gw->polyline( 2, v, NULL, NULL, FALSE, NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else if( this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED)))
|
|
|
|
DrawCone(t, gw, fLightPB->GetFloat( kAttenMaxFalloffEdit, t ) );
|
|
|
|
}
|
|
|
|
else if( this->ClassID() == RTDIR_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
if ((extDispFlags & EXT_DISP_ONLY_SELECTED))
|
|
|
|
DrawCone(t, gw, 500/*GetTDist(t)*/);
|
|
|
|
}
|
|
|
|
return gw->checkHitCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//// DrawArrow ///////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void plRTLightBase::DrawArrow( TimeValue t, GraphicsWindow *gw, Point3 &direction, float dist )
|
|
|
|
{
|
|
|
|
Point3 pts[ 5 ];
|
|
|
|
|
|
|
|
|
|
|
|
pts[ 0 ] = Point3( 0, 0, 0 );
|
|
|
|
pts[ 1 ] = direction * dist;
|
|
|
|
pts[ 3 ] = pts[ 1 ] - direction * 10.f;
|
|
|
|
pts[ 2 ] = pts[ 3 ] + Point3( direction.y, direction.z, direction.x ) * 5.f;
|
|
|
|
|
|
|
|
gw->polyline( 4, pts, nil, nil, true, nil );
|
|
|
|
}
|
|
|
|
|
|
|
|
int plRTLightBase::HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
|
|
|
|
{
|
|
|
|
DWORD savedLimits;
|
|
|
|
GraphicsWindow *gw = vpt->getGW();
|
|
|
|
HitRegion hitRegion;
|
|
|
|
int res;
|
|
|
|
Matrix3 m;
|
|
|
|
MakeHitRegion(hitRegion, type, crossing, 4, p);
|
|
|
|
Material *mtl = gw->getMaterial();
|
|
|
|
|
|
|
|
gw->setRndLimits( ((savedLimits = gw->getRndLimits()) | GW_PICK) & ~(GW_ILLUM|GW_BACKCULL));
|
|
|
|
GetMat(t,node,vpt,m);
|
|
|
|
|
|
|
|
//BuildMeshes(t);
|
|
|
|
gw->setTransform(m);
|
|
|
|
res = fMesh.select( gw, mtl, &hitRegion, flags & HIT_ABORTONHIT);
|
|
|
|
// if not, check the target line, and set the pair flag if it's hit
|
|
|
|
if( !res )
|
|
|
|
{
|
|
|
|
// this special case only works with point selection of targeted lights
|
|
|
|
if((type != HITTYPE_POINT) || !node->GetTarget())
|
|
|
|
return 0;
|
|
|
|
// don't let line be active if only looking at selected stuff and target isn't selected
|
|
|
|
if((flags & HIT_SELONLY) && !node->GetTarget()->Selected() )
|
|
|
|
return 0;
|
|
|
|
gw->clearHitCode();
|
|
|
|
if(res = DrawConeAndLine(t, node, gw, -1))
|
|
|
|
node->SetTargetNodePair(1);
|
|
|
|
}
|
|
|
|
gw->setRndLimits(savedLimits);
|
|
|
|
return res;
|
|
|
|
|
|
|
|
//return fMesh.select(gw,node->Mtls(),&hitRegion,flags & HIT_ABORTONHIT,node->NumMtls());
|
|
|
|
}
|
|
|
|
static void GenericSnap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt)
|
|
|
|
{
|
|
|
|
// Make sure the vertex priority is active and at least as important as the best snap so far
|
|
|
|
if(snap->vertPriority > 0 && snap->vertPriority <= snap->priority)
|
|
|
|
{
|
|
|
|
Matrix3 tm = inode->GetObjectTM(t);
|
|
|
|
GraphicsWindow *gw = vpt->getGW();
|
|
|
|
|
|
|
|
gw->setTransform(tm);
|
|
|
|
|
|
|
|
Point2 fp = Point2((float)p->x, (float)p->y);
|
|
|
|
IPoint3 screen3;
|
|
|
|
Point2 screen2;
|
|
|
|
Point3 vert(0.0f,0.0f,0.0f);
|
|
|
|
|
|
|
|
gw->wTransPoint(&vert,&screen3);
|
|
|
|
|
|
|
|
screen2.x = (float)screen3.x;
|
|
|
|
screen2.y = (float)screen3.y;
|
|
|
|
|
|
|
|
// Are we within the snap radius?
|
|
|
|
int len = (int)Length(screen2 - fp);
|
|
|
|
if(len <= snap->strength)
|
|
|
|
{
|
|
|
|
// Is this priority better than the best so far?
|
|
|
|
if(snap->vertPriority < snap->priority)
|
|
|
|
{
|
|
|
|
snap->priority = snap->vertPriority;
|
|
|
|
snap->bestWorld = vert * tm;
|
|
|
|
snap->bestScreen = screen2;
|
|
|
|
snap->bestDist = len;
|
|
|
|
}
|
|
|
|
// Closer than the best of this priority?
|
|
|
|
else if(len < snap->bestDist)
|
|
|
|
{
|
|
|
|
snap->priority = snap->vertPriority;
|
|
|
|
snap->bestWorld = vert * tm;
|
|
|
|
snap->bestScreen = screen2;
|
|
|
|
snap->bestDist = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt)
|
|
|
|
{
|
|
|
|
GenericSnap(t,inode,snap,p,vpt);
|
|
|
|
}
|
|
|
|
// This generic snap routine is used to snap to the 0,0,0 point of the given node. For lights,
|
|
|
|
// this works to snap all types.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RefTargetHandle plRTLightBase::GetReference(int i)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
kRefProjMap,
|
|
|
|
kRefShadowProjMap,
|
|
|
|
kRefShadowType,
|
|
|
|
*///Texmap* MyMap;
|
|
|
|
switch(i)
|
|
|
|
{
|
|
|
|
case kRefGeneralLightProp:
|
|
|
|
return NULL;
|
|
|
|
case kRefProjMap:
|
|
|
|
//if(fLightPB->GetTexmap(kProjMapTexButton, 0) != NULL)
|
|
|
|
//{
|
|
|
|
// MyMap = fLightPB->GetTexmap(kProjMapTexButton, 0);
|
|
|
|
//return (RefTargetHandle) MyMap;
|
|
|
|
//}else
|
|
|
|
return NULL;
|
|
|
|
case kRefShadowProjMap:
|
|
|
|
return NULL;
|
|
|
|
case kRefShadowType:
|
|
|
|
return NULL;
|
|
|
|
case kRefOmniLight:
|
|
|
|
case kRefSpotLight:
|
|
|
|
case kRefTSpotLight:
|
|
|
|
case kRefDirLight:
|
|
|
|
case kRefTDirLight:
|
|
|
|
case kRefProjDirLight:
|
|
|
|
return (RefTargetHandle)fLightPB;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::SetReference(int ref, RefTargetHandle rtarg)
|
|
|
|
{
|
|
|
|
//Texmap* MyMap;
|
|
|
|
switch(ref)
|
|
|
|
{
|
|
|
|
case kRefGeneralLightProp:
|
|
|
|
return;
|
|
|
|
case kRefProjMap:
|
|
|
|
|
|
|
|
//MyMap = (Texmap *)rtarg;
|
|
|
|
//fLightPB->SetValue(kProjMapTexButton, 0, MyMap);
|
|
|
|
|
|
|
|
//if (projMapName)
|
|
|
|
// projMapName->SetText(projMap?projMap->GetFullName().data():GetString(IDS_DB_NONE));
|
|
|
|
return;
|
|
|
|
|
|
|
|
case kRefShadowProjMap:
|
|
|
|
return;
|
|
|
|
case kRefShadowType:
|
|
|
|
return;
|
|
|
|
case kRefOmniLight:
|
|
|
|
case kRefSpotLight:
|
|
|
|
case kRefTSpotLight:
|
|
|
|
case kRefDirLight:
|
|
|
|
case kRefTDirLight:
|
|
|
|
case kRefProjDirLight:
|
|
|
|
fLightPB = (IParamBlock2*)rtarg; break;
|
|
|
|
}
|
|
|
|
//fLightPB = (IParamBlock2*)rtarg;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefResult plRTLightBase::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message)
|
|
|
|
{
|
|
|
|
if( fLightPB )
|
|
|
|
{
|
|
|
|
ParamID param = fLightPB->LastNotifyParamID();
|
|
|
|
|
|
|
|
if( param == kAmbientOnlyStub )
|
|
|
|
{
|
|
|
|
fLightPB->EnableNotifications( false );
|
|
|
|
fLightPB->SetValue( kAmbientOnlyStub, TimeValue( 0 ), false );
|
|
|
|
// Assume this was true, since, well, we're IN NotifyRefChanged....
|
|
|
|
fLightPB->EnableNotifications( true );
|
|
|
|
|
|
|
|
return REF_SUCCEED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return REF_SUCCEED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev)
|
|
|
|
{
|
|
|
|
fIP = ip;
|
|
|
|
fClassDesc->BeginEditParams(ip, this, flags, prev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next)
|
|
|
|
{
|
|
|
|
GenLight::EndEditParams( ip, flags, next );
|
|
|
|
fIP = NULL;
|
|
|
|
fClassDesc->EndEditParams(ip, this, flags, next);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefResult plRTLightBase::EvalLightState(TimeValue t, Interval& valid, LightState *ls)
|
|
|
|
{
|
|
|
|
//t uselight;
|
|
|
|
//#if 0 //fLightPB->GetInt(kLightOn, t);
|
|
|
|
if(fLightPB->GetInt(kLightOn, t) )
|
|
|
|
ls->color = GetRGBColor(t,valid);
|
|
|
|
else
|
|
|
|
ls->color = Color(0,0,0);
|
|
|
|
ls->on = fLightPB->GetInt(kLightOn, t);
|
|
|
|
ls->intens = GetIntensity(t, valid);
|
|
|
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID || this->ClassID() == RTOMNI_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
ls->hotsize = GetHotspot(t, valid);
|
|
|
|
ls->fallsize = GetFallsize(t, valid);
|
|
|
|
ls->useNearAtten = GetUseAttenNear();
|
|
|
|
ls->useAtten = GetUseAtten();
|
|
|
|
ls->attenStart = GetAtten(t, ATTEN_START, valid);
|
|
|
|
ls->attenEnd = GetAtten(t, ATTEN_END, valid);
|
|
|
|
}else
|
|
|
|
{
|
|
|
|
ls->hotsize = 20;
|
|
|
|
ls->fallsize = 10000;
|
|
|
|
ls->useNearAtten = false; //GetUseAttenNear();
|
|
|
|
ls->useAtten = false; //GetUseAtten();
|
|
|
|
//ls->attenStart = GetAtten(t, ATTEN_START, valid);
|
|
|
|
//ls->attenEnd = GetAtten(t, ATTEN_END, valid);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
ls->shape = GW_SHAPE_CIRCULAR; //fLightPB->GetInt(kLightShapeRadio);
|
|
|
|
|
|
|
|
ls->aspect = -1.0;//GetAspect(t, valid);
|
|
|
|
ls->overshoot = false; //GetOvershoot();
|
|
|
|
ls->shadow = GetShadow();
|
|
|
|
ls->ambientOnly = false; //fLightPB->GetValue( kAmbiOnly,t, ls->ambientOnly, valid); //ls->ambientOnly = fLightP.AmbiOnly;
|
|
|
|
ls->affectDiffuse = true; //fLightPB->GetInt(kDiffOn,t); //ls->affectDiffusey = fLightP.AmbiOnly;
|
|
|
|
ls->affectSpecular = fLightPB->GetInt(kSpec,t); //ls- = fLightP.DiffOn;;
|
|
|
|
|
|
|
|
//ls->
|
|
|
|
|
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID )
|
|
|
|
ls->type = OMNI_LGT;
|
|
|
|
else if( this->ClassID() == RTDIR_LIGHT_CLASSID || this->ClassID() == RTPDIR_LIGHT_CLASSID )
|
|
|
|
ls->type = DIRECT_LGT;
|
|
|
|
else
|
|
|
|
ls->type = SPOT_LGT;
|
|
|
|
|
|
|
|
return REF_SUCCEED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define PLASMAOBJ_DATA_CHUNK 1
|
|
|
|
|
|
|
|
IOResult plRTLightBase::Save(ISave* isave)
|
|
|
|
{
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
IOResult plRTLightBase::Load(ILoad* iload)
|
|
|
|
{
|
|
|
|
ULONG nb;
|
|
|
|
IOResult res;
|
|
|
|
int numrefs = 0;
|
|
|
|
|
|
|
|
while (IO_OK == (res = iload->OpenChunk()))
|
|
|
|
{
|
|
|
|
if (iload->CurChunkID() == PLASMAOBJ_DATA_CHUNK)
|
|
|
|
res = iload->Read(&numrefs, sizeof(int), &nb);
|
|
|
|
iload->CloseChunk();
|
|
|
|
|
|
|
|
if (res != IO_OK)
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return IO_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
ObjLightDesc *plRTLightBase::CreateLightDesc(INode *n, BOOL forceShadowBuf)
|
|
|
|
{
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetHotspot(TimeValue t, float f)
|
|
|
|
{
|
|
|
|
if(!IsSpot())
|
|
|
|
return;
|
|
|
|
if(f < 0.5f)
|
|
|
|
f = 0.5f;
|
|
|
|
if(!IsDir() && (f > 179.5f))
|
|
|
|
f = 179.5f;
|
|
|
|
//pblock->SetValue( PB_HOTSIZE, t, f );
|
|
|
|
fLightPB->SetValue(kHotSpot, t, f);
|
|
|
|
|
|
|
|
//fLightP.HotSpot = f;
|
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
float plRTLightBase::GetHotspot(TimeValue t, Interval& valid)
|
|
|
|
{
|
|
|
|
Interval iv;
|
|
|
|
|
|
|
|
if(!IsSpot() && !IsDir())
|
|
|
|
return -1.0f;
|
|
|
|
float f;
|
|
|
|
//pblock->GetValue( PB_HOTSIZE, t, f, valid );
|
|
|
|
if(IsSpot())
|
|
|
|
fLightPB->GetValue(kHotSpot, t, f, FOREVER);
|
|
|
|
else
|
|
|
|
f = 20.0;
|
|
|
|
|
|
|
|
if(GetFallsize(t, iv) < f )
|
|
|
|
return GetFallsize(t, iv) - 2.0;
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::SetRGBColor(TimeValue t, Point3& rgb)
|
|
|
|
{
|
|
|
|
//fLightPB->SetValue(plRTLightBase::kRed, t, rgb.x);
|
|
|
|
//fLightPB->SetValue(plRTLightBase::kGreen, t, rgb.y);
|
|
|
|
//fLightPB->SetValue(plRTLightBase::kBlue, t, rgb.z);
|
|
|
|
fLightPB->SetValue(kLightColor, t, rgb );
|
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Point3 plRTLightBase::GetRGBColor(TimeValue t, Interval &valid)
|
|
|
|
{
|
|
|
|
//Point3 Foo = Point3(fLightPB->GetInt(plRTLightBase::kRed, t), fLightPB->GetInt(plRTLightBase::kGreen, t), fLightPB->GetInt(plRTLightBase::kBlue, t));
|
|
|
|
Point3 rgb;
|
|
|
|
fLightPB->GetValue( kLightColor, t, rgb, valid );
|
|
|
|
return rgb;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetFallsize(TimeValue t, float f)
|
|
|
|
{
|
|
|
|
if(!IsSpot() )
|
|
|
|
return;
|
|
|
|
if(f < 0.5f)
|
|
|
|
f = 0.5f;
|
|
|
|
if(!IsDir() && (f > 179.5f))
|
|
|
|
f = 179.5f;
|
|
|
|
//pblock->SetValue( PB_FALLSIZE, t, f );
|
|
|
|
fLightPB->SetValue(kFallOff, t, f);
|
|
|
|
|
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
float plRTLightBase::GetFallsize(TimeValue t, Interval& valid)
|
|
|
|
{
|
|
|
|
if(!IsSpot() && !IsDir())
|
|
|
|
return -1.0f;
|
|
|
|
float f;
|
|
|
|
|
|
|
|
//pblock->GetValue( PB_FALLSIZE, t, f, valid );
|
|
|
|
if(IsSpot())
|
|
|
|
fLightPB->GetValue(kFallOff, t, f, valid);
|
|
|
|
else
|
|
|
|
f = 200.0;
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetAtten(TimeValue t, int which, float f)
|
|
|
|
{
|
|
|
|
|
|
|
|
if(which != ATTEN_START)
|
|
|
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, f);
|
|
|
|
|
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float plRTLightBase::GetAtten(TimeValue t, int which, Interval& valid)
|
|
|
|
{
|
|
|
|
float f = 0.0;
|
|
|
|
//if(fLightPB->GetInt(kEndAttenFar, t) == 1)
|
|
|
|
//if(LyteType == RT_OMNI)
|
|
|
|
// fLightPB->GetValue(kStartAttenFar, t, f, FOREVER);
|
|
|
|
//else
|
|
|
|
// fLightPB->GetValue(kStartAttenNear, t, f, FOREVER);
|
|
|
|
if(which == LIGHT_ATTEN_START)
|
|
|
|
return f;
|
|
|
|
else
|
|
|
|
return( fLightPB->GetFloat(kAttenMaxFalloffEdit, t));
|
|
|
|
|
|
|
|
//return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetTDist(TimeValue t, float f)
|
|
|
|
{
|
|
|
|
// int i;
|
|
|
|
// fLightPB->GetInt(kLightType, t, i);
|
|
|
|
|
|
|
|
//pblock->SetValue( PB_TDIST, t, f );
|
|
|
|
//To be implemented.
|
|
|
|
if( IHasAttenuation() )
|
|
|
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, f);
|
|
|
|
//fLightPB->SetValue(kTargetDist, t, f);
|
|
|
|
|
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
float plRTLightBase::GetTDist(TimeValue t, Interval& valid)
|
|
|
|
{
|
|
|
|
if(!IsSpot())
|
|
|
|
return -1.0f;
|
|
|
|
// int i;
|
|
|
|
//fLightPB->GetValue(kLightType, t, i, valid);
|
|
|
|
float f = -1.0;
|
|
|
|
|
|
|
|
fLightPB->GetFloat( kAttenMaxFalloffEdit, t );
|
|
|
|
|
|
|
|
//pblock->GetValue( PB_TDIST, t, f, valid );
|
|
|
|
//fLightPB->GetValue(kTargetDist, t, f, valid);
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::SetConeDisplay(int s, int notify)
|
|
|
|
{
|
|
|
|
if(!IsDir())
|
|
|
|
fLightPB->SetValue(kShowConeBool, 0, s);
|
|
|
|
if(notify && IsSpot())
|
|
|
|
NotifyDependents(FOREVER, PART_OBJ, REFMSG_CHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL plRTLightBase::GetConeDisplay(void)
|
|
|
|
{
|
|
|
|
if(!IsDir())
|
|
|
|
return fLightPB->GetInt(kShowConeBool);
|
|
|
|
return
|
|
|
|
false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::SetProjMap(BitmapInfo* pmap)
|
|
|
|
{
|
|
|
|
//plLayerTex* MyMap = new plLayerTex;
|
|
|
|
if(!fTex)
|
|
|
|
fTex = new plLayerTex;
|
|
|
|
fTex->SetBitmap(pmap);
|
|
|
|
ReplaceReference(kRefProjMap,fTex);
|
|
|
|
|
|
|
|
IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap);
|
|
|
|
bitmapPB->SetValue(kBmpUseBitmap, 0, 1);
|
|
|
|
|
|
|
|
// This is set in the call to fTex->SetBitmap(pmap)
|
|
|
|
//PBBitmap pbb(*pmap);
|
|
|
|
//bitmapPB->SetValue(kBmpBitmap, 0, &pbb);
|
|
|
|
|
|
|
|
//Texmap* MyMap;
|
|
|
|
//fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER);
|
|
|
|
if (fTex) fLightPB->SetValue(kUseProjectorBool, 0, true);
|
|
|
|
NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED);
|
|
|
|
if( fLightPB->GetMap() )
|
|
|
|
{
|
|
|
|
fLightPB->GetMap()->Invalidate(kProjMapTexButton);
|
|
|
|
fLightPB->GetMap()->Invalidate(kUseProjectorBool);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL plRTLightBase::GetShadow()
|
|
|
|
{
|
|
|
|
return fLightPB->GetInt(kCastShadows);
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::SetShadow(int a)
|
|
|
|
{
|
|
|
|
fLightPB->SetValue(kCastShadows, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Texmap* plRTLightBase::GetProjMap()
|
|
|
|
{
|
|
|
|
if( !fLightPB->GetInt(kUseProjectorBool) )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if( GetTex() )
|
|
|
|
{
|
|
|
|
const char* dbgTexName = GetTex()->GetName();
|
|
|
|
|
|
|
|
IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap);
|
|
|
|
hsAssert(bitmapPB, "LayerTex with no param block");
|
|
|
|
|
|
|
|
int noCompress = fLightPB->GetInt(kProjNoCompress);
|
|
|
|
int noMip = fLightPB->GetInt(kProjNoMip);
|
|
|
|
bitmapPB->SetValue(kBmpNonCompressed, TimeValue(0), noCompress);
|
|
|
|
bitmapPB->SetValue(kBmpNoFilter, TimeValue(0), noMip);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Texmap*) GetTex();
|
|
|
|
}
|
|
|
|
|
|
|
|
void plRTLightBase::UpdateTargDistance(TimeValue t, INode* inode)
|
|
|
|
{
|
|
|
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID )
|
|
|
|
{
|
|
|
|
Point3 pt,v[3];
|
|
|
|
if (GetTargetPoint(t, inode, pt))
|
|
|
|
{
|
|
|
|
Matrix3 tm = inode->GetObjectTM(t);
|
|
|
|
float den = FLength(tm.GetRow(2));
|
|
|
|
float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f;
|
|
|
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist);
|
|
|
|
|
|
|
|
// fLightPB->SetValue(kTargetDist, t, dist);
|
|
|
|
//TCHAR buf[40];
|
|
|
|
//_stprintf(buf,_T("%0.3f"),targDist);
|
|
|
|
//SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
///
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Target Creation for Targeted Lights...
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
class TSpotCreationManager : public MouseCallBack, ReferenceMaker
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
CreateMouseCallBack *createCB;
|
|
|
|
INode *lgtNode,*targNode;
|
|
|
|
plRTLightBase *lgtObject;
|
|
|
|
TargetObject *targObject;
|
|
|
|
int attachedToNode;
|
|
|
|
IObjCreate *createInterface;
|
|
|
|
ClassDesc *cDesc;
|
|
|
|
Matrix3 mat; // the nodes TM relative to the CP
|
|
|
|
IPoint2 pt0;
|
|
|
|
int ignoreSelectionChange;
|
|
|
|
int lastPutCount;
|
|
|
|
|
|
|
|
void CreateNewObject();
|
|
|
|
|
|
|
|
int NumRefs() { return 1; }
|
|
|
|
RefTargetHandle GetReference(int i) { return (RefTargetHandle)lgtNode; }
|
|
|
|
void SetReference(int i, RefTargetHandle rtarg) { lgtNode = (INode *)rtarg; }
|
|
|
|
|
|
|
|
// StdNotifyRefChanged calls this, which can change the partID to new value
|
|
|
|
// If it doesnt depend on the particular message& partID, it should return
|
|
|
|
// REF_DONTCARE
|
|
|
|
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
|
|
|
|
PartID& partID, RefMessage message);
|
|
|
|
|
|
|
|
public:
|
|
|
|
void Begin( IObjCreate *ioc, ClassDesc *desc );
|
|
|
|
void End();
|
|
|
|
|
|
|
|
TSpotCreationManager() { ignoreSelectionChange = FALSE; }
|
|
|
|
int proc( HWND hwnd, int msg, int point, int flag, IPoint2 m );
|
|
|
|
BOOL SupportAutoGrid(){return TRUE;}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define CID_TSPOTCREATE CID_USER + 3
|
|
|
|
|
|
|
|
class TSpotCreateMode : public CommandMode {
|
|
|
|
TSpotCreationManager proc;
|
|
|
|
public:
|
|
|
|
void Begin( IObjCreate *ioc, ClassDesc *desc ) { proc.Begin( ioc, desc ); }
|
|
|
|
void End() { proc.End(); }
|
|
|
|
|
|
|
|
int Class() { return CREATE_COMMAND; }
|
|
|
|
int ID() { return CID_TSPOTCREATE; }
|
|
|
|
MouseCallBack *MouseProc(int *numPoints) { *numPoints = 1000000; return &proc; }
|
|
|
|
ChangeForegroundCallback *ChangeFGProc() { return CHANGE_FG_SELECTED; }
|
|
|
|
BOOL ChangeFG( CommandMode *oldMode ) { return (oldMode->ChangeFGProc() != CHANGE_FG_SELECTED); }
|
|
|
|
void EnterMode() {
|
|
|
|
}
|
|
|
|
void ExitMode() {
|
|
|
|
}
|
|
|
|
BOOL IsSticky() { return FALSE; }
|
|
|
|
};
|
|
|
|
|
|
|
|
static TSpotCreateMode theTSpotCreateMode;
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
void TSpotCreationManager::Begin( IObjCreate *ioc, ClassDesc *desc )
|
|
|
|
{
|
|
|
|
createInterface = ioc;
|
|
|
|
cDesc = desc;
|
|
|
|
attachedToNode = FALSE;
|
|
|
|
createCB = NULL;
|
|
|
|
lgtNode = NULL;
|
|
|
|
targNode = NULL;
|
|
|
|
lgtObject = NULL;
|
|
|
|
targObject = NULL;
|
|
|
|
CreateNewObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TSpotCreationManager::End()
|
|
|
|
{
|
|
|
|
if ( lgtObject ) {
|
|
|
|
lgtObject->EndEditParams( (IObjParam*)createInterface, END_EDIT_REMOVEUI, NULL);
|
|
|
|
if ( !attachedToNode ) {
|
|
|
|
// RB 4-9-96: Normally the hold isn't holding when this
|
|
|
|
// happens, but it can be in certain situations (like a track view paste)
|
|
|
|
// Things get confused if it ends up with undo...
|
|
|
|
theHold.Suspend();
|
|
|
|
//delete lgtObject;
|
|
|
|
lgtObject->DeleteThis(); // JBW 11.1.99, this allows scripted plugin lights to delete cleanly
|
|
|
|
lgtObject = NULL;
|
|
|
|
theHold.Resume();
|
|
|
|
// RB 7/28/97: If something has been put on the undo stack since this object was created, we have to flush the undo stack.
|
|
|
|
if (theHold.GetGlobalPutCount()!=lastPutCount) {
|
|
|
|
GetSystemSetting(SYSSET_CLEAR_UNDO);
|
|
|
|
}
|
|
|
|
macroRec->Cancel(); // JBW 4/23/99
|
|
|
|
}
|
|
|
|
else if ( lgtNode ) {
|
|
|
|
// Get rid of the reference.
|
|
|
|
DeleteReference(0); // sets lgtNode = NULL
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RefResult TSpotCreationManager::NotifyRefChanged(
|
|
|
|
Interval changeInt,
|
|
|
|
RefTargetHandle hTarget,
|
|
|
|
PartID& partID,
|
|
|
|
RefMessage message)
|
|
|
|
{
|
|
|
|
switch (message) {
|
|
|
|
|
|
|
|
case REFMSG_PRENOTIFY_PASTE:
|
|
|
|
case REFMSG_TARGET_SELECTIONCHANGE:
|
|
|
|
if ( ignoreSelectionChange ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lgtObject && lgtNode==hTarget) {
|
|
|
|
// this will set camNode== NULL;
|
|
|
|
DeleteReference(0);
|
|
|
|
goto endEdit;
|
|
|
|
}
|
|
|
|
// fall through
|
|
|
|
|
|
|
|
case REFMSG_TARGET_DELETED:
|
|
|
|
if ( lgtObject && lgtNode==hTarget ) {
|
|
|
|
endEdit:
|
|
|
|
lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL);
|
|
|
|
lgtObject = NULL;
|
|
|
|
lgtNode = NULL;
|
|
|
|
CreateNewObject();
|
|
|
|
attachedToNode = FALSE;
|
|
|
|
}
|
|
|
|
else if (targNode==hTarget) {
|
|
|
|
targNode = NULL;
|
|
|
|
targObject = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return REF_SUCCEED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TSpotCreationManager::CreateNewObject()
|
|
|
|
{
|
|
|
|
lgtObject = (plRTLightBase *)cDesc->Create();
|
|
|
|
lastPutCount = theHold.GetGlobalPutCount();
|
|
|
|
|
|
|
|
macroRec->BeginCreate(cDesc); // JBW 4/23/99
|
|
|
|
|
|
|
|
// Start the edit params process
|
|
|
|
if ( lgtObject ) {
|
|
|
|
lgtObject->BeginEditParams( (IObjParam*)createInterface, BEGIN_EDIT_CREATE, NULL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void whoa(){};
|
|
|
|
|
|
|
|
static BOOL needToss;
|
|
|
|
|
|
|
|
int TSpotCreationManager::proc(
|
|
|
|
HWND hwnd,
|
|
|
|
int msg,
|
|
|
|
int point,
|
|
|
|
int flag,
|
|
|
|
IPoint2 m )
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
TSTR targName;
|
|
|
|
ViewExp *vpx = createInterface->GetViewport(hwnd);
|
|
|
|
assert( vpx );
|
|
|
|
|
|
|
|
switch ( msg ) {
|
|
|
|
case MOUSE_POINT:
|
|
|
|
switch ( point ) {
|
|
|
|
case 0:
|
|
|
|
pt0 = m;
|
|
|
|
assert( lgtObject );
|
|
|
|
vpx->CommitImplicitGrid(m, flag); //KENNY MERGE
|
|
|
|
if ( createInterface->SetActiveViewport(hwnd) ) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (createInterface->IsCPEdgeOnInView()) {
|
|
|
|
res = FALSE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if lights were hidden by category, re-display them
|
|
|
|
GetCOREInterface()->SetHideByCategoryFlags(
|
|
|
|
GetCOREInterface()->GetHideByCategoryFlags() & ~HIDE_LIGHTS);
|
|
|
|
|
|
|
|
if ( attachedToNode ) {
|
|
|
|
// send this one on its way
|
|
|
|
lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL);
|
|
|
|
macroRec->EmitScript(); // JBW 4/23/99
|
|
|
|
|
|
|
|
// Get rid of the reference.
|
|
|
|
if (lgtNode)
|
|
|
|
DeleteReference(0);
|
|
|
|
|
|
|
|
// new object
|
|
|
|
CreateNewObject(); // creates lgtObject
|
|
|
|
}
|
|
|
|
|
|
|
|
needToss = theHold.GetGlobalPutCount()!=lastPutCount;
|
|
|
|
|
|
|
|
theHold.Begin(); // begin hold for undo
|
|
|
|
mat.IdentityMatrix();
|
|
|
|
|
|
|
|
// link it up
|
|
|
|
lgtNode = createInterface->CreateObjectNode( lgtObject);
|
|
|
|
attachedToNode = TRUE;
|
|
|
|
assert( lgtNode );
|
|
|
|
createCB = lgtObject->GetCreateMouseCallBack();
|
|
|
|
createInterface->SelectNode( lgtNode );
|
|
|
|
|
|
|
|
// Create target object and node
|
|
|
|
targObject = new TargetObject;
|
|
|
|
assert(targObject);
|
|
|
|
targNode = createInterface->CreateObjectNode( targObject);
|
|
|
|
assert(targNode);
|
|
|
|
targName = lgtNode->GetName();
|
|
|
|
targName += GetString(IDS_DB_DOT_TARGET);
|
|
|
|
targNode->SetName(targName);
|
|
|
|
|
|
|
|
// hook up camera to target using lookat controller.
|
|
|
|
createInterface->BindToTarget(lgtNode,targNode);
|
|
|
|
|
|
|
|
// Reference the new node so we'll get notifications.
|
|
|
|
MakeRefByID( FOREVER, 0, lgtNode);
|
|
|
|
|
|
|
|
// Position camera and target at first point then drag.
|
|
|
|
mat.IdentityMatrix();
|
|
|
|
//mat[3] = vpx->GetPointOnCP(m);
|
|
|
|
#ifdef _3D_CREATE
|
|
|
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) );
|
|
|
|
#else
|
|
|
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
|
|
|
|
#endif
|
|
|
|
createInterface->SetNodeTMRelConstPlane(lgtNode, mat);
|
|
|
|
createInterface->SetNodeTMRelConstPlane(targNode, mat);
|
|
|
|
lgtObject->Enable(1);
|
|
|
|
|
|
|
|
ignoreSelectionChange = TRUE;
|
|
|
|
createInterface->SelectNode( targNode,0);
|
|
|
|
ignoreSelectionChange = FALSE;
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
if (Length(m-pt0)<2)
|
|
|
|
goto abort;
|
|
|
|
//mat[3] = vpx->GetPointOnCP(m);
|
|
|
|
#ifdef _3D_CREATE
|
|
|
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) );
|
|
|
|
#else
|
|
|
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
|
|
|
|
#endif
|
|
|
|
macroRec->Disable(); // JBW 4/23/99
|
|
|
|
createInterface->SetNodeTMRelConstPlane(targNode, mat);
|
|
|
|
macroRec->Enable();
|
|
|
|
|
|
|
|
ignoreSelectionChange = TRUE;
|
|
|
|
createInterface->SelectNode( lgtNode);
|
|
|
|
ignoreSelectionChange = FALSE;
|
|
|
|
|
|
|
|
theHold.Accept(IDS_DS_CREATE);
|
|
|
|
|
|
|
|
createInterface->AddLightToScene(lgtNode);
|
|
|
|
createInterface->RedrawViews(createInterface->GetTime());
|
|
|
|
|
|
|
|
res = FALSE; // We're done
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOUSE_MOVE:
|
|
|
|
//mat[3] = vpx->GetPointOnCP(m);
|
|
|
|
#ifdef _3D_CREATE
|
|
|
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) );
|
|
|
|
#else
|
|
|
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE));
|
|
|
|
#endif
|
|
|
|
macroRec->Disable(); // JBW 4/23/99
|
|
|
|
createInterface->SetNodeTMRelConstPlane(targNode, mat);
|
|
|
|
macroRec->Enable();
|
|
|
|
createInterface->RedrawViews(createInterface->GetTime());
|
|
|
|
|
|
|
|
macroRec->SetProperty(lgtObject, _T("target"), // JBW 4/23/99
|
|
|
|
mr_create, Class_ID(TARGET_CLASS_ID, 0), GEOMOBJECT_CLASS_ID, 1, _T("transform"), mr_matrix3, &mat);
|
|
|
|
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOUSE_FREEMOVE:
|
|
|
|
SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CROSS_HAIR)));
|
|
|
|
#ifdef _OSNAP
|
|
|
|
//Snap Preview
|
|
|
|
#ifdef _3D_CREATE
|
|
|
|
vpx->SnapPreview(m,m,NULL, SNAP_IN_3D);
|
|
|
|
#else
|
|
|
|
vpx->SnapPreview(m,m,NULL, SNAP_IN_PLANE);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
vpx->TrackImplicitGrid(m); //KENNY MERGE
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOUSE_PROPCLICK:
|
|
|
|
// right click while between creations
|
|
|
|
createInterface->RemoveMode(NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MOUSE_ABORT:
|
|
|
|
abort:
|
|
|
|
assert( lgtObject );
|
|
|
|
lgtObject->EndEditParams( (IObjParam*)createInterface,0,NULL);
|
|
|
|
// Toss the undo stack if param changes have been made
|
|
|
|
macroRec->Cancel(); // JBW 4/23/99
|
|
|
|
theHold.Cancel(); // deletes both the camera and target.
|
|
|
|
if (needToss)
|
|
|
|
GetSystemSetting(SYSSET_CLEAR_UNDO);
|
|
|
|
lgtNode = NULL;
|
|
|
|
targNode = NULL;
|
|
|
|
createInterface->RedrawViews(createInterface->GetTime());
|
|
|
|
CreateNewObject();
|
|
|
|
attachedToNode = FALSE;
|
|
|
|
res = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
//KENNY MERGE
|
|
|
|
if ((res == CREATE_STOP)||(res==CREATE_ABORT))
|
|
|
|
vpx->ReleaseImplicitGrid();
|
|
|
|
createInterface->ReleaseViewport(vpx);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|