Initial import: Tesla Release 4.10 (Tesla:BattleTech & Tesla:Red Planet)

Archival snapshot of the Virtual World Entertainment Tesla cockpit
software, 1994-1996: MUNGA engine and L4 pod layer source (Borland
C++ 5.0), BT/RP game code, and game content (models, audio, maps,
gauges, Division renderer data). Includes third-party libraries:
Division dVS/DPL graphics, HMI SOS audio, WATTCP networking.

Files are preserved byte-for-byte (.gitattributes disables all
line-ending conversion). README.md documents the layout, target
hardware, and toolchain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-02 13:21:58 -05:00
co-authored by Claude Fable 5
commit fdd9ac9d97
8682 changed files with 419927 additions and 0 deletions
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+49
View File
@@ -0,0 +1,49 @@
LINK_OPTIONS = -Tpe -ax -L$(LIBRARY_PATH) -v -x
BCC = bcc32
TASM_OPTIONS = -zi
STARTUP_OBJ = $(STARTUP_ROOT)\c0x32.obj
STARTUP_LIBS = $(STARTUP_ROOT)\dpmi32.lib $(STARTUP_ROOT)\cw32.lib
LIB_OPTIONS = /P512
$(CFG_FILE): d0.mak make.cfg $(BPATH)
copy &&|
-DLAB_ONLY;LBE4;DEBUG_LEVEL=0;DEBUG_STREAM=cout
-DTEST_CLASS=50;MESSAGE_BUFFERING=False
-b
-r
-ff
-AT
-k-
-N-
-v
-vi-
-5
-pc
-a4
-V
-Jg
-x-
-RT-
-O2
-Ot
-Oc
-Og
-O
-Ol
-Z
-Ob
-Oe
-Oi
-Om
-Op
-Ov
-w
-c
-I$(INCLUDE_PATH)
-H
-H=$(HEADER_FILE)
-Hc
-n$(TARGET_DIR)
| $(CFG_FILE)
Binary file not shown.
+831
View File
@@ -0,0 +1,831 @@
//===========================================================================//
// File: affnmtrx.cc //
// Project: MUNGA Brick: Math Library //
// Contents: Implementation details for the Affine matrices //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/20/94 JMA Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AFFNMTRX_HPP)
#include <affnmtrx.hpp>
#endif
#if !defined(MATRIX_HPP)
# include <matrix.hpp>
#endif
#if !defined(LINMTRX_HPP)
#include <linmtrx.hpp>
#endif
#if !defined(ORIGIN_HPP)
#include <origin.hpp>
#endif
const AffineMatrix
AffineMatrix::Identity(True);
#if defined(USE_SIGNATURE)
int
Is_Signature_Bad(const volatile AffineMatrix *)
{
return False;
}
#endif
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::BuildIdentity()
{
Check_Pointer(this);
entries[0] = 1.0f;
entries[1] = 0.0f;
entries[2] = 0.0f;
entries[3] = 0.0f;
entries[4] = 0.0f;
entries[5] = 1.0f;
entries[6] = 0.0f;
entries[7] = 0.0f;
entries[8] = 0.0f;
entries[9] = 0.0f;
entries[10] = 1.0f;
entries[11] = 0.0f;
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::operator=(const AffineMatrix& m)
{
Check_Pointer(this);
Check(&m);
#if sizeof(entries)>sizeof(m.entries)
# error memcpy mismatch
#endif
memcpy(entries, m.entries, sizeof(m.entries));
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::operator=(const Origin& p)
{
Check_Pointer(this);
Check(&p);
*this = p.angularPosition;
*this = p.linearPosition;
return *this;
}
AffineMatrix&
AffineMatrix::operator=(const Hinge &hinge)
{
Check_Pointer(this);
Check(&hinge);
SinCosPair x,y,z;
switch (hinge.axisNumber)
{
case X_Axis:
x = hinge.rotationAmount;
(*this)(0,0) = 1.0f;
(*this)(0,1) = 0.0f;
(*this)(0,2) = 0.0f;
(*this)(1,0) = 0.0f;
(*this)(1,1) = x.cosine;
(*this)(1,2) = -x.sine;
(*this)(2,0) = 0.0f;
(*this)(2,1) = x.sine;
(*this)(2,2) = x.cosine;
break;
case Y_Axis:
y = hinge.rotationAmount;
(*this)(0,0) = y.cosine;
(*this)(0,1) = 0.0f;
(*this)(0,2) = y.sine;
(*this)(1,0) = 0.0f;
(*this)(1,1) = 1.0f;
(*this)(1,2) = 0.0f;
(*this)(2,0) = -y.sine;
(*this)(2,1) = 0.0f;
(*this)(2,2) = y.cosine;
break;
case Z_Axis:
z = hinge.rotationAmount;
(*this)(0,0) = z.cosine;
(*this)(0,1) = -z.sine;
(*this)(0,2) = 0.0f;
(*this)(1,0) = z.sine;
(*this)(1,1) = z.cosine;
(*this)(1,2) = 0.0f;
(*this)(2,0) = 0.0f;
(*this)(2,1) = 0.0f;
(*this)(2,2) = 1.0f;
break;
}
return *this;
}
//
//#############################################################################
//#############################################################################
//
AffineMatrix&
AffineMatrix::operator=(const EulerAngles &angles)
{
Check_Pointer(this);
Check(&angles);
SinCosPair
x,
y,
z;
x = angles.pitch;
y = angles.yaw;
z = angles.roll;
(*this)(0,0) = y.cosine*z.cosine;
(*this)(0,1) = y.cosine*z.sine;
(*this)(0,2) = -y.sine;
(*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine;
(*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine;
(*this)(1,2) = x.sine*y.cosine;
(*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine;
(*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine;
(*this)(2,2) = x.cosine*y.cosine;
Check(this);
return *this;
}
//
//#############################################################################
//#############################################################################
//
AffineMatrix&
AffineMatrix::operator=(const YawPitchRoll &angles)
{
Check_Pointer(this);
Check(&angles);
SinCosPair
x,
y,
z;
x = angles.pitch;
y = angles.yaw;
z = angles.roll;
(*this)(0,0) = y.cosine*z.cosine + x.sine*y.sine*z.sine;
(*this)(0,1) = x.cosine*z.sine;
(*this)(0,2) = x.sine*y.cosine*z.sine - y.sine*z.cosine;
(*this)(1,0) = x.sine*y.sine*z.cosine - y.cosine*z.sine;
(*this)(1,1) = x.cosine*z.cosine;
(*this)(1,2) = y.sine*z.sine + x.sine*y.cosine*z.cosine;
(*this)(2,0) = x.cosine*y.sine;
(*this)(2,1) = -x.sine;
(*this)(2,2) = x.cosine*y.cosine;
Check(this);
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::operator=(const Quaternion &q)
{
Check_Pointer(this);
Check(&q);
Scalar
a = q.x*q.y,
b = q.y*q.z,
c = q.z*q.x,
d = q.w*q.x,
e = q.w*q.y,
f = q.w*q.z,
g = q.w*q.w,
h = q.x*q.x,
i = q.y*q.y,
j = q.z*q.z;
(*this)(0,0) = g + h - i - j;
(*this)(1,0) = 2.0f*(a - f);
(*this)(2,0) = 2.0f*(c + e);
(*this)(0,1) = 2.0f*(f + a);
(*this)(1,1) = g - h + i - j;
(*this)(2,1) = 2.0f*(b - d);
(*this)(0,2) = 2.0f*(c - e);
(*this)(1,2) = 2.0f*(b + d);
(*this)(2,2) = g - h - i + j;
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::operator=(const Matrix4x4 &m)
{
Check_Pointer(this);
Check(&m);
Warn(!Small_Enough(m(0,3)));
Warn(!Small_Enough(m(1,3)));
Warn(!Small_Enough(m(2,3)));
Warn(!Close_Enough(m(3,3),1.0f));
(*this)(0,0) = m(0,0);
(*this)(0,1) = m(0,1);
(*this)(0,2) = m(0,2);
(*this)(1,0) = m(1,0);
(*this)(1,1) = m(1,1);
(*this)(1,2) = m(1,2);
(*this)(2,0) = m(2,0);
(*this)(2,1) = m(2,1);
(*this)(2,2) = m(2,2);
(*this)(3,0) = m(3,0);
(*this)(3,1) = m(3,1);
(*this)(3,2) = m(3,2);
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::operator=(const TransposedMatrix &m)
{
Check_Pointer(this);
Check(&m);
Warn(!Small_Enough(m(3,0)));
Warn(!Small_Enough(m(3,1)));
Warn(!Small_Enough(m(3,2)));
Warn(!Close_Enough(m(3,3),1.0f));
(*this)(0,0) = m(0,0);
(*this)(0,1) = m(1,0);
(*this)(0,2) = m(2,0);
(*this)(1,0) = m(0,1);
(*this)(1,1) = m(1,1);
(*this)(1,2) = m(2,1);
(*this)(2,0) = m(0,2);
(*this)(2,1) = m(1,2);
(*this)(2,2) = m(2,2);
(*this)(3,0) = m(0,3);
(*this)(3,1) = m(1,3);
(*this)(3,2) = m(2,3);
return *this;
}
//
//###########################################################################
//###########################################################################
//
Logical
AffineMatrix::operator==(const AffineMatrix& m) const
{
Check(this);
Check(&m);
for (size_t i=0; i<ELEMENTS(entries); ++i) {
if (!Close_Enough(entries[i],m.entries[i])) {
return False;
}
}
return True;
}
//
//###########################################################################
//###########################################################################
//
Logical
AffineMatrix::operator!=(const AffineMatrix& m) const
{
Check(this);
Check(&m);
for (size_t i=0; i<ELEMENTS(entries); ++i) {
if (!Close_Enough(entries[i],m.entries[i])) {
return True;
}
}
return False;
}
//
//###########################################################################
//###########################################################################
//
void
AffineMatrix::GetFromAxis(
size_t index,
Vector3D *v
) const
{
Check(this);
Check_Pointer(v);
Warn(index>W_Axis);
v->x = (*this)(index,X_Axis);
v->y = (*this)(index,Y_Axis);
v->z = (*this)(index,Z_Axis);
}
//
//###########################################################################
//###########################################################################
//
void
AffineMatrix::GetToAxis(
size_t index,
Vector3D *v
) const
{
Check(this);
Check_Pointer(v);
Warn(index>Z_Axis);
v->x = (*this)(X_Axis,index);
v->y = (*this)(Y_Axis,index);
v->z = (*this)(Z_Axis,index);
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::SetFromAxis(
size_t index,
const Vector3D &v
)
{
Check_Pointer(this);
Check(&v);
Warn(index>W_Axis);
(*this)(index,X_Axis) = v.x;
(*this)(index,Y_Axis) = v.y;
(*this)(index,Z_Axis) = v.z;
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::SetToAxis(
size_t index,
const Vector3D &v
)
{
Check_Pointer(this);
Check(&v);
Warn(index>Z_Axis);
(*this)(X_Axis,index) = v.x;
(*this)(Y_Axis,index) = v.y;
(*this)(Z_Axis,index) = v.z;
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Multiply(
const AffineMatrix& Source1,
const AffineMatrix& Source2
)
{
Check_Pointer(this);
Check(&Source1);
Check(&Source2);
(*this)(0,0) =
Source1(0,0)*Source2(0,0)
+ Source1(0,1)*Source2(1,0)
+ Source1(0,2)*Source2(2,0);
(*this)(1,0) =
Source1(1,0)*Source2(0,0)
+ Source1(1,1)*Source2(1,0)
+ Source1(1,2)*Source2(2,0);
(*this)(2,0) =
Source1(2,0)*Source2(0,0)
+ Source1(2,1)*Source2(1,0)
+ Source1(2,2)*Source2(2,0);
(*this)(3,0) =
Source1(3,0)*Source2(0,0)
+ Source1(3,1)*Source2(1,0)
+ Source1(3,2)*Source2(2,0)
+ Source2(3,0);
(*this)(0,1) =
Source1(0,0)*Source2(0,1)
+ Source1(0,1)*Source2(1,1)
+ Source1(0,2)*Source2(2,1);
(*this)(1,1) =
Source1(1,0)*Source2(0,1)
+ Source1(1,1)*Source2(1,1)
+ Source1(1,2)*Source2(2,1);
(*this)(2,1) =
Source1(2,0)*Source2(0,1)
+ Source1(2,1)*Source2(1,1)
+ Source1(2,2)*Source2(2,1);
(*this)(3,1) =
Source1(3,0)*Source2(0,1)
+ Source1(3,1)*Source2(1,1)
+ Source1(3,2)*Source2(2,1)
+ Source2(3,1);
(*this)(0,2) =
Source1(0,0)*Source2(0,2)
+ Source1(0,1)*Source2(1,2)
+ Source1(0,2)*Source2(2,2);
(*this)(1,2) =
Source1(1,0)*Source2(0,2)
+ Source1(1,1)*Source2(1,2)
+ Source1(1,2)*Source2(2,2);
(*this)(2,2) =
Source1(2,0)*Source2(0,2)
+ Source1(2,1)*Source2(1,2)
+ Source1(2,2)*Source2(2,2);
(*this)(3,2) =
Source1(3,0)*Source2(0,2)
+ Source1(3,1)*Source2(1,2)
+ Source1(3,2)*Source2(2,2)
+ Source2(3,2);
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Invert(const AffineMatrix& Source)
{
Check_Pointer(this);
Check(&Source);
(*this)(0,0) = Source(1,1)*Source(2,2) - Source(1,2)*Source(2,1);
(*this)(1,0) = Source(1,2)*Source(2,0) - Source(1,0)*Source(2,2);
(*this)(2,0) = Source(1,0)*Source(2,1) - Source(1,1)*Source(2,0);
Scalar det =
(*this)(0,0)*Source(0,0)
+ (*this)(1,0)*Source(0,1)
+ (*this)(2,0)*Source(0,2);
Verify(!Small_Enough(det));
(*this)(3,0) =
-Source(3,0)*(*this)(0,0)
- Source(3,1)*(*this)(1,0)
- Source(3,2)*(*this)(2,0);
(*this)(0,1) = Source(0,2)*Source(2,1) - Source(0,1)*Source(2,2);
(*this)(1,1) = Source(0,0)*Source(2,2) - Source(0,2)*Source(2,0);
(*this)(2,1) = Source(0,1)*Source(2,0) - Source(0,0)*Source(2,1);
(*this)(3,1) =
-Source(3,0)*(*this)(0,1)
- Source(3,1)*(*this)(1,1)
- Source(3,2)*(*this)(2,1);
(*this)(0,2) = Source(0,1)*Source(1,2) - Source(0,2)*Source(1,1);
(*this)(1,2) = Source(1,0)*Source(0,2) - Source(0,0)*Source(1,2);
(*this)(2,2) = Source(0,0)*Source(1,1) - Source(0,1)*Source(1,0);
(*this)(3,2) =
-Source(3,0)*(*this)(0,2)
- Source(3,1)*(*this)(1,2)
- Source(3,2)*(*this)(2,2);
det = 1.0f/det;
for (int i=0; i<12; ++i)
{
entries[i] *= det;
}
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Multiply(const AffineMatrix &m,const Vector3D &v)
{
Check_Pointer(this);
Check(&m);
Check(&v);
(*this)(0,0) = m(0,0)*v.x;
(*this)(1,0) = m(1,0)*v.x;
(*this)(2,0) = m(2,0)*v.x;
(*this)(3,0) = m(3,0)*v.x;
(*this)(0,1) = m(0,1)*v.y;
(*this)(1,1) = m(1,1)*v.y;
(*this)(2,1) = m(2,1)*v.y;
(*this)(3,1) = m(3,1)*v.y;
(*this)(0,2) = m(0,2)*v.z;
(*this)(1,2) = m(1,2)*v.z;
(*this)(2,2) = m(2,2)*v.z;
(*this)(3,2) = m(3,2)*v.z;
return *this;
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Multiply(const AffineMatrix& m,const Quaternion &q)
{
Check_Pointer(this);
Check(&m);
Check(&q);
LinearMatrix t(LinearMatrix::Identity);
t = q;
return Multiply(m,t);
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Multiply(const AffineMatrix &m,const Point3D& p)
{
Check_Pointer(this);
Check(&m);
Check(&p);
(*this)(3,0) = m(3,0) + p.x;
(*this)(3,1) = m(3,1) + p.y;
(*this)(3,2) = m(3,2) + p.z;
return *this;
}
//
//###########################################################################
//###########################################################################
//
Scalar
AffineMatrix::Determinant() const
{
Check(this);
return
(*this)(0,0)*((*this)(1,1)*(*this)(2,2) - (*this)(1,2)*(*this)(2,1))
+ (*this)(0,1)*((*this)(1,2)*(*this)(2,0) - (*this)(1,0)*(*this)(2,2))
+ (*this)(0,2)*((*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0));
}
//
//###########################################################################
//###########################################################################
//
AffineMatrix&
AffineMatrix::Solve()
{
Check(this);
int column;
Scalar temp;
//
//------------------------------------------------------------------
// Make sure that we get a decent value into the first diagonal spot
//------------------------------------------------------------------
//
if (!(*this)(0,0))
{
for (column=0; column<3; ++column)
if ((*this)(0,column))
break;
Verify(column != 3);
//
//--------------
// Swap the columns
//--------------
//
temp = (*this)(0,0);
(*this)(0,0) = (*this)(0,column);
(*this)(0,column) = temp;
temp = (*this)(1,0);
(*this)(1,0) = (*this)(1,column);
(*this)(1,column) = temp;
temp = (*this)(2,0);
(*this)(2,0) = (*this)(2,column);
(*this)(2,column) = temp;
temp = (*this)(3,0);
(*this)(3,0) = (*this)(3,column);
(*this)(3,column) = temp;
}
//
//------------------------------------
// Make sure the diagonal entry is 1.0
//------------------------------------
//
temp = (*this)(0,0);
(*this)(0,0) = 1.0f;
(*this)(1,0) /= temp;
(*this)(2,0) /= temp;
(*this)(3,0) /= temp;
//
//------------------------
// Make the first row zero
//------------------------
//
temp = (*this)(0,1);
(*this)(0,1) = 0.0f;
(*this)(1,1) -= temp * (*this)(1,0);
(*this)(2,1) -= temp * (*this)(2,0);
(*this)(3,1) -= temp * (*this)(3,0);
temp = (*this)(0,2);
(*this)(0,2) = 0.0f;
(*this)(1,2) -= temp * (*this)(1,0);
(*this)(2,2) -= temp * (*this)(2,0);
(*this)(3,2) -= temp * (*this)(3,0);
//
//-------------------------------------------------------------------
// Make sure that we get a decent value into the second diagonal spot
//-------------------------------------------------------------------
//
if (!(*this)(1,1))
{
Verify(!(*this)(2,2));
//
//---------------------
// Swap the (*this) columns
//---------------------
//
temp = (*this)(1,1);
(*this)(1,1) = (*this)(1,2);
(*this)(1,2) = temp;
temp = (*this)(2,1);
(*this)(2,1) = (*this)(2,2);
(*this)(2,2) = temp;
temp = (*this)(3,1);
(*this)(3,1) = (*this)(3,2);
(*this)(3,2) = temp;
}
//
//-----------------------------------
// Make the second diaginal entry 1.0
//-----------------------------------
//
temp = (*this)(1,1);
(*this)(1,1) = 1.0f;
(*this)(2,1) /= temp;
(*this)(3,1) /= temp;
//
//------------------------------------
// Make the second row zeros otherwise
//------------------------------------
//
temp = (*this)(1,0);
(*this)(1,0) = 0.0f;
(*this)(2,0) -= temp * (*this)(2,1);
(*this)(3,0) -= temp * (*this)(3,1);
temp = (*this)(1,2);
(*this)(1,2) = 0.0f;
(*this)(2,2) -= temp * (*this)(2,1);
(*this)(3,2) -= temp * (*this)(3,1);
//
//---------------------------
// Make the last diagonal 1.0
//---------------------------
//
Verify((*this)(2,2));
temp = (*this)(2,2);
(*this)(2,2) = 1.0f;
(*this)(3,2) /= temp;
//
//------------------------------------
// Make the third row zeros otherwise
//------------------------------------
//
temp = (*this)(2,0);
(*this)(2,0) = 0.0f;
(*this)(3,0) -= temp * (*this)(3,2);
temp = (*this)(2,1);
(*this)(2,1) = 0.0f;
(*this)(3,1) -= temp * (*this)(3,2);
//
//-------------------------
// Return the reduced array
//-------------------------
//
return *this;
}
//
//###########################################################################
//###########################################################################
//
ostream&
operator <<(ostream& Stream, const AffineMatrix& M)
{
Check(&M);
return Stream << setprecision(4) << "\n\t| " << setw(9) << M(0,0) << ", "
<< setw(9) << M(0,1) << ", " << setw(9) << M(0,2) << ", 0 |\n\t| "
<< setw(9) << M(1,0) << ", " << setw(9) << M(1,1) << ", " << setw(9)
<< M(1,2) << ", 0 |\n\t| " << setw(9) << M(2,0) << ", " << setw(9)
<< M(2,1) << ", " << setw(9) << M(2,2) << ", 0 |\n\t| " << setw(9)
<< M(3,0) << ", " << setw(9) << M(3,1) << ", " << setw(9) << M(3,2)
<< ", 1 |";
}
//
//###########################################################################
//###########################################################################
//
Logical
AffineMatrix::TestInstance() const
{
return True;
}
#if defined(TEST_CLASS)
# include "affnmtrx.tcp"
#endif
+195
View File
@@ -0,0 +1,195 @@
//===========================================================================//
// File: affnmtrx.hh //
// Project: MUNGA Brick: Math Library //
// Contents: Interface specifications for Affine matrices //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/20/94 JMA Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AFFNMTRX_HPP)
# define AFFNMTRX_HPP
# if !defined(POINT3D_HPP)
# include <point3d.hpp>
# endif
class Origin;
class TransposedMatrix;
class Hinge;
class EulerAngles;
class Quaternion;
class YawPitchRoll;
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AffineMatrix ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AffineMatrix
{
public:
static const AffineMatrix
Identity;
#if defined(USE_SIGNATURE)
friend int
Is_Signature_Bad(const volatile AffineMatrix *);
#endif
Scalar
entries[12];
//
// Constructors
//
AffineMatrix()
{}
AffineMatrix&
BuildIdentity();
AffineMatrix(int)
{BuildIdentity();}
//
// Assignment Operators
//
AffineMatrix&
operator=(const AffineMatrix &m);
AffineMatrix&
operator=(const Origin &p);
AffineMatrix&
operator=(const Hinge &hinge);
AffineMatrix&
operator=(const EulerAngles &angles);
AffineMatrix&
operator=(const YawPitchRoll &angles);
AffineMatrix&
operator=(const Quaternion &q);
AffineMatrix&
operator=(const Point3D &p)
{return SetFromAxis(W_Axis,p);}
AffineMatrix&
operator=(const Matrix4x4 &m);
AffineMatrix&
operator=(const TransposedMatrix &m);
//
// Comparison operators
//
Logical
operator==(const AffineMatrix& m) const;
Logical
operator!=(const AffineMatrix& m) const;
//
// Index operators
//
Scalar&
operator()(size_t row,size_t column)
{
Check_Pointer(this); Warn(row>3); Warn(column>2);
return entries[(column<<2)+row];
}
const Scalar&
operator ()(size_t row,size_t column) const
{
Check_Pointer(this); Warn(row>3); Warn(column>2);
return entries[(column<<2)+row];
}
//
// Axis Manipulation functions
//
void
GetFromAxis(size_t index, Vector3D *v) const;
void
GetToAxis(size_t index, Vector3D *v) const;
AffineMatrix&
SetFromAxis(size_t index, const Vector3D &v);
AffineMatrix&
SetToAxis(size_t index, const Vector3D &v);
//
// Matrix Multiplication
//
AffineMatrix&
Multiply(
const AffineMatrix& m1,
const AffineMatrix& m2
);
AffineMatrix&
operator*=(const AffineMatrix& m)
{AffineMatrix temp(*this); return Multiply(temp,m);}
//
// Matrix Inversion
//
AffineMatrix&
Invert(const AffineMatrix& Source);
AffineMatrix&
Invert()
{AffineMatrix src(*this); return Invert(src);}
//
// Scaling, Rotation and Translation
//
AffineMatrix&
Multiply(const AffineMatrix &m,const Vector3D &v);
AffineMatrix&
operator*=(const Vector3D &v)
{AffineMatrix m(*this); return Multiply(m,v);}
AffineMatrix&
Multiply(const AffineMatrix &m,const Quaternion &q);
AffineMatrix&
operator*=(const Quaternion &q)
{AffineMatrix m(*this); return Multiply(m,q);}
AffineMatrix&
Multiply(const AffineMatrix &m,const Point3D &p);
AffineMatrix&
operator*=(const Point3D& p)
{AffineMatrix m(*this); return Multiply(m,p);}
//
// Miscellaneous Functions
//
Scalar
Determinant() const;
AffineMatrix&
Solve();
//
// Support functions
//
friend ostream&
operator <<(
ostream& stream,
const AffineMatrix& m
);
Logical
TestInstance() const;
static Logical
TestClass();
};
inline Point3D&
Point3D::operator=(const AffineMatrix& m)
{m.GetFromAxis(W_Axis,this); return *this;}
inline MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
AffineMatrix *output
)
{return stream->ReadBytes(output, sizeof(*output));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const AffineMatrix *input
)
{return stream->WriteBytes(input, sizeof(*input));}
#endif
+27
View File
@@ -0,0 +1,27 @@
//===========================================================================//
// File: affnmtrx.cc //
// Project: MUNGA Brick: Math Library //
// Contents: Implementation details for the Affine matrices //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/20/94 JMA Initial coding. //
// 12/01/94 JMA Made compatible with SGI CC //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
//###########################################################################
//###########################################################################
//
Logical
AffineMatrix::TestClass()
{
cout << "Starting AffineMatrix Test...\n";
Tell(" AffineMatrix::TestClass() stubbed out!\n");
return False;
}
+205
View File
@@ -0,0 +1,205 @@
//===========================================================================//
// File: angle.cc //
// Project: MUNGA Brick: Math Library //
// Contents: Implementation details for angle classes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/19/94 JMA Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(ANGLE_HPP)
#include <angle.hpp>
#endif
#if defined(USE_SIGNATURE)
int
Is_Signature_Bad(const volatile Radian *)
{
return False;
}
#endif
//
//#############################################################################
//#############################################################################
//
Scalar
Radian::Normalize(Scalar Value)
{
Scalar temp;
temp = fmod(Value,TWO_PI);
if (temp > PI) {
temp -= TWO_PI;
}
else if (temp < -PI) {
temp += TWO_PI;
}
return temp;
}
//
//#############################################################################
//#############################################################################
//
Radian&
Radian::Normalize()
{
Check(this);
angle = fmod(angle,TWO_PI);
if (angle > PI) {
angle -= TWO_PI;
}
else if (angle < -PI) {
angle += TWO_PI;
}
return *this;
}
//
//#############################################################################
//#############################################################################
//
Radian&
Radian::Lerp(const Radian &a,const Radian &b,Scalar t)
{
Scalar a1,a2;
Check_Pointer(this);
Check(&a);
Check(&b);
a1 = Radian::Normalize(a.angle);
a2 = Radian::Normalize(b.angle);
if (a2-a1 > PI) {
a2 -= TWO_PI;
}
else if (a2-a1 < -PI) {
a2 += TWO_PI;
}
angle = ::Lerp(a1, a2, t);
return *this;
}
//
//#############################################################################
//#############################################################################
//
ostream&
operator<<(
ostream& stream,
const Radian& radian
)
{
return stream << radian.angle << " rad";
}
//
//#############################################################################
//#############################################################################
//
Logical
Radian::TestInstance() const
{
return angle >= -100.0f && angle <= 100.0f;
}
#if defined(USE_SIGNATURE)
int
Is_Signature_Bad(const volatile Degree *)
{
return False;
}
#endif
//
//#############################################################################
//#############################################################################
//
ostream&
operator<<(
ostream& stream,
const Degree& degree
)
{
return stream << degree.angle << " deg";
}
//
//#############################################################################
//#############################################################################
//
Logical
Degree::TestInstance() const
{
return True;
}
#if defined(USE_SIGNATURE)
int
Is_Signature_Bad(const volatile SinCosPair *)
{
return False;
}
#endif
//
//#############################################################################
//#############################################################################
//
SinCosPair&
SinCosPair::operator=(const Radian &radian)
{
Check_Pointer(this);
Check(&radian);
cosine = cos(radian);
sine = sin(radian);
#if defined(__BCPLUSPLUS__)
cosine = cos(radian); // STUPID FUCKING BORLAND LIBRARY HACK!!!!!
#endif
Check(this);
return *this;
}
//
//#############################################################################
//#############################################################################
//
ostream&
operator<<(
ostream& stream,
const SinCosPair& pair
)
{
return stream << '{' << pair.cosine << ',' << pair.sine << '}';
}
//
//#############################################################################
//#############################################################################
//
Logical
SinCosPair::TestInstance() const
{
Scalar t = sine*sine + cosine*cosine;
if (!Close_Enough(t,1.0f,0.001f))
{
Dump(*this);
Dump(t);
return False;
}
return True;
}
#if defined(TEST_CLASS)
# include "angle.tcp"
#endif
+276
View File
@@ -0,0 +1,276 @@
//===========================================================================//
// File: angle.hh //
// Project: MUNGA Brick: Math Library //
// Contents: Interface specification for angle classes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/18/94 JMA Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(ANGLE_HPP)
# define ANGLE_HPP
# if !defined(SCALAR_HPP)
# include <scalar.hpp>
# endif
class Degree;
class SinCosPair;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Radian ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Radian
{
public:
Scalar
angle;
#if defined(USE_SIGNATURE)
friend int
Is_Signature_Bad(const volatile Radian *);
#endif
//
// Constructors
//
Radian()
{}
Radian(Scalar angle)
{this->angle = angle;}
//
// Assignment operators
//
Radian&
operator=(Scalar angle)
{
Check_Pointer(this);
this->angle = angle; return *this;
}
Radian&
operator=(const Radian &radian)
{
Check_Pointer(this); Check(&radian);
angle = radian.angle; return *this;
}
Radian&
operator=(const Degree &degree);
Radian&
operator=(const SinCosPair &pair);
//
// Casting
//
operator Scalar() const
{Check(this); return angle;}
//
// These comparator functions are not designed to make exact comparisons
// of Scalaring point numbers, but rather to compare them to within some
// specified error threshold
//
Logical
operator!() const
{Check(this); return Small_Enough(angle);}
Logical
operator==(const Radian &r) const
{Check(this); Check(&r); return Close_Enough(angle,r.angle);}
Logical
operator==(float r) const
{Check(this); return Close_Enough(angle,r);}
Logical
operator!=(const Radian &r) const
{Check(this); Check(&r); return !Close_Enough(angle,r.angle);}
Logical
operator!=(float r) const
{Check(this); return !Close_Enough(angle,r);}
//
// Math operators
//
Radian&
Negate(Scalar r)
{Check_Pointer(this); angle = -r; return *this;}
Radian&
Add(Scalar r1,Scalar r2)
{Check_Pointer(this); angle = r1 + r2; return *this;}
Radian&
operator+=(Scalar r)
{Check(this); angle += r; return *this;}
Radian&
Subtract(Scalar r1,Scalar r2)
{Check_Pointer(this); angle = r1 - r2; return *this;}
Radian&
operator-=(Scalar r)
{Check(this); angle -= r; return *this;}
Radian&
Multiply(Scalar r1,Scalar r2)
{Check_Pointer(this); angle = r1 * r2; return *this;}
Radian&
operator*=(Scalar r)
{Check(this); angle *= r; return *this;}
Radian&
Divide(Scalar r1,Scalar r2)
{
Check_Pointer(this); Verify(!Small_Enough(r2));
angle = r1 / r2; return *this;
}
Radian&
operator/=(Scalar r)
{Check(this); Verify(!Small_Enough(r)); angle /= r; return *this;}
//
// Template support
//
Radian&
Lerp(
const Radian &a,
const Radian &b,
Scalar t
);
//
// Support functions
//
static Scalar
Normalize(Scalar Value);
Radian&
Normalize();
friend ostream&
operator<<(
ostream& stream,
const Radian &radian
);
Logical
TestInstance() const;
static Logical
TestClass();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Degree ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Degree
{
public:
Scalar
angle;
#if defined(USE_SIGNATURE)
friend int
Is_Signature_Bad(const volatile Degree *);
#endif
//
// constructors
//
Degree()
{}
Degree(Scalar angle)
{this->angle = angle;}
//
// Assignment operators
//
Degree&
operator=(const Degree &degree)
{Check(this); Check(&degree); angle = degree.angle; return *this;}
Degree&
operator=(Scalar angle)
{Check(this); this->angle = angle; return *this;}
Degree&
operator=(const Radian &radian)
{
Check(this); Check(&radian);
angle = radian.angle * DEG_PER_RAD; return *this;
}
//
// Support functions
//
friend ostream&
operator<<(
ostream& stream,
const Degree &angle
);
Logical
TestInstance() const;
static Logical
TestClass();
};
inline Radian&
Radian::operator=(const Degree& degree)
{
Check_Pointer(this); Check(&degree);
angle = degree.angle * RAD_PER_DEG; return *this;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SinCosPair ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SinCosPair
{
public:
Scalar
sine,
cosine;
#if defined(USE_SIGNATURE)
friend int
Is_Signature_Bad(const volatile SinCosPair *);
#endif
//
// Constructors
//
SinCosPair()
{}
SinCosPair(Scalar sin, Scalar cos)
{Check_Pointer(this); sine = sin; cosine = cos; Check(this);}
//
// Assignment operators
//
SinCosPair&
operator=(const SinCosPair &pair)
{
Check_Pointer(this); Check(&pair);
sine = pair.sine; cosine = pair.cosine; return *this;
}
SinCosPair&
operator=(const Radian &radian);
//
// Support functions
//
friend ostream&
operator<<(
ostream& stream,
const SinCosPair &pair
);
Logical
TestInstance() const;
static Logical
TestClass();
};
inline Radian&
Radian::operator=(const SinCosPair& pair)
{
Check_Pointer(this); Check(&pair);
angle = Arctan(pair.sine,pair.cosine); return *this;
}
#endif
+170
View File
@@ -0,0 +1,170 @@
//===========================================================================//
// File: angle.tst //
// Project: MUNGA Brick: Math Library //
// Contents: Tests for angle classes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/19/94 JMA Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
//#############################################################################
//#############################################################################
//
Logical
Radian::TestClass()
{
cout << "Starting Radian Test...\n";
const Radian a(1.25f);
Radian
b,c;
Test(a);
c = 0.0f;
Test(!c);
Test(Normalize(3.1f) == 3.1f);
Test(Normalize(-3.1f) == -3.1f);
Scalar f = Normalize(PI+PI_OVER_2);
Test(Close_Enough(f,PI_OVER_2 - PI));
f = Normalize(-PI-PI_OVER_2);
Test(Close_Enough(f,PI - PI_OVER_2));
c = a;
Test(c == a);
Test(c.angle == a);
Test(c == a.angle);
b.Negate(c);
Test(b == -c.angle);
#if 0
b = -c;
d.Add(b,c);
Test(d == b.angle + c.angle);
Test(a+b == a.angle + b.angle);
Test(a+c == a.angle + c.angle);
Test(a+1.25f == a.angle+1.25f);
Test(1.25f+c == 1.25f+c.angle);
c = 1.5f;
d.Subtract(c,a);
Test(d == c.angle - a.angle);
Test(c-a == c.angle - a.angle);
Test(c-1.25f == c.angle - 1.25f);
Test(1.5f-a == 1.5f - a.angle);
Test(c-b == c.angle - b.angle);
c = 2.5f;
d.Multiply(a,c);
Test(d == a.angle * c.angle);
Test(a*c == a.angle * c.angle);
Test(1.25f*c == 1.25f * c.angle);
Test(a*2.5f == a.angle * 2.5f);
Test(a*b == a.angle * b.angle);
c = 2.0f;
d.Divide(a,c);
Test(d == a.angle / c.angle);
Test(a/c == a.angle / c.angle);
Test(1.25f/c == 1.25f / c.angle);
Test(a/2.0f == a.angle / 2.0f);
Test(a/b == a.angle / b.angle);
b = a;
b += c;
b.Normalize();
Test(b == 3.25f - TWO_PI);
b += 2.0f;
b.Normalize();
Test(b == 5.25f - TWO_PI);
b -= c;
b.Normalize();
Test(b == 3.25f - TWO_PI);
b -= 2.0f;
b.Normalize();
Test(b == 1.25f);
b *= c;
b.Normalize();
Test(b == 1.25f*2.0f);
b *= 2.0f;
b.Normalize();
Test(b == 1.25f*2.0f*2.0f - TWO_PI);
b = a*c;
b.Normalize();
Test(b == 1.25f*2.0f);
b /= 2.0f;
b.Normalize();
Test(b == 1.25f);
b = -3.0f*PI_OVER_4;
c = 3.0f*PI_OVER_4;
Test(Lerp(b,c,0.25f) < b);
Test(Normalize(Lerp(b,c,0.75f)) > c);
#endif
return True;
}
//
//#############################################################################
//#############################################################################
//
Logical
Degree::TestClass()
{
cout << "Starting Degree test...\n";
const Degree a(DEG_PER_RAD);
Degree
b,c;
Radian
r(1.0f),s;
s = a;
Test(r == s);
b = r;
s = b;
Test(r == s);
c = DEG_PER_RAD;
s = c;
Test(r == s);
b = c;
s = b;
Test(r == s);
return True;
}
//
//#############################################################################
//#############################################################################
//
Logical
SinCosPair::TestClass()
{
cout << "Starting SinCos test...\n";
Radian
s,r(PI_OVER_2);
SinCosPair a;
a = r;
Test(Close_Enough(a.sine,1.0f));
Test(Small_Enough(a.cosine));
s = a;
Test(s == r);
return True;
}
+97
View File
@@ -0,0 +1,97 @@
//===========================================================================//
// File: app.tst //
// Project: MUNGA Brick: Application //
// Contents: Interface specification for Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/12/94 ECH Added event utilities. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include "app.thp"
#include "entity.thp"
#include "controls.thp"
TestApplication::TestApplication(ResourceFile *resource_file):
Application(resource_file, (ApplicationID)0)
{
}
TestApplication::~TestApplication()
{
}
void
TestApplication::Initialize()
{
Check(this);
//
//--------------------------------------------------------------------------
// Create the network manager
//--------------------------------------------------------------------------
//
application = this;
networkManager = MakeNetworkManager();
Register_Object(networkManager);
#if 0
//
//--------------------------------------------------------------------------
// Create the registry, load static object streams
//--------------------------------------------------------------------------
//
registry = MakeRegistry();
Register_Object(registry);
registry->LoadStaticObjectStreamResource();
//
//--------------------------------------------------------------------------
// Create the controls manager
//--------------------------------------------------------------------------
//
controlsManager = MakeControlsManager();
Register_Object(controlsManager);
//
//--------------------------------------------------------------------------
// Create the intercom manager
//--------------------------------------------------------------------------
//
intercomManager = MakeIntercomManager();
Register_Object(intercomManager);
#endif
//
//--------------------------------------------------------------------------
// Add background tasks
//--------------------------------------------------------------------------
//
ApplicationTask *application_task;
application_task = new RoutePacketTask;
Register_Object(application_task);
backgroundTasks->AddTask(application_task);
application_task = new ProcessEventTask;
Register_Object(application_task);
backgroundTasks->AddTask(application_task);
application_task = new CompleteCyclesTask;
Register_Object(application_task);
backgroundTasks->AddTask(application_task);
}
void
TestApplication::Terminate()
{
Check(this);
application = this;
networkManager->Shutdown();
Application::Terminate();
}
+45
View File
@@ -0,0 +1,45 @@
//===========================================================================//
// File: tstapp.hh //
// Project: MUNGA Brick: Application //
// Contents: Interface specification for Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/06/95 ECH Added event utilities. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(APP_THP)
# define APP_THP
# if !defined(APP_HPP)
# include "app.hpp"
# endif
# if !defined(RENDERER_THP)
# include "renderer.thp"
# endif
# if !defined(VIDREND_HPP)
# include "vidrend.hpp"
# endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TestApplication ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class TestApplication:
public Application
{
public:
TestApplication(ResourceFile *resource_file);
~TestApplication();
void
Initialize();
void
Terminate();
};
#endif
+131
View File
@@ -0,0 +1,131 @@
#include <munga.hpp>
#pragma hdrstop
#if !defined(APPMGR_HPP)
# include <appmgr.hpp>
#endif
ApplicationManager::ApplicationManager(Scalar frame_rate):
Node(ApplicationManagerClassID),
runningApplications(this)
{
frameRate = frame_rate;
frameDuration = 1.0f/frameRate;
Check_Fpu();
}
ApplicationManager::~ApplicationManager()
{
}
void
ApplicationManager::StartApplication(Application *new_app)
{
Check(this);
Check(new_app);
runningApplications.Add(new_app);
application = new_app;
new_app->Initialize();
}
//
//#############################################################################
// RunMissions
//#############################################################################
//
void
ApplicationManager::RunMissions()
{
Check(this);
SChainIteratorOf<Application*> current_application(runningApplications);
Start_Of_Frame:
current_application.First();
Time end_of_frame = Now();
end_of_frame += frameDuration;
#if defined(LAB_ONLY)
int bad_count = 0;
#endif
if (frameDuration > 0.1f)
{
Fail("frameDuration has grown!\n");
}
//
//----------------------------------
// Run all relevant foreground loops
//----------------------------------
//
while ((application = current_application.ReadAndNext()) != NULL)
{
Check(application);
if (!application->ExecuteForeground(end_of_frame, frameDuration))
{
if (!application->Shutdown())
{
application->Terminate();
Unregister_Object(application);
delete application;
}
}
}
//
//-----------------------------------------------------------------------
// Run all relevant background loops until it is time for the next frame.
// If no applications remain, exit the whole loop
//-----------------------------------------------------------------------
//
current_application.First();
application = current_application.GetCurrent();
if (!application)
{
return;
}
//
//------------------------------------------------------------------
// Give each application a chance to do at least one background task
//------------------------------------------------------------------
//
Background_Loop:
do {
Check(application);
application->ExecuteBackgroundTask();
//
// Move to the next application
//
current_application.Next();
application = current_application.GetCurrent();
} while (application);
//
//---------------------------------------------------------------------
// If time remains before the next frame is due, do another pass on the
// background tasks
//---------------------------------------------------------------------
//
Time t2 = Now();
if (t2 < end_of_frame)
{
current_application.First();
application = current_application.GetCurrent();
#if defined(LAB_ONLY)
if (end_of_frame - t2 > 0.1f)
{
DEBUG_STREAM << t2 << ',' << end_of_frame << endl;
if (++bad_count == 1000)
{
Fail("End-of-frame cannot be correctly calculated!");
}
}
#endif
goto Background_Loop;
}
goto Start_Of_Frame;
}
+33
View File
@@ -0,0 +1,33 @@
#if !defined(APPMGR_HPP)
# define APPMGR_HPP
# if !defined(APP_HPP)
# include <app.hpp>
# endif
class ApplicationManager:
public Node
{
public:
ApplicationManager(Scalar frame_rate);
~ApplicationManager();
void
StartApplication(Application *new_app);
void
RunMissions();
Scalar
GetFrameRate()
{Check(this); return frameRate;}
protected:
Scalar
frameDuration,
frameRate;
SChainOf<Application*>
runningApplications;
};
#endif
+87
View File
@@ -0,0 +1,87 @@
//===========================================================================//
// File: cnslmsgs.cpp //
// Project: MUNGA Brick: //
// Contents: Console messages //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/02/95 ECH Initial coding. //
// 06/03/95 GAH Added corresponding Macintosh message defintions. //
// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(APPMSG_HPP)
# include <appmsg.hpp>
#endif
#if !defined(APP_HPP)
# include <app.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~~
Application__StateQueryMessage::Application__StateQueryMessage(
HostID requesting_host
):
NetworkClient::Message(
Application::StateQueryMessageID,
sizeof(Application__StateQueryMessage)
)
{
requestingHost = requesting_host;
}
//~~~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~~
Application__RunMissionMessage::Application__RunMissionMessage():
NetworkClient::Message(
Application::RunMissionMessageID,
sizeof(Application__RunMissionMessage)
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
Application__StopMissionMessage::Application__StopMissionMessage(Enumeration exit_code):
NetworkClient::Message(
Application::StopMissionMessageID,
sizeof(Application__StopMissionMessage)
)
{
exitCode = exit_code;
}
//~~~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
Application__AbortMissionMessage::Application__AbortMissionMessage(Enumeration exit_code):
NetworkClient::Message(
Application::AbortMissionMessageID,
sizeof(Application__AbortMissionMessage)
)
{
exitCode = exit_code;
}
//~~~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~
Application__SuspendMissionMessage::Application__SuspendMissionMessage():
NetworkClient::Message(
Application::SuspendMissionMessageID,
sizeof(Application__SuspendMissionMessage)
)
{
}
//~~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
Application__ResumeMissionMessage::Application__ResumeMissionMessage():
NetworkClient::Message(
Application::ResumeMissionMessageID,
sizeof(Application__ResumeMissionMessage)
)
{
}
//==============================================================================
+246
View File
@@ -0,0 +1,246 @@
//===========================================================================//
// File: cnslmsgs.hpp //
// Project: MUNGA Brick: //
// Contents: Console messages //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/02/95 ECH Initial coding. //
// 06/03/95 GAH Added corresponding Macintosh message defintions. //
// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(APPMSG_HPP)
# define APPMSG_HPP
#ifdef MAC
#pragma once
#endif
#ifdef MAC
#include "NetworkEndpoint.h"
#include "Participant.h"
#else
#include <network.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Application IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
enum ApplicationMessageID
{
StateQueryMessageID = NetworkEndpoint::NextMessageID,
CheckLoadMessageID,
RunMissionMessageID,
StopMissionMessageID,
KeyCommandMessageID,
SuspendMissionMessageID,
ResumeMissionMessageID,
LoadMissionMessageID,
AbortMissionMessageID,
ApplicationNextMessageID
};
enum ApplicationID
{
RPL4,
BTL4,
BTW4
};
typedef ApplicationID ApplicationID;
enum ExitCodeID
{
NullExitCodeID = 0,
AbortExitCodeID,
RunRedPlanetExitCodeID,
RunBattleTechExitCodeID,
RunSinglePlayerRedPlanetExitCodeID,
RunSinglePlayerBattleTechExitCodeID,
DisplayMainTestPatternExitCodeID,
DisplayAuxTestPatternExitCodeID,
TestPlasmaDisplayExitCodeID,
ResetRIOExitCodeID,
RunAudioTestExitCodeID,
RunNortonDiskDoctorExitCodeID,
CheckDiskUsageExitCodeID,
RefreshRedPlanetExitCodeID,
RefreshBattleTechExitCodeID,
ChangeScreenModeExitCodeID,
SoftwareResetExitCodeID,
ClearCrashlogExitCodeID,
KillSpoolFileExitCodeID,
RunRedPlanetCameraExitCodeID,
RunBattleTechCameraExitCodeID,
RunRedPlanetMissionReviewExitCodeID,
RunBattleTechMissionReviewExitCodeID
};
typedef ExitCodeID ExitCodeID;
#endif
//~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__StateQueryMessage:
public NetworkEndpoint::Message
{
public:
Application__StateQueryMessage(HostID requesting_host);
long
GetRequestingHostID()
{return requestingHost.value();}
private:
HostID
requestingHost;
};
#pragma options align=reset
#else
class Application__StateQueryMessage:
public NetworkClient::Message
{
public:
Application__StateQueryMessage(HostID requesting_host);
HostID
GetRequestingHostID()
{return requestingHost;}
private:
HostID
requestingHost;
};
#endif
//~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__RunMissionMessage:
public NetworkEndpoint::Message
{
public:
Application__RunMissionMessage();
};
#pragma options align=reset
#else
class Application__RunMissionMessage:
public NetworkClient::Message
{
public:
Application__RunMissionMessage();
};
#endif
//~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__StopMissionMessage:
public NetworkEndpoint::Message
{
public:
Application__StopMissionMessage(ExitCodeID exit_code);
ExitCodeID
GetExitCodeID()
{return((ExitCodeID) exitCode.value());}
private:
LEDWORD
exitCode;
};
#pragma options align=reset
#else
class Application__StopMissionMessage:
public NetworkClient::Message
{
public:
Application__StopMissionMessage(Enumeration exit_code);
Enumeration
GetExitCode()
{return(exitCode);}
private:
Enumeration
exitCode;
};
#endif
//~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__AbortMissionMessage:
public NetworkEndpoint::Message
{
public:
Application__AbortMissionMessage(ExitCodeID exit_code);
ExitCodeID
GetExitCode()
{return((ExitCodeID) exitCode.value());}
private:
LEDWORD
exitCode;
};
#pragma options align=reset
#else
class Application__AbortMissionMessage:
public NetworkClient::Message
{
public:
Application__AbortMissionMessage(Enumeration exit_code);
Enumeration
GetExitCode()
{return(exitCode);}
private:
Enumeration
exitCode;
};
#endif
//~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__SuspendMissionMessage:
public NetworkEndpoint::Message
{
public:
Application__SuspendMissionMessage();
};
#pragma options align=reset
#else
class Application__SuspendMissionMessage:
public NetworkClient::Message
{
public:
Application__SuspendMissionMessage();
};
#endif
//~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class Application__ResumeMissionMessage:
public NetworkEndpoint::Message
{
public:
Application__ResumeMissionMessage();
};
#pragma options align=reset
#else
class Application__ResumeMissionMessage:
public NetworkClient::Message
{
public:
Application__ResumeMissionMessage();
};
#endif
#endif
+206
View File
@@ -0,0 +1,206 @@
//===========================================================================//
// File: apptask.cpp //
// Project: MUNGA Brick: Application //
// Contents: Interface specification for Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/24/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(APPTASK_HPP)
# include <apptask.hpp>
#endif
#if !defined(RENDERER_HPP)
# include <renderer.hpp>
#endif
#if !defined(AUDREND_HPP)
# include <audrend.hpp>
#endif
#if !defined(APP_HPP)
# include <app.hpp>
#endif
#if !defined(NTTMGR_HPP)
# include <nttmgr.hpp>
#endif
#if !defined(GAUGEREND_HPP)
# include <gaugrend.hpp>
#endif
#if defined(TRACE_COMPLETE_CYCLES)
BitTrace Complete_Cycles("Complete Cycles");
#endif
#if defined(TRACE_DEATH_ROW)
BitTrace Death_Row("Death Row");
#endif
//#############################################################################
//########################### ApplicationTask ###########################
//#############################################################################
ApplicationTask::ApplicationTask(ClassID class_ID):
Component(class_ID)
{
}
ApplicationTask::~ApplicationTask()
{
}
//#############################################################################
//########################### BackgroundTasks ###########################
//#############################################################################
BackgroundTasks::BackgroundTasks():
taskSocket(NULL)
{
taskIterator = new SChainIteratorOf<ApplicationTask*>(&taskSocket);
Register_Object(taskIterator);
}
BackgroundTasks::~BackgroundTasks()
{
Check(taskIterator);
taskIterator->DeletePlugs();
Unregister_Object(taskIterator);
delete taskIterator;
}
Logical
BackgroundTasks::TestInstance() const
{
Component::TestInstance();
Check(&taskSocket);
Check(taskIterator);
return True;
}
void
BackgroundTasks::AddTask(ApplicationTask *task)
{
Check(this);
Check(task);
taskSocket.Add(task);
}
void
BackgroundTasks::Execute()
{
Check(this);
Check(taskIterator);
if (taskIterator->GetCurrent() == NULL)
{
taskIterator->First();
}
ApplicationTask *task = taskIterator->GetCurrent();
Check(task);
task->Execute();
taskIterator->Next();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
NetworkManagerTask::Execute()
{
Check(this);
Check(application);
Check(application->GetNetworkManager());
application->GetNetworkManager()->ExecuteBackground();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
RoutePacketTask::Execute()
{
Check(this);
Check(application);
Check(application->GetNetworkManager());
application->GetNetworkManager()->RoutePacket();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
ProcessEventTask::Execute()
{
Check(this);
Check(application);
application->ProcessOneEvent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
AudioRendererTask::Execute()
{
Check(this);
Check(application);
if (application->GetAudioRenderer() != NULL)
{
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->ExecuteBackground();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
GaugeRendererTask::Execute()
{
Check(this);
Check(application);
if (application->GetGaugeRenderer() != NULL)
{
Check(application->GetGaugeRenderer());
application->GetGaugeRenderer()->ExecuteBackground();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
CompleteCyclesTask::Execute()
{
SET_COMPLETE_CYCLES();
Check(this);
Check(application);
Check(application->GetRendererManager());
application->GetRendererManager()->CompleteCycles();
CLEAR_COMPLETE_CYCLES();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
FryDeathRowTask::Execute()
{
SET_DEATH_ROW();
Check(this);
Check(application);
Check(application->GetEntityManager());
application->GetEntityManager()->FryDeathRow();
CLEAR_DEATH_ROW();
}
+179
View File
@@ -0,0 +1,179 @@
//===========================================================================//
// File: apptask.hpp //
// Project: MUNGA Brick: Application //
// Contents: Interface specification for Application //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/24/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(APPTASK_HPP)
# define APPTASK_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(CMPNNT_HPP)
# include <cmpnnt.hpp>
# endif
# if !defined(SCHAIN_HPP)
# include <schain.hpp>
# endif
# if defined(TRACE_COMPLETE_CYCLES)
extern BitTrace Complete_Cycles;
# define SET_COMPLETE_CYCLES() Complete_Cycles.Set()
# define CLEAR_COMPLETE_CYCLES() Complete_Cycles.Clear()
# else
# define SET_COMPLETE_CYCLES()
# define CLEAR_COMPLETE_CYCLES()
# endif
# if defined(TRACE_DEATH_ROW)
extern BitTrace Death_Row;
# define SET_DEATH_ROW() Death_Row.Set()
# define CLEAR_DEATH_ROW() Death_Row.Clear()
# else
# define SET_DEATH_ROW()
# define CLEAR_DEATH_ROW()
# endif
//##########################################################################
//####################### ApplicationTask ############################
//##########################################################################
class ApplicationTask:
public Component
{
public:
ApplicationTask(ClassID class_ID = ApplicationTaskClassID);
~ApplicationTask();
};
//##########################################################################
//####################### BackgroundTasks ############################
//##########################################################################
class BackgroundTasks:
public Component
{
public:
BackgroundTasks();
~BackgroundTasks();
Logical
TestInstance() const;
void
AddTask(ApplicationTask *task);
void
Execute();
private:
SChainOf<ApplicationTask*>
taskSocket;
SChainIteratorOf<ApplicationTask*>
*taskIterator;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class NetworkManagerTask:
public ApplicationTask
{
public:
NetworkManagerTask() {}
~NetworkManagerTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class RoutePacketTask:
public ApplicationTask
{
public:
RoutePacketTask() {}
~RoutePacketTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ProcessEventTask:
public ApplicationTask
{
public:
ProcessEventTask() {}
~ProcessEventTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioRendererTask:
public ApplicationTask
{
public:
AudioRendererTask() {}
~AudioRendererTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class GaugeRendererTask:
public ApplicationTask
{
public:
GaugeRendererTask() {}
~GaugeRendererTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CompleteCyclesTask:
public ApplicationTask
{
public:
CompleteCyclesTask() {}
~CompleteCyclesTask() {}
void
Execute();
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class FryDeathRowTask:
public ApplicationTask
{
public:
FryDeathRowTask() {}
~FryDeathRowTask() {}
void
Execute();
};
#endif
+751
View File
@@ -0,0 +1,751 @@
//===========================================================================//
// File: audcmp.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDCMP_HPP)
# define AUDCMP_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
# if !defined(AUDLOC_HPP)
# include <audloc.hpp>
# endif
# if !defined(AVERAGE_HPP)
# include <average.hpp>
# endif
# if !defined(AUDTIME_HPP)
# include <audtime.hpp>
# endif
//##########################################################################
//######################## AudioMessageWatcher #######################
//##########################################################################
class AudioMessageWatcher:
public AudioComponent
{
public:
//
//-----------------------------------------------------------------------
// Constructor, Destructor
//-----------------------------------------------------------------------
//
AudioMessageWatcher(
PlugStream *stream,
Entity *entity
);
~AudioMessageWatcher();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//-----------------------------------------------------------------------
// MessageTapScanCallback
//-----------------------------------------------------------------------
//
void
MessageTapScanCallback(
Receiver::Message *message,
Receiver *receiver
);
//
//-----------------------------------------------------------------------
// Controller methods
//-----------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//-----------------------------------------------------------------------
// Controller methods
//-----------------------------------------------------------------------
//
virtual Logical
DoesMessageMatch(Receiver::Message*)
{return True;}
//
//-----------------------------------------------------------------------
// Private Data
//-----------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlID controlID;
AudioControlValue controlValue;
MessageTap *messageTap;
#if DEBUG_LEVEL>0
Receiver *verifyReceiver;
Receiver::MessageID verifyMessageID;
#endif
};
//##########################################################################
//############### AudioControlsButtonMessageWatcher ##################
//##########################################################################
class AudioControlsButtonMessageWatcher:
public AudioMessageWatcher
{
public:
//
//-----------------------------------------------------------------------
// Constructor, Destructor
//-----------------------------------------------------------------------
//
AudioControlsButtonMessageWatcher(
PlugStream *stream,
Entity *entity
);
~AudioControlsButtonMessageWatcher();
private:
//
//-----------------------------------------------------------------------
// Controller methods
//-----------------------------------------------------------------------
//
Logical
DoesMessageMatch(Receiver::Message*);
};
//##########################################################################
//######################### AudioControlSend #########################
//##########################################################################
class AudioControlSend:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioControlSend(
PlugStream *stream,
Entity *entity
);
~AudioControlSend();
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
};
//##########################################################################
//####################### AudioControlSplitter #######################
//##########################################################################
class AudioControlSplitter:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioControlSplitter(
PlugStream *stream,
Entity *entity
);
void
AudioControlSplitterX(Entity *entity);
~AudioControlSplitter();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SChainOf<AudioComponent*> audioComponentSocket;
};
//##########################################################################
//####################### AudioControlMixer ##########################
//##########################################################################
#define AUDIO_CONTROL_MIXER_MAX_CONTROLS (4)
class AudioControlMixer:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioControlMixer(
PlugStream *stream,
Entity *entity
);
void
AudioControlMixerX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID first_input_control_ID,
AudioControlID last_input_control_ID,
AudioControlID output_control_ID
);
~AudioControlMixer();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlValue
controlValueArray[AUDIO_CONTROL_MIXER_MAX_CONTROLS];
AudioControlID
firstInputControlID;
int
numberOfInputs;
AudioControlID
outputControlID;
};
//##########################################################################
//###################### AudioControlMultiplier ######################
//##########################################################################
#define AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS (4)
class AudioControlMultiplier:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioControlMultiplier(
PlugStream *stream,
Entity *entity
);
void
AudioControlMultiplierX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID first_input_control_ID,
AudioControlID last_input_control_ID,
AudioControlID output_control_ID
);
~AudioControlMultiplier();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlValue
controlValueArray[AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS];
AudioControlID
firstInputControlID;
int
numberOfInputs;
AudioControlID
outputControlID;
};
//##########################################################################
//######################## AudioControlSmoother ######################
//##########################################################################
class AudioControlSmoother:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioControlSmoother(
PlugStream *stream,
Entity *entity
);
void
AudioControlSmootherX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID control_ID
);
~AudioControlSmoother();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AverageOf<AudioControlValue>
audioControlAverage;
AudioControlID
controlID;
};
//##########################################################################
//####################### AudioResourceSelector ######################
//##########################################################################
class AudioResourceIndex;
class AudioResourceSelector:
public AudioComponent
{
public:
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
AudioResourceSelector(
PlugStream *stream,
Entity *entity
);
void
AudioResourceSelectorX(
AudioSource *audio_source,
Entity *entity,
AudioResourceIndex *audio_resource_index,
AudioControlID control_ID,
AudioControlValue min_control_value,
AudioControlValue max_control_value,
Logical dump_value
);
~AudioResourceSelector();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioSourceSocket;
AudioResourceIndex
*audioResourceIndex;
AudioControlID
controlID;
AudioControlValue
minControlValue,
maxControlValue;
Logical
dumpValue;
};
//##########################################################################
//######################## AudioSampleAndHold ########################
//##########################################################################
class AudioSampleAndHold:
public AudioComponent
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioSampleAndHold(
PlugStream *stream,
Entity *entity
);
void
AudioSampleAndHoldX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID audio_control_ID,
const AudioTime &sample_duration,
Scalar min_value,
Scalar max_value
);
~AudioSampleAndHold();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Execute
//--------------------------------------------------------------------
//
void
Execute();
//
//-----------------------------------------------------------------------
// Controller methods
//-----------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//-----------------------------------------------------------------------
// Private methods
//-----------------------------------------------------------------------
//
void
SampleAndHold();
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlID
audioControlID;
AudioControlValue
minValue,
maxValue,
currentValue;
AudioTime
nextSampleTime,
sampleDuration;
};
//##########################################################################
//############################# AudioLFO #############################
//##########################################################################
enum AudioLFOWaveForm
{
SinusoidalAudioLFOWaveForm = 0,
TriangularAudioLFOWaveForm = 1
};
inline MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
AudioLFOWaveForm *ptr
)
{return stream->ReadBytes(ptr, sizeof(*ptr));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const AudioLFOWaveForm *ptr
)
{return stream->WriteBytes(ptr, sizeof(*ptr));}
class AudioLFO:
public AudioComponent
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioLFO(
PlugStream *stream,
Entity *entity
);
void
AudioLFOX(
AudioComponent *audio_component,
Entity *entity,
AudioControlID audio_control_ID,
AudioLFOWaveForm wave_form,
Scalar the_period,
AudioControlValue min_value,
AudioControlValue max_value,
Logical dump_value
);
~AudioLFO();
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//--------------------------------------------------------------------
// Execute
//--------------------------------------------------------------------
//
void
Execute();
//
//-----------------------------------------------------------------------
// Controller methods
//-----------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
//
//-----------------------------------------------------------------------
// Private methods
//-----------------------------------------------------------------------
//
void
Generate();
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlID
audioControlID;
AudioLFOWaveForm
waveForm;
AudioControlValue
minValue,
maxValue;
AudioTime
period;
AudioTime
startTime;
Logical
dumpValue;
};
#endif
+203
View File
@@ -0,0 +1,203 @@
//===========================================================================//
// File: audent.cpp //
// Project: MUNGA Brick: Model Manager //
// Contents: Implementation details of audio entity class //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/20/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDENT_HPP)
# include <audent.hpp>
#endif
#if !defined(JMOVER_HPP)
# include <jmover.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(HOSTMGR_HPP)
#include <hostmgr.hpp>
#endif
//#############################################################################
//########################### AudioEntity ###############################
//#############################################################################
//#############################################################################
// Shared Data Support
//
Derivation
AudioEntity::ClassDerivations(
Explosion::ClassDerivations,
"AudioEntity"
);
AudioEntity::SharedData
AudioEntity::DefaultData(
AudioEntity::ClassDerivations,
AudioEntity::MessageHandlers,
AudioEntity::AttributeIndex,
AudioEntity::StateCount,
(Entity::MakeHandler)AudioEntity::Make
);
//
//#############################################################################
//#############################################################################
//
AudioEntity::AudioEntity(
AudioEntity::MakeMessage *creation_message,
AudioEntity::SharedData &shared_data
):
Explosion(creation_message, shared_data),
parentEntitySocket(NULL)
{
Check_Pointer(this);
Check_Pointer(creation_message);
//
// Get the parent entity
//
Entity *parent_entity;
parent_entity =
application->GetHostManager()->GetEntityPointer(
creation_message->parentEntityID
);
if (parent_entity != NULL)
{
parentEntitySocket.Add(parent_entity);
parentEntitySegment = creation_message->parentEntitySegment;
}
else
{
parentEntitySegment = NULL;
}
//
// Set simulation
//
SetPerformance(&AudioEntity::AudioEntitySimulation);
SetValidFlag();
}
//
//#############################################################################
//#############################################################################
//
AudioEntity::~AudioEntity()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioEntity::TestInstance() const
{
if (!IsDerivedFrom(ClassDerivations))
{
return False;
}
Check(&parentEntitySocket);
if (parentEntitySegment != NULL)
{
Check(parentEntitySegment);
}
return True;
}
//
//#############################################################################
//#############################################################################
//
AudioEntity*
AudioEntity::Make(AudioEntity::MakeMessage *creation_message)
{
return new AudioEntity(creation_message);
}
//
//#############################################################################
//#############################################################################
//
void
AudioEntity::AudioEntitySimulation(Scalar time_slice)
{
Check(this);
//
// Get the parent entity, if it does not exist, condemn to death row
//
Entity *parent_entity;
if ((parent_entity = parentEntitySocket.GetCurrent()) == NULL)
{
CondemnToDeathRow();
return;
}
//
// Get the orign of the parent entities segment
//
JointedMover *jointed_mover;
Verify(parent_entity->IsDerivedFrom(JointedMover::ClassDerivations));
jointed_mover = Cast_Object(JointedMover*, parent_entity);
Check(jointed_mover);
Check(parentEntitySegment);
jointed_mover->GetSegmentToWorld(
*parentEntitySegment,
&localToWorld
);
//
// Set the origin of this entity
//
localOrigin = localToWorld;
updateOrigin = localOrigin;
//
// Call inherited simulation
//
Explosion::ExplosionSimulation(time_slice);
}
//#############################################################################
//##################### AudioEntity__MakeMessage ########################
//#############################################################################
AudioEntity__MakeMessage::AudioEntity__MakeMessage(
ResourceDescription::ResourceID resource_ID,
Entity *parent_entity,
EntitySegment *parent_entity_segment
):
Explosion::MakeMessage(
AudioEntity::MakeMessageID,
sizeof(AudioEntity__MakeMessage),
RegisteredClass::AudioEntityClassID,
EntityID::Null,
resource_ID,
Entity::HermitInstance|Entity::DynamicFlag,
parent_entity->localOrigin,
parent_entity->GetEntityID(),
EntityID::Null
),
parentEntityID(parent_entity->GetEntityID()),
parentEntitySegment(parent_entity_segment)
{
}
+118
View File
@@ -0,0 +1,118 @@
//===========================================================================//
// File: audent.hpp //
// Project: MUNGA Brick: Model Manager //
// Contents: Interface specification for audio entity class //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/20/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDENT_HPP)
# define AUDENT_HPP
# if !defined(EXPLODE_HPP)
# include <explode.hpp>
# endif
# if !defined(SEGMENT_HPP)
# include <segment.hpp>
# endif
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
//##########################################################################
//########################## AudioEntity #############################
//##########################################################################
class AudioEntity__MakeMessage;
class AudioEntity:
public Explosion
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public types
//
public:
typedef AudioEntity__MakeMessage
MakeMessage;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
AudioEntity(
MakeMessage *creation_message,
SharedData &shared_data = DefaultData
);
~AudioEntity();
static AudioEntity*
Make(MakeMessage *creation_message);
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
typedef void
(AudioEntity::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
AudioEntitySimulation(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation
ClassDerivations;
static SharedData
DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
SlotOf<Entity*>
parentEntitySocket;
EntitySegment
*parentEntitySegment;
};
//##########################################################################
//#################### AudioEntity__MakeMessage ######################
//##########################################################################
class AudioEntity__MakeMessage:
public Explosion::MakeMessage
{
public:
AudioEntity__MakeMessage(
ResourceDescription::ResourceID resource_ID,
Entity *parent_entity,
EntitySegment *parent_entity_segment
);
EntityID
parentEntityID;
EntitySegment
*parentEntitySegment;
};
#endif
+488
View File
@@ -0,0 +1,488 @@
//===========================================================================//
// File: audio.hh //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDIO_HPP)
# include <audio.hpp>
#endif
#if !defined(AUDREND_HPP)
# include <audrend.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Audio Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const Scalar AudioDoubleTriggerCutoff = 0.2f;
const AudioControlValue MaxAudioVolume = 1.0f;
const AudioControlValue MinAudioVolume = 0.0f;
const AudioControlValue LowAudioVolumeThreshold = 0.3f;
const AudioControlValue MaxAudioBrightness = 1.0f;
const AudioControlValue MinAudioBrightness = 0.0f;
const AudioControlValue MaxAudioAttack = 1.0f;
const AudioControlValue MinAudioAttack = 0.0f;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioHead::AudioHead():
headEntitySocket(NULL)
{
//
// Start frame counter at 0, other counts should be at
// NullAudioFrameCount
//
audioFrameCount = 0;
//
// Other audio parameters
//
clippingRadius = 100.0f;
distanceBetweenEars = 1.0f;
amplitudeRollOffExponent = 1.0f;
amplitudeRollOffKnee = 10.0f,
amplitudeRollOffDistanceScale = 0.05f;
highFrequencyRollOffExponent = 0.5f;
highFrequencyRollOffKnee = 10.0f;
highFrequencyRollOffDistanceScale = 0.05f;
reverbToDryRatio = 0.1f;
audioSoundSpeed = 345.0f;
audioDopplerConstant = 20.0f;
sourceCompressionExponent = 0.5f;
sourceCompressionScale = 0.5f;
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
AudioHead::~AudioHead()
{
Check(this);
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioHead::TestInstance() const
{
Check(&headEntitySocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::LinkToEntity(Entity *entity)
{
Check(this);
Check(entity);
//
// Remove existing entity, add new one
//
if (headEntitySocket.GetCurrent() != NULL)
{
headEntitySocket.Remove();
}
headEntitySocket.Add(entity);
#if 0
//
// Make the new clipping sphere
//
clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition);
#endif
}
//
//#############################################################################
//#############################################################################
//
LinearMatrix
AudioHead::GetEarToWorld()
{
Check(this);
Entity *entity = headEntitySocket.GetCurrent();
Check(entity);
return entity->localToWorld;
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::Execute()
{
Check(this);
//
// Increment frame counter
//
audioFrameCount++;
Verify(audioFrameCount < LONG_MAX);
#if 0
//
// Get the entity
//
Entity *entity = headEntitySocket.GetCurrent();
Check(entity);
//
// Make the new clipping sphere
//
clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition);
#endif
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::DefineClippingSphere(Scalar radius)
{
Check(this);
clippingRadius = radius;
#if 0
//
// Get entity position
//
Entity *entity;
Point3D position(0.0f, 0.0f, 0.0f);
if ((entity = headEntitySocket.GetCurrent()) != NULL)
{
Check(entity);
position = entity->localOrigin.linearPosition;
}
//
// Make the new clipping sphere
//
clippingSphere.SetCurrentOrigin(position);
clippingSphere.SetReferenceRadius(radius);
#endif
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioHead::IsPointClipped(const Point3D &point)
{
Check(this);
Entity
*entity;
Vector3D
difference;
entity = headEntitySocket.GetCurrent();
Check(entity);
difference.Subtract(entity->localOrigin.linearPosition, point);
return difference.LengthSquared() > clippingRadius*clippingRadius;
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::ControlDopplerEffect(
Scalar doppler_constant,
Scalar sound_speed
)
{
Check(this);
audioDopplerConstant = doppler_constant;
audioSoundSpeed = sound_speed;
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::ControlAmplitudeRollOff(
Scalar exponent,
Scalar amplitude_rolloff_knee,
Scalar distance_scale
)
{
Check(this);
amplitudeRollOffExponent = exponent;
amplitudeRollOffKnee = amplitude_rolloff_knee;
amplitudeRollOffDistanceScale = distance_scale;
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::ControlHighFrequencyRollOff(
Scalar exponent,
Scalar high_frequency_rolloff_knee,
Scalar distance_scale
)
{
Check(this);
highFrequencyRollOffExponent = exponent;
highFrequencyRollOffKnee = high_frequency_rolloff_knee;
highFrequencyRollOffDistanceScale = distance_scale;
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::ControlSourceCompression(
Scalar exponent,
Scalar scale
)
{
Check(this);
sourceCompressionExponent = exponent;
sourceCompressionScale = scale;
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioHead::SetPositionalCulling(Logical)
{
Check(this);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
const Receiver::HandlerEntry
AudioComponent::MessageHandlerEntries[]=
{
{
AudioComponent::ReceiveControlMessageID,
"ReceiveControl",
(AudioComponent::Handler)&AudioComponent::ReceiveControlMessageHandler
}
};
AudioComponent::MessageHandlerSet
AudioComponent::MessageHandlers(
ELEMENTS(AudioComponent::MessageHandlerEntries),
AudioComponent::MessageHandlerEntries,
Component::MessageHandlers
);
//
//#############################################################################
//#############################################################################
//
Derivation
AudioComponent::ClassDerivations(
Component::ClassDerivations,
"AudioComponent"
);
AudioComponent::SharedData
AudioComponent::DefaultData(
AudioComponent::ClassDerivations,
AudioComponent::MessageHandlers
);
//
//#############################################################################
//#############################################################################
//
AudioComponent::AudioComponent(
PlugStream *stream,
SharedData &shared_data
):
Component(stream, shared_data),
audioWatcherSocket(NULL)
{
nextExecuteWatcherFrame = NullAudioFrameCount;
}
//
//#############################################################################
//#############################################################################
//
AudioComponent::~AudioComponent()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioComponent::TestInstance() const
{
if (!IsDerivedFrom(ClassDerivations))
{
return False;
}
Check(&audioWatcherSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioComponent::ExecuteWatchers()
{
Check(this);
//
// Execute watchers if this is the next watcher frame
//
AudioFrameCount
audio_frame_count;
Check(application);
Check(application->GetAudioRenderer());
audio_frame_count = application->GetAudioRenderer()->GetAudioFrameCount();
if (nextExecuteWatcherFrame <= audio_frame_count)
{
nextExecuteWatcherFrame = audio_frame_count + DefaultAudioFrameDelay;
//
// Execute watchers
//
ChainIteratorOf<Component*>
iterator(&audioWatcherSocket);
Component
*component;
while ((component = iterator.ReadAndNext()) != NULL)
{
Check(component);
component->Execute();
}
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioComponent::Execute()
{
Check(this);
ExecuteWatchers();
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioComponent::ReceiveControl(
AudioControlID,
AudioControlValue
)
{
Fail("AudioComponent::ReceiveControl - Should never reach here");
}
//
//#############################################################################
//#############################################################################
//
void
AudioComponent::PostReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
ReceiveControlMessage
message(control_ID, control_value);
Check(application);
// ECH 1/26/96 - application->Post(HighEventPriority, this, &message);
application->Post(DefaultEventPriority, this, &message);
Check_Fpu();
}
//
//#############################################################################
//#############################################################################
//
void
AudioComponent::ReceiveControlMessageHandler(ReceiveControlMessage *message)
{
Check(this);
Check(message);
ReceiveControl(message->controlID, message->controlValue);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~~~~
AudioComponent__ReceiveControlMessage::AudioComponent__ReceiveControlMessage(
AudioControlID control_ID,
AudioControlValue control_value
):
Receiver::Message(
AudioComponent::ReceiveControlMessageID,
sizeof(AudioComponent__ReceiveControlMessage)
)
{
controlID = control_ID;
controlValue = control_value;
}
+687
View File
@@ -0,0 +1,687 @@
//===========================================================================//
// File: audio.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDIO_HPP)
# define AUDIO_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(ENTITY_HPP)
# include <entity.hpp>
# endif
# if !defined(SPHERE_HPP)
# include <sphere.hpp>
# endif
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
# if !defined(TABLE_HPP)
# include <table.hpp>
# endif
class PlugStream;
//
//--------------------------------------------------------------------------
// Support types
//--------------------------------------------------------------------------
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef long AudioTick;
typedef long AudioDivisionsPerBeat;
typedef long AudioTempo;
typedef long AudioFrameCount;
const AudioFrameCount NullAudioFrameCount = -1;
const AudioFrameCount DefaultAudioFrameDelay = 2;
extern const Scalar AudioDoubleTriggerCutoff;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Resource types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef int AudioResourceID;
typedef int AudioVoiceCount;
typedef Scalar AudioRadiationProfile;
typedef Scalar AudioPitchCents;
enum AudioRenderType
{
TransientAudioRenderType = 0,
SustainedAudioRenderType = 1
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
enum AudioRepresentation
{
InternalAudioRepresentation = 0,
ExternalAudioRepresentation = 1
};
#define AUDIO_SOURCE_PRIORITY_COUNT (5)
enum AudioSourcePriority
{
MinAudioSourcePriority = 0,
LowAudioSourcePriority = 1,
MedAudioSourcePriority = 2,
HighAudioSourcePriority = 3,
MaxAudioSourcePriority = 4
};
enum AudioSourceState
{
StoppedAudioSourceState = 0,
DormantAudioSourceState = 1,
RunningAudioSourceState = 2,
SuspendedAudioSourceState = 3
};
enum AudioSourceMixPresence
{
ManualAudioSourceMixPresence = 0,
MaxAudioSourceMixPresence = 1,
HighAudioSourceMixPresence = 2,
MedAudioSourceMixPresence = 3,
LowAudioSourceMixPresence = 4,
MinAudioSourceMixPresence = 5
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
enum AudioControlID
{
NullAudioControlID = 0,
StartAudioControlID,
StopAudioControlID,
VolumeAudioControlID,
PitchAudioControlID,
BrightnessAudioControlID,
AttackVolumeAudioControlID,
AttackTimeAudioControlID,
NoteAudioControlID,
IdleAudioControlID,
DurationAudioControlID,
FlushMessagesAudioControlID,
TempoAudioControlID,
AudioControlIDCount
};
typedef Scalar AudioControlValue;
extern const AudioControlValue MaxAudioVolume;
extern const AudioControlValue MinAudioVolume;
extern const AudioControlValue LowAudioVolumeThreshold;
extern const AudioControlValue MaxAudioBrightness;
extern const AudioControlValue MinAudioBrightness;
extern const AudioControlValue MaxAudioAttack;
extern const AudioControlValue MinAudioAttack;
#if 0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere ~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioClippingSphere SIGNATURED
{
public:
AudioClippingSphere();
~AudioClippingSphere();
void
SetReferenceRadius(Scalar radius);
void
SetCurrentOrigin(const Point3D &origin);
void
SetCurrentScale(Scalar scale);
Logical
Contains(const Point3D &point) const;
private:
Scalar
referenceRadius;
Sphere
currentSphere;
};
//~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere inlines ~~~~~~~~~~~~~~~~~~~~~~
inline AudioClippingSphere::AudioClippingSphere():
referenceRadius(100.0f),
currentSphere(0.0f, 0.0f, 0.0f, 100.0f)
{
}
inline AudioClippingSphere::~AudioClippingSphere()
{
}
inline void
AudioClippingSphere::SetReferenceRadius(Scalar radius)
{
Check(this);
referenceRadius = radius;
currentSphere.radius = radius;
}
inline void
AudioClippingSphere::SetCurrentOrigin(const Point3D &origin)
{
Check(this);
currentSphere.center = origin;
}
inline void
AudioClippingSphere::SetCurrentScale(Scalar scale)
{
Check(this);
currentSphere.radius = scale * referenceRadius;
}
inline Logical
AudioClippingSphere::Contains(const Point3D &point) const
{
Check(this);
return currentSphere.Contains(point);
}
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioSource;
class AudioHead SIGNATURED
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioHead();
~AudioHead();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// Get current frame of audio simulation
//-----------------------------------------------------------------------
//
AudioFrameCount
GetAudioFrameCount()
{return audioFrameCount;}
//
//-----------------------------------------------------------------------
// Sets the location and orientation of the head
//-----------------------------------------------------------------------
//
virtual void
LinkToEntity(Entity *entity);
Entity*
GetHeadEntity();
//
//-----------------------------------------------------------------------
// Get the ear to world linear matrix
//-----------------------------------------------------------------------
//
virtual LinearMatrix
GetEarToWorld();
//
//-----------------------------------------------------------------------
// Execute
//-----------------------------------------------------------------------
//
virtual void
Execute();
//
//-----------------------------------------------------------------------
// Sets the distance between ears. Expressed in meters.
//-----------------------------------------------------------------------
//
void
SetDistanceBetweenEars(Scalar distance)
{distanceBetweenEars = distance;}
Scalar
GetDistanceBetweenEars()
{return distanceBetweenEars;}
//
//-----------------------------------------------------------------------
// Controls Doppler effects
//-----------------------------------------------------------------------
//
void
ControlDopplerEffect(
Scalar doppler_constant,
Scalar sound_speed
);
Scalar
GetAudioSoundSpeed()
{return audioSoundSpeed;}
AudioPitchCents
GetAudioDopplerConstant()
{return audioDopplerConstant;}
//
//-----------------------------------------------------------------------
// Reverb scaling
//-----------------------------------------------------------------------
//
void
SetReverbToDryRatio(Scalar ratio)
{reverbToDryRatio = ratio;}
Scalar
GetReverbToDryRatio()
{return reverbToDryRatio;}
// HACK
void
SetGlobalReverbScale(Scalar global_reverb_scale)
{globalReverbScale = global_reverb_scale;}
Scalar
GetGlobalReverbScale()
{return globalReverbScale;}
//
//-----------------------------------------------------------------------
// Controls the attenuation of an audio source with respect to its
// distance from the head.
//-----------------------------------------------------------------------
//
void
ControlAmplitudeRollOff(
Scalar exponent,
Scalar amplitude_rolloff_knee,
Scalar distance_scale
);
Scalar
GetAmplitudeRollOffExponent()
{return amplitudeRollOffExponent;}
Scalar
GetAmplitudeRollOffKnee()
{return amplitudeRollOffKnee;}
Scalar
GetAmplitudeRollOffDistanceScale()
{return amplitudeRollOffDistanceScale;}
//
//-----------------------------------------------------------------------
// Controls the attenuation of the high frequencies
// of an audio source with respect to its distance from
// the head.
//-----------------------------------------------------------------------
//
void
ControlHighFrequencyRollOff(
Scalar exponent,
Scalar high_frequency_rolloff_knee,
Scalar distance_scale
);
Scalar
GetHighFrequencyRollOffExponent()
{return highFrequencyRollOffExponent;}
Scalar
GetHighFrequencyRollOffKnee()
{return highFrequencyRollOffKnee;}
Scalar
GetHighFrequencyRollOffDistanceScale()
{return highFrequencyRollOffDistanceScale;}
//
//-----------------------------------------------------------------------
// Controls source compression
//-----------------------------------------------------------------------
//
void
ControlSourceCompression(
Scalar exponent,
Scalar scale
);
Scalar
GetSourceCompressionExponent()
{return sourceCompressionExponent;}
Scalar
GetSourceCompressionScale()
{return sourceCompressionScale;}
//
//-----------------------------------------------------------------------
// Defines the audio clipping sphere
//-----------------------------------------------------------------------
//
void
DefineClippingSphere(Scalar radius);
Logical
IsPointClipped(const Point3D &point);
Scalar
GetClippingRadius()
{return clippingRadius;}
//
//-----------------------------------------------------------------------
// ITD Difference
//-----------------------------------------------------------------------
//
void
SetITDDifference(Scalar itd_difference)
{itdDifference = itd_difference;}
Scalar
GetITDDifference()
{return itdDifference;}
//
//-----------------------------------------------------------------------
// The SetPositionalCulling method allows the rendering process to
// not play audio locations whose positions are masked by other
// audio sources. This has found to be useful for controlling
// audio when resources are limited, but must be
// selectable globally or on a per audio effect basis.
//-----------------------------------------------------------------------
//
void
SetPositionalCulling(Logical turn_on);
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
AudioFrameCount
audioFrameCount;
SlotOf<Entity*>
headEntitySocket;
Scalar
clippingRadius;
Scalar
distanceBetweenEars;
Scalar
amplitudeRollOffExponent,
amplitudeRollOffKnee,
amplitudeRollOffDistanceScale;
Scalar
highFrequencyRollOffExponent,
highFrequencyRollOffKnee,
highFrequencyRollOffDistanceScale;
Scalar
reverbToDryRatio;
Scalar
audioSoundSpeed;
Scalar
audioDopplerConstant;
Scalar
sourceCompressionExponent,
sourceCompressionScale;
Scalar
itdDifference;
Scalar
globalReverbScale;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline Entity*
AudioHead::GetHeadEntity()
{
Check(this);
return headEntitySocket.GetCurrent();
}
//##########################################################################
//######################### AudioComponent ###########################
//##########################################################################
class AudioComponent__ReceiveControlMessage;
class AudioComponent:
public Component
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
AudioComponent(
PlugStream *stream,
SharedData &shared_data = DefaultData
);
~AudioComponent();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Component Methods
//
public:
void
AddWatcher(Component *component);
void
ExecuteWatchers();
void
Execute();
virtual void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
void
PostReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum {
ReceiveControlMessageID = Component::NextMessageID,
NextMessageID
};
typedef AudioComponent__ReceiveControlMessage
ReceiveControlMessage;
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
void
ReceiveControlMessageHandler(
ReceiveControlMessage *message
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation
ClassDerivations;
static SharedData
DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
AudioFrameCount
nextExecuteWatcherFrame;
ChainOf<Component*>
audioWatcherSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent inlines ~~~~~~~~~~~~~~~~~~~~~~~~
inline void
AudioComponent::AddWatcher(Component *component)
{
Check(component);
Check(&audioWatcherSocket);
audioWatcherSocket.Add(component);
}
//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~
class AudioComponent__ReceiveControlMessage:
public Receiver::Message
{
friend class AudioComponent;
public:
AudioComponent__ReceiveControlMessage(
AudioControlID control_ID,
AudioControlValue control_value
);
private:
AudioControlID
controlID;
AudioControlValue
controlValue;
};
//~~~~~~~~~~~~~~~~~~~~~~~~ Resource type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioRenderType *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioRenderType *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioRepresentation *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioRepresentation *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourceState *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourceState *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourcePriority *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourcePriority *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioSourceMixPresence *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioSourceMixPresence *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
AudioControlID *output
)
{
return stream->ReadBytes(output, sizeof(*output));
}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const AudioControlID *input
)
{
return stream->WriteBytes(input, sizeof(*input));
}
#endif
+531
View File
@@ -0,0 +1,531 @@
//===========================================================================//
// File: audloc.cpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDLOC_HPP)
# include <audloc.hpp>
#endif
#if !defined(OBJSTRM_HPP)
#include <objstrm.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioLocation::AudioLocation(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
vectorToSource(0.0f, 0.0f, 0.0f),
locationOffset(0.0f, 0.0f, 0.0f)
{
AudioFrameCount next_update_delay;
Scalar clipping_scale;
MemoryStream_Read(stream, &locationOffset);
MemoryStream_Read(stream, &next_update_delay);
MemoryStream_Read(stream, &clipping_scale);
AudioLocationX(entity, next_update_delay, clipping_scale);
}
//
//#############################################################################
//#############################################################################
//
AudioLocation::~AudioLocation()
{
}
//
//#############################################################################
//#############################################################################
//
void
AudioLocation::AudioLocationX(
Entity *entity,
AudioFrameCount next_update_delay,
Scalar clipping_scale
)
{
Check(entity);
linkedEntity = entity;
entity->AddAudioComponent(this);
clippingScale = clipping_scale;
isHeadSource = False;
distanceToSource = 1.0f;
dopplerCents = 0;
#if 0
angleOffOrientation = 0.0f;
#endif
azimuthOfSource = 0.0f;
distanceVolumeScale = 1.0f;
highFreqCutoffScale = 1.0f;
#if 0
reverbVolumeScale = 0.0f;
#endif
nextUpdateDelay = next_update_delay;
nextUpdateFrame = NullAudioFrameCount;
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioLocation::TestInstance() const
{
Component::TestInstance();
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioLocation::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Point3D, location_offset);
//
// Read update delay
//
CString update_delay_string("update_delay");
AudioFrameCount update_delay = DefaultAudioFrameDelay;
if (name_list->FindData(update_delay_string) != NULL)
{
Check_Pointer(name_list->FindData(update_delay_string));
Convert_From_Ascii(
(const char *)name_list->FindData(update_delay_string),
&update_delay
);
}
MemoryStream_Write(stream, &update_delay);
//
// Read culling scale
//
CString clipping_scale_string("clipping_scale");
Scalar clipping_scale = 1.0f;
if (name_list->FindData(clipping_scale_string) != NULL)
{
Check_Pointer(name_list->FindData(clipping_scale_string));
Convert_From_Ascii(
(const char *)name_list->FindData(clipping_scale_string),
&clipping_scale
);
}
MemoryStream_Write(stream, &clipping_scale);
}
//
//#############################################################################
//#############################################################################
//
void
AudioLocation::ReceiveControl(
AudioControlID,
AudioControlValue
)
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioLocation::IsAudioLocationClipped(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
//
// HACK - This is a rough approximation in that it does not
// take into account the offset of the location from the
// center of the entity. But, this is more efficient and is OK
// as long as the clipping sphere does not exclude the location
// unnaturally
//
Entity
*head_entity;
Vector3D
difference;
Scalar
scaled_radius;
head_entity = audio_head->GetHeadEntity();
Check(head_entity);
Check(linkedEntity);
difference.Subtract(
head_entity->localOrigin.linearPosition,
linkedEntity->localOrigin.linearPosition
);
scaled_radius = audio_head->GetClippingRadius() * clippingScale;
return difference.LengthSquared() > scaled_radius * scaled_radius;
}
//
//#############################################################################
//#############################################################################
//
void
AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
//
//--------------------------------------------------------------------------
// Get head and source entity
//--------------------------------------------------------------------------
//
Entity *source_entity = GetLinkedEntity();
Entity *head_entity = audio_head->GetHeadEntity();
Check(source_entity);
Check(head_entity);
//
//--------------------------------------------------------------------------
// Catch case of head == source at origin
//--------------------------------------------------------------------------
//
if (
head_entity == source_entity &&
locationOffset == Vector3D::Identity
)
{
isHeadSource = True;
vectorToSource = Vector3D::Identity;
distanceToSource = 0.0f;
dopplerCents = 0;
#if 0
angleOffOrientation = 0.0f;
#endif
azimuthOfSource = 0.0f;
distanceVolumeScale = 1.0f;
highFreqCutoffScale = 1.0f;
#if 0
reverbVolumeScale = audio_head->GetReverbToDryRatio();
#endif
return;
}
isHeadSource = False;
//
//--------------------------------------------------------------------------
// Get the ear to world linear matrix
//--------------------------------------------------------------------------
//
LinearMatrix ear_to_world = audio_head->GetEarToWorld();
//
//--------------------------------------------------------------------------
// Calculate vector to source with respect to local coordinate system
// of the ears
//--------------------------------------------------------------------------
//
{
//
// Get the source location offset from the entity position in
// world coordinates
//
Vector3D world_location_offset;
Vector3D world_source_location;
world_location_offset.Multiply(
locationOffset,
source_entity->localToWorld
);
Check(&world_location_offset);
world_source_location.Add(
source_entity->localOrigin.linearPosition,
world_location_offset
);
Check(&world_source_location);
//
// Get the vector from the ear to the source, note that the vector
// is not calculated by the ears offset but from the entities location
//
Vector3D world_ear_to_source_vector;
world_ear_to_source_vector.Subtract(
world_source_location,
head_entity->localOrigin.linearPosition
);
Check(&world_ear_to_source_vector);
//
// Transform the vector into ear coordinates
//
vectorToSource.MultiplyByInverse(
world_ear_to_source_vector,
ear_to_world
);
Check(&vectorToSource);
}
//
//--------------------------------------------------------------------------
// Calculate distance to source
//--------------------------------------------------------------------------
//
distanceToSource = vectorToSource.Length();
//
//--------------------------------------------------------------------------
// Calculate normal to source
//--------------------------------------------------------------------------
//
Vector3D normal_to_source(0.0f, 0.0f, -1.0f);
if (!Small_Enough(distanceToSource))
{
normal_to_source.Normalize(vectorToSource);
Check(&normal_to_source);
}
#if 0
//
//--------------------------------------------------------------------------
// Calculate angle between the orientation of the head and source
//--------------------------------------------------------------------------
//
if (Small_Enough(distanceToSource))
{
angleOffOrientation = 0.0f;
}
else
{
UnitVector direction;
Scalar cosine;
ear_to_world.GetToAxis(Z_Axis, &direction);
Check(&direction);
Check(&normal_to_source);
cosine = normal_to_source * direction;
Clamp(cosine, -1.0f, 1.0f);
angleOffOrientation = Arccos(cosine);
angleOffOrientation.Normalize();
}
Verify(
angleOffOrientation <= 180.0f*RAD_PER_DEG &&
angleOffOrientation >= -180.0f*RAD_PER_DEG
);
#endif
//
//--------------------------------------------------------------------------
// Calculate azimuth
//--------------------------------------------------------------------------
//
if (Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z))
{
azimuthOfSource = 0.0f;
}
else
{
Verify(!(Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z)));
azimuthOfSource = Arctan(vectorToSource.x, vectorToSource.z);
}
Verify(
azimuthOfSource <= 180.0f*RAD_PER_DEG &&
azimuthOfSource >= -180.0f*RAD_PER_DEG
);
//
//--------------------------------------------------------------------------
// Calculate distance volume scaling
// Apply clipping scale to rolloff distance scale, thereby giving this
// audio location a specifc rolloff characteristic
//--------------------------------------------------------------------------
//
if (distanceToSource > audio_head->GetAmplitudeRollOffKnee())
{
//
// y = 1 / 1 + (K(x - knee))^exp
//
Verify(!Small_Enough(clippingScale));
const Scalar temp =
(audio_head->GetAmplitudeRollOffDistanceScale() / clippingScale) *
(distanceToSource - audio_head->GetAmplitudeRollOffKnee());
const Scalar temp2 =
1.0f + pow(temp, audio_head->GetAmplitudeRollOffExponent());
Verify(!Small_Enough(temp2));
distanceVolumeScale = 1.0f / temp2;
}
else
{
distanceVolumeScale = 1.0f;
}
Verify(distanceVolumeScale >= 0.0f && distanceVolumeScale <= 1.0f);
//
//--------------------------------------------------------------------------
// Calculate high frequency cutoff scaling
// Apply clipping scale to high frequency rolloff distance scale, thereby
// giving this audio location a specifc rolloff characteristic
//--------------------------------------------------------------------------
//
if (distanceToSource > audio_head->GetHighFrequencyRollOffKnee())
{
//
// y = 1 / 1 + (K(x - knee))^exp
//
Verify(!Small_Enough(clippingScale));
const Scalar temp =
(audio_head->GetHighFrequencyRollOffDistanceScale() / clippingScale) *
(distanceToSource - audio_head->GetHighFrequencyRollOffKnee());
const Scalar temp2 =
1.0f + pow(temp, audio_head->GetHighFrequencyRollOffExponent());
Verify(!Small_Enough(temp2));
highFreqCutoffScale = 1.0f / temp2;
}
else
{
highFreqCutoffScale = 1.0f;
}
Verify(highFreqCutoffScale >= 0.0f && highFreqCutoffScale <= 1.0f);
#if 0
//
//--------------------------------------------------------------------------
// Calculate reverb volume scaling
//--------------------------------------------------------------------------
//
if (distanceToSource > audio_head->GetAmplitudeRollOffKnee())
{
const Scalar temp =
distanceToSource - audio_head->GetAmplitudeRollOffKnee() + 1.0f;
reverbVolumeScale =
audio_head->GetReverbToDryRatio() *
pow(temp, audio_head->GetAmplitudeRollOffExponent());
if (reverbVolumeScale > 1.0f)
reverbVolumeScale = 1.0f;
}
else
{
reverbVolumeScale = audio_head->GetReverbToDryRatio();
}
Verify(reverbVolumeScale >= 0.0f && reverbVolumeScale <= 1.0f);
#endif
//
//--------------------------------------------------------------------------
// Calculate relative velocity of source
//--------------------------------------------------------------------------
//
Vector3D relative_velocity_temp;
Vector3D relative_velocity;
relative_velocity_temp.Subtract(
source_entity->GetWorldLinearVelocity(),
head_entity->GetWorldLinearVelocity()
);
Check(&relative_velocity_temp);
relative_velocity.MultiplyByInverse(
relative_velocity_temp,
head_entity->localToWorld
);
Check(&relative_velocity);
//
//--------------------------------------------------------------------------
// Calculate doppler shift in cents
// cents = (c / (c - v)) / ScaleRatio
//--------------------------------------------------------------------------
//
if (!Small_Enough(distanceToSource))
{
AudioPitchCents
cents;
Scalar speed_of_source =
normal_to_source * relative_velocity;
const Scalar ear_radius =
audio_head->GetDistanceBetweenEars() * 0.5f;
if (distanceToSource < ear_radius)
{
Verify(!Small_Enough(ear_radius));
speed_of_source *= (distanceToSource / ear_radius);
}
if (CalculateDoppler(audio_head, speed_of_source, &cents))
{
dopplerCents = cents;
}
}
else
{
dopplerCents = 0;
}
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioLocation::CalculateDoppler(
AudioHead *audio_head,
Scalar speed,
AudioPitchCents *result
)
{
Check(this);
Check(audio_head);
Check_Pointer(result);
Scalar speed_of_sound = audio_head->GetAudioSoundSpeed();
Clamp(speed, -speed_of_sound, speed_of_sound);
if (!Small_Enough(speed_of_sound - speed))
{
*result = audio_head->GetAudioDopplerConstant() *
( 1 - speed_of_sound / (speed_of_sound - speed) );
return True;
}
return False;
}
+221
View File
@@ -0,0 +1,221 @@
//===========================================================================//
// File: audloc.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDLOC_HPP)
# define AUDLOC_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
//##########################################################################
//######################## AudioLocation #############################
//##########################################################################
class AudioLocation:
public AudioComponent
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
AudioLocation(
PlugStream *stream,
Entity *entity
);
void
AudioLocationX(
Entity *entity,
AudioFrameCount next_update_delay,
Scalar clipping_scale
);
~AudioLocation();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Resource Building
//
public:
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Component Support
//
public:
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Audio Location Support
//
public:
//
//-----------------------------------------------------------------------
// GetLinkedEntity
//-----------------------------------------------------------------------
//
Entity*
GetLinkedEntity();
//
//-----------------------------------------------------------------------
// IsAudioLocationClipped
//-----------------------------------------------------------------------
//
Logical
IsAudioLocationClipped(AudioHead *audio_head);
//
//-----------------------------------------------------------------------
// UpdateSpatialModel
//-----------------------------------------------------------------------
//
void
UpdateSpatialModel(AudioHead *audio_head);
//
//-----------------------------------------------------------------------
// Access to localization results
//-----------------------------------------------------------------------
//
Logical
IsHeadSource()
{return isHeadSource;}
Scalar
GetDistanceToSource()
{return distanceToSource;}
Scalar
GetDistanceToSourceListenerPlane();
Radian
GetAzimuthOfSource()
{return azimuthOfSource;}
Scalar
GetDistanceVolumeScale()
{return distanceVolumeScale;}
Scalar
GetHighFreqCutoffScale()
{return highFreqCutoffScale;}
AudioPitchCents
GetDopplerCents()
{return dopplerCents;}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Protected Implementations
//
protected:
virtual void
UpdateSpatialModelImplementation(AudioHead *audio_head);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Methods
//
private:
Logical
CalculateDoppler(
AudioHead *audio_head,
Scalar speed,
AudioPitchCents *result
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
Entity
*linkedEntity;
Point3D
locationOffset;
Scalar
clippingScale;
Logical
isHeadSource;
Vector3D
vectorToSource;
Scalar
distanceToSource;
#if 0
Radian
angleOffOrientation;
#endif
Radian
azimuthOfSource;
Scalar
distanceVolumeScale;
Scalar
highFreqCutoffScale;
#if 0
Scalar
reverbVolumeScale;
#endif
AudioPitchCents
dopplerCents;
AudioFrameCount
nextUpdateDelay;
AudioFrameCount
nextUpdateFrame;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation inlines ~~~~~~~~~~~~~~~~~~~~~~~~
inline Entity*
AudioLocation::GetLinkedEntity()
{
Check(this);
return linkedEntity;
}
inline Scalar
AudioLocation::GetDistanceToSourceListenerPlane()
{
Check(this);
Vector3D
vector_to_source_listener_plane(
vectorToSource.x,
0.0f,
vectorToSource.z
);
return vector_to_source_listener_plane.Length();
}
inline void
AudioLocation::UpdateSpatialModel(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
if (nextUpdateFrame <= audio_head->GetAudioFrameCount())
{
nextUpdateFrame = audio_head->GetAudioFrameCount() + nextUpdateDelay;
UpdateSpatialModelImplementation(audio_head);
}
}
#endif
+480
View File
@@ -0,0 +1,480 @@
//===========================================================================//
// File: audio.hh //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDLVL_HPP)
# include <audlvl.hpp>
#endif
#if !defined(OBJSTRM_HPP)
#include <objstrm.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(AUDREND_HPP)
#include <audrend.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioLevelOfDetail::AudioLevelOfDetail(PlugStream *stream):
Plug(stream)
{
#if 0
amplitudeRadiationProfile = 0.0f;
filterRadiationProfile = 0.0f;
#endif
//
// Read fields
//
MemoryStream_Read(stream, &voiceCount);
MemoryStream_Read(stream, &audioRenderType);
//
// Read suspend seconds and calculate suspendDelay
//
Scalar
suspend_delay_seconds;
MemoryStream_Read(stream, &suspend_delay_seconds);
Check(application);
Check(application->GetAudioRenderer());
suspendDelay = suspend_delay_seconds *
application->GetAudioRenderer()->GetCalibrationRate() + 0.5f;
}
//
//#############################################################################
//#############################################################################
//
void
AudioLevelOfDetail::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
Plug::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioVoiceCount, voice_count);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, render_type);
//
// Store suspend delay
//
CString suspend_delay_string("suspend_delay");
Scalar suspend_delay_seconds = 0.33f; // HACK - should come from somewhere else
if (name_list->FindData(suspend_delay_string) != NULL)
{
Check_Pointer(name_list->FindData(suspend_delay_string));
Convert_From_Ascii(
(const char *)name_list->FindData(suspend_delay_string),
&suspend_delay_seconds
);
}
MemoryStream_Write(stream, &suspend_delay_seconds);
}
//
//#############################################################################
//#############################################################################
//
AudioLevelOfDetail::~AudioLevelOfDetail()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioLevelOfDetail::TestInstance() const
{
Plug::TestInstance();
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioResource::AudioResource(PlugStream *stream):
Node(stream),
audioLevelOfDetailSocket(NULL, True)
{
//
// Read the table
//
CollectionSize i, number_of_entries;
MemoryStream_Read(stream, &number_of_entries);
for (i = 0; i < number_of_entries; i++)
{
Scalar distance;
AudioLevelOfDetail *audio_level_of_detail;
MemoryStream_Read(stream, &distance);
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_level_of_detail);
Check(audio_level_of_detail);
audioLevelOfDetailSocket.AddValue(audio_level_of_detail, distance);
}
//
// Verify that there is at least one entry and the first one is at 0.0f
//
#if DEBUG_LEVEL>0
{
TableIteratorOf<AudioLevelOfDetail*, Scalar> iterator(&audioLevelOfDetailSocket);
Check(&iterator);
Verify(iterator.GetSize() > 0);
Verify(iterator.GetCurrent() != NULL);
Verify(iterator.GetValue() == 0.0f);
}
#endif
//
// Select the first entry
//
TableIteratorOf<AudioLevelOfDetail*, Scalar> iterator(&audioLevelOfDetailSocket);
audioLevelOfDetail = iterator.GetCurrent();
Check(audioLevelOfDetail);
}
//
//#############################################################################
//#############################################################################
//
void
AudioResource::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
Node::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Count number of entries
//
int number_of_entries = 0;
NameList::Entry *entry;
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_level_of_detail"))
number_of_entries++;
entry = entry->GetNextEntry();
}
//
// Store entries
//
MemoryStream_Write(stream, &number_of_entries);
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_level_of_detail"))
{
CString object_string;
Scalar distance;
ObjectID object_ID;
Check_Pointer(entry->GetChar());
object_string = entry->GetChar();
Check_Pointer(object_string.GetNthToken(0));
Convert_From_Ascii(object_string.GetNthToken(0), &distance);
MemoryStream_Write(stream, &distance);
Check(stream);
Check_Pointer(object_string.GetNthToken(1));
object_ID = stream->FindObjectID(object_string.GetNthToken(1));
Verify(object_ID != NullObjectID);
MemoryStream_Write(stream, &object_ID);
}
entry = entry->GetNextEntry();
}
}
//
//#############################################################################
//#############################################################################
//
AudioResource::~AudioResource()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioResource::TestInstance() const
{
Node::TestInstance();
Check(&audioLevelOfDetailSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioResource::SetDistance(Scalar distance)
{
Check(this);
Verify(distance >= 0.0f);
//
// Goto the last entry
//
TableIteratorOf<AudioLevelOfDetail*, Scalar>
iterator(&audioLevelOfDetailSocket);
Check(&iterator);
iterator.Last();
//
// While the distance is less than the distance of the entry
//
while (distance < iterator.GetValue())
{
iterator.Previous();
}
audioLevelOfDetail = iterator.GetCurrent();
Check(audioLevelOfDetail);
//
// Verify that the distance is greater than this entry, and less than
// the next
//
#if DEBUG_LEVEL>0
Verify(distance >= iterator.GetValue());
iterator.Next();
if (iterator.GetCurrent() != NULL)
{
Verify(distance < iterator.GetValue());
}
#endif
//
// Dump the LOD of the resource
//
#if 0
CollectionSize i = 0;
iterator.First();
while (iterator.GetCurrent() != NULL)
{
Check(iterator.GetCurrent());
if (audioLevelOfDetail == iterator.GetCurrent() /* && i > 0 */ )
{
Tell(
"AudioLOD:" << i <<
" d:" << distance <<
" t:" << iterator.GetValue() <<
"\n"
);
break;
}
iterator.Next();
i++;
}
#endif
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceIndex ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioResourceIndex::AudioResourceIndex(PlugStream *stream):
Node(stream),
audioResourceSocket(NULL, True)
{
CollectionSize i, number_of_entries;
MemoryStream_Read(stream, &number_of_entries);
for (i = 0; i < number_of_entries; i++)
{
AudioResource *audio_resource;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource);
Check(audio_resource);
AddAudioResource(audio_resource, i);
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioResourceIndex::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
Node::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Count number of entries
//
int number_of_entries = 0;
NameList::Entry *entry;
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_resource"))
number_of_entries++;
entry = entry->GetNextEntry();
}
//
// Store entries
//
MemoryStream_Write(stream, &number_of_entries);
Check(name_list);
entry = name_list->GetFirstEntry();
while (entry != NULL)
{
Check(entry);
if (entry->IsName("audio_resource"))
{
CString object_name;
ObjectID object_ID;
Check_Pointer(entry->GetChar());
object_name = entry->GetChar();
Check(stream);
object_ID = stream->FindObjectID(object_name);
Verify(object_ID != NullObjectID);
MemoryStream_Write(stream, &object_ID);
}
entry = entry->GetNextEntry();
}
}
//
//#############################################################################
//#############################################################################
//
AudioResourceIndex::~AudioResourceIndex()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioResourceIndex::TestInstance() const
{
Node::TestInstance();
Check(&audioResourceSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioResourceIndex::AddAudioResource(
AudioResource *audio_resource,
Enumeration index
)
{
Check(this);
audioResourceSocket.AddValue(audio_resource, index);
#if DEBUG_LEVEL>0
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
Check(&iterator);
for (int i = 0; i < iterator.GetSize(); i++)
{
Verify(iterator.GetNth(i) == audioResourceSocket.Find(i));
}
#endif
}
//
//#############################################################################
//#############################################################################
//
AudioResource*
AudioResourceIndex::GetAudioResource(Enumeration index)
{
Check(this);
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
Check(&iterator);
Verify(iterator.GetNth(index) == audioResourceSocket.Find(index));
return iterator.GetNth(index);
}
//
//#############################################################################
//#############################################################################
//
CollectionSize
AudioResourceIndex::GetSize()
{
Check(this);
TableIteratorOf<AudioResource*, Enumeration> iterator(&audioResourceSocket);
Check(&iterator);
return iterator.GetSize();
}
+270
View File
@@ -0,0 +1,270 @@
//===========================================================================//
// File: audlvl.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDLVL_HPP)
# define AUDLVL_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
//##########################################################################
//####################### AudioLevelOfDetail #########################
//##########################################################################
class AudioLevelOfDetail:
public Plug
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioLevelOfDetail(PlugStream *stream);
~AudioLevelOfDetail();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//-----------------------------------------------------------------------
// Accessors
//-----------------------------------------------------------------------
//
AudioVoiceCount
GetVoiceCount()
{return voiceCount;}
AudioRenderType
GetAudioRenderType()
{return audioRenderType;}
AudioFrameCount
GetSuspendDelay()
{return suspendDelay;}
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
#if 0
//
//-----------------------------------------------------------------------
// Defines the radial variation of the amplitude of the audio source.
// This feature is implemented well in Crystal River Engineering's
// API. The radiation profile of an audio source is specified with
// an array of sound levels in decibels paired with angles off of
// the audio source orientation. For example, you can design a
// rocket sound that is louder when heard from directly behind then
// from the side.
//-----------------------------------------------------------------------
//
AudioRadiationProfile
amplitudeRadiationProfile;
#endif
#if 0
//
//-----------------------------------------------------------------------
// Defines the radial variation of the high frequency content of the
// audio source. This concept is analogous to
// SetAmplitudeRadiationProfile except applied to the high frequency
// content of the audio source. Again, this allows the audio source
// to vary with respect to the position and orientation of the audio
// source and head.
//-----------------------------------------------------------------------
//
AudioRadiationProfile
filterRadiationProfile;
#endif
//
//-----------------------------------------------------------------------
// Misc
//-----------------------------------------------------------------------
//
AudioVoiceCount
voiceCount;
AudioRenderType
audioRenderType;
AudioFrameCount
suspendDelay;
};
//##########################################################################
//########################## AudioResource ############################
//##########################################################################
class AudioResource:
public Node
{
public:
//
//-----------------------------------------------------------------------
// Construction, Destruction, Testing
//-----------------------------------------------------------------------
//
AudioResource(PlugStream *stream);
~AudioResource();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// BuildFromPage
//-----------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//
//-----------------------------------------------------------------------
// SetDistance
//-----------------------------------------------------------------------
//
void
SetDistance(Scalar distance);
//
//-----------------------------------------------------------------------
// Accessors
//-----------------------------------------------------------------------
//
AudioVoiceCount
GetVoiceCount();
AudioRenderType
GetAudioRenderType();
AudioFrameCount
GetSuspendDelay();
protected:
//
//-----------------------------------------------------------------------
// Protected data
//-----------------------------------------------------------------------
//
AudioLevelOfDetail*
GetAudioLevelOfDetail();
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
AudioLevelOfDetail
*audioLevelOfDetail;
TableOf<AudioLevelOfDetail*, Scalar>
audioLevelOfDetailSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~
inline AudioLevelOfDetail*
AudioResource::GetAudioLevelOfDetail()
{
Check(this);
return audioLevelOfDetail;
}
inline AudioVoiceCount
AudioResource::GetVoiceCount()
{
Check(this);
Check(audioLevelOfDetail);
return audioLevelOfDetail->GetVoiceCount();
}
inline AudioRenderType
AudioResource::GetAudioRenderType()
{
Check(this);
Check(audioLevelOfDetail);
return audioLevelOfDetail->GetAudioRenderType();
}
inline AudioFrameCount
AudioResource::GetSuspendDelay()
{
Check(this);
Check(audioLevelOfDetail);
return audioLevelOfDetail->GetSuspendDelay();
}
//##########################################################################
//######################## AudioResourceIndex ########################
//##########################################################################
class AudioResourceIndex:
public Node
{
public:
AudioResourceIndex(PlugStream *stream);
~AudioResourceIndex();
Logical
TestInstance() const;
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
void
AddAudioResource(
AudioResource *audio_resource,
Enumeration index
);
AudioResource*
GetAudioResource(Enumeration index);
CollectionSize
GetSize();
private:
TableOf<AudioResource*, Enumeration>
audioResourceSocket;
};
#endif
+706
View File
@@ -0,0 +1,706 @@
//===========================================================================//
// File: audmidi.cpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 10/23/95 ECH Initial code
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDMIDI_HPP)
# include <audmidi.hpp>
#endif
//#############################################################################
//########################### MidiParse #################################
//#############################################################################
#define NOTEOFF (0x80)
#define NOTEON (0x90)
#define PRESSURE (0xa0)
#define CONTROLLER (0xb0)
#define PITCHBEND (0xe0)
#define PROGRAM (0xc0)
#define CHANPRESSURE (0xd0)
#define METATEXT "Text Event"
#define METACOPYRIGHT "Copyright Notice"
#define METASEQUENCE "Sequence/Track Name"
#define METAINSTRUMENT "Instrument Name"
#define METALYRIC "Lyric"
#define METAMARKER "Marker"
#define METACUE "Cue Point"
#define METAUNRECOGNIZED "Unrecognized"
#define CHAR_BUFF_SIZE (32)
//
//#############################################################################
//#############################################################################
//
MidiParse::MidiParse()
{
Mf_nomerge = 0; // 1 => continue'ed system exclusives are not collapsed.
Mf_currtime = 0L; // current time in delta-time units
Mf_skipinit = 0; // 1 if initial garbage should be skipped
Mf_toberead = 0L;
Msgbuff = NULL; // message buffer
Msgsize = 0; // Size of currently allocated Msg
Msgindex = 0; // index of next available location in Msg
}
//
//#############################################################################
//#############################################################################
//
MidiParse::~MidiParse()
{
if (Msgbuff != NULL)
{
Unregister_Pointer(Msgbuff);
#if 0
free(Msgbuff);
#else
delete[] Msgbuff;
#endif
Msgbuff = NULL;
}
}
//
//#############################################################################
//#############################################################################
//
Logical
MidiParse::TestInstance() const
{
Node::TestInstance();
return True;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedLongWord
MidiParse::CurTime()
{
Check(this);
return Mf_currtime;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::Parse()
{
Check(this);
SignedWord ntrks;
ntrks = readheader();
Verify(ntrks > 0);
while (ntrks-- > 0)
readtrack();
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::readmt(
char *s,
SignedWord skip
)
{
Check(this);
SignedWord nread = 0;
char b[4];
char buff[CHAR_BUFF_SIZE];
SignedWord c;
char *errmsg = "expecting ";
// read through the "MThd" or "MTrk" header string
// if 1, we attempt to skip initial garbage.
retry:
while ( nread<4 )
{
c = Mf_getc();
if ( c == EOF )
{
errmsg = "EOF while expecting ";
goto err;
}
b[nread++] = (char)c;
}
// See if we found the 4 characters we're looking for
if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )
return 0;
if ( skip )
{
// If we are supposed to skip initial garbage,
// try again with the next character.
b[0]=b[1];
b[1]=b[2];
b[2]=b[3];
nread = 3;
goto retry;
}
err:
Str_Copy(buff, errmsg, CHAR_BUFF_SIZE);
Str_Cat(buff, s, CHAR_BUFF_SIZE);
mferror(buff);
return 0;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::egetc()
{
Check(this);
// read a single character and abort on EOF
SignedWord c = Mf_getc();
if ( c == EOF )
mferror("premature EOF");
Mf_toberead--;
return c;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::readheader()
{
Check(this);
// read a header chunk
SignedWord
format, ntrks, division;
if ( readmt("MThd", Mf_skipinit) == EOF )
return 0;
Mf_toberead = read32bit();
format = read16bit();
ntrks = read16bit();
division = read16bit();
Mf_header(format,ntrks,division);
// flush any extra stuff, in case the length of header is not 6
while ( Mf_toberead > 0 )
egetc();
return ntrks;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::readtrack()
{
Check(this);
// read a track chunk
// This array is indexed by the high half of a status byte. It's
// value is either the number of bytes needed (1 or 2) for a channel
// message, or 0 (meaning it's not a channel message).
static SignedWord chantype[] =
{
0, 0, 0, 0, 0, 0, 0, 0, // 0x00 through 0x70
2, 2, 2, 2, 1, 1, 2, 0 // 0x80 through 0xf0
};
SignedLongWord lookfor, lng;
SignedWord c, c1, type;
SignedWord sysexcontinue = 0; // 1 if last message was an unfinished sysex
SignedWord running; // 1 when running status used
SignedWord status = 0; // (possibly running) status byte
SignedWord needed;
if ( readmt("MTrk",0) == EOF )
return;
Mf_toberead = read32bit();
Mf_currtime = 0;
Mf_starttrack();
while ( Mf_toberead > 0 )
{
Mf_currtime += readvarinum(); // delta time
c = egetc();
if ( sysexcontinue && c != 0xf7 )
mferror("didn't find expected continuation of a sysex");
if ( (c & 0x80) == 0 ) // running status?
{
if ( status == 0 )
mferror("unexpected running status");
running = 1;
}
else
{
status = c;
running = 0;
}
needed = chantype[ (status>>4) & 0xf ];
if ( needed ) // ie. is it a channel message?
{
if ( running )
c1 = c;
else
c1 = egetc();
chanmessage( status, c1, (needed>1) ? egetc() : (SignedWord)0 );
continue;
}
switch ( c )
{
case 0xff: // meta event
type = egetc();
// watch out - Don't combine the next 2 statements
lng = readvarinum();
lookfor = Mf_toberead - lng;
msginit();
while ( Mf_toberead > lookfor )
msgadd(egetc());
metaevent(type);
break;
case 0xf0: // start of system exclusive
// watch out - Don't combine the next 2 statements
lng = readvarinum();
lookfor = Mf_toberead - lng;
msginit();
msgadd(0xf0);
while ( Mf_toberead > lookfor )
msgadd(c=egetc());
if ( c==0xf7 || Mf_nomerge==0 )
sysex();
else
sysexcontinue = 1; // merge into next msg
break;
case 0xf7: // sysex continuation or arbitrary stuff
// watch out - Don't combine the next 2 statements
lng = readvarinum();
lookfor = Mf_toberead - lng;
if ( ! sysexcontinue )
msginit();
while ( Mf_toberead > lookfor )
msgadd(c=egetc());
if ( ! sysexcontinue )
{
Mf_arbitrary(msgleng(),msg());
}
else if ( c == 0xf7 )
{
sysex();
sysexcontinue = 0;
}
break;
default:
badbyte(c);
break;
}
}
Mf_endtrack();
return;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::badbyte(SignedWord c)
{
Check(this);
char buff[CHAR_BUFF_SIZE];
sprintf(buff,"unexpected byte: 0x%02x",c);
mferror(buff);
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::metaevent(SignedWord type)
{
Check(this);
SignedWord leng = msgleng();
char *m = msg();
switch ( type )
{
case 0x00:
Mf_seqnum(to16bit(m[0],m[1]));
break;
case 0x01: // Text event
case 0x02: // Copyright notice
case 0x03: // Sequence/Track name
case 0x04: // Instrument name
case 0x05: // Lyric
case 0x06: // Marker
case 0x07: // Cue point
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
// These are all text events
Mf_text(type,leng,m);
break;
case 0x2f: // End of Track
Mf_eot();
break;
case 0x51: // Set tempo
Mf_tempo(to32bit((SignedWord)0,m[0],m[1],m[2]));
break;
case 0x54:
Mf_smpte(m[0],m[1],m[2],m[3],m[4]);
break;
case 0x58:
Mf_timesig(m[0],m[1],m[2],m[3]);
break;
case 0x59:
Mf_keysig(m[0],m[1]);
break;
case 0x7f:
Mf_sqspecific(leng,m);
break;
default:
Mf_metamisc(type,leng,m);
}
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::sysex()
{
Check(this);
Mf_sysex(msgleng(),msg());
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::chanmessage(
SignedWord status,
SignedWord c1,
SignedWord c2
)
{
Check(this);
SignedWord chan = status & (SignedWord)0xf;
switch ( status & 0xf0 )
{
case NOTEOFF:
Mf_off(chan,c1,c2);
break;
case NOTEON:
Mf_on(chan,c1,c2);
break;
case PRESSURE:
Mf_pressure(chan,c1,c2);
break;
case CONTROLLER:
Mf_controller(chan,c1,c2);
break;
case PITCHBEND:
Mf_pitchbend(chan,c1,c2);
break;
case PROGRAM:
Mf_program(chan,c1);
break;
case CHANPRESSURE:
Mf_chanpressure(chan,c1);
break;
}
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedLongWord
MidiParse::readvarinum()
{
Check(this);
// readvarinum - read a varying-length number, and return the
// number of characters it took.
SignedLongWord value;
SignedWord c;
c = egetc();
value = c;
if (c & 0x80)
{
value &= 0x7f;
do
{
c = egetc();
value <<= 7;
value += (c & 0x7f);
} while (c & 0x80);
}
return value;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedLongWord
MidiParse::to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4)
{
Check(this);
SignedLongWord value;
value = (c1 & 0xff);
value = (value<<8) + (c2 & 0xff);
value = (value<<8) + (c3 & 0xff);
value = (value<<8) + (c4 & 0xff);
return value;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::to16bit(SignedWord c1,SignedWord c2)
{
Check(this);
SignedWord value;
value = (c1 & (SignedWord)0xff);
value = (SignedWord)((SignedWord)(value<<8) + (c2 & (SignedWord)0xff));
return value;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedLongWord
MidiParse::read32bit()
{
Check(this);
SignedWord c1, c2, c3, c4;
c1 = egetc();
c2 = egetc();
c3 = egetc();
c4 = egetc();
return to32bit(c1,c2,c3,c4);
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::read16bit()
{
Check(this);
SignedWord c1, c2;
c1 = egetc();
c2 = egetc();
return to16bit(c1,c2);
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::mferror(char *s)
{
Check(this);
Mf_error(s);
}
// The code below allows collection of a system exclusive message of
// arbitrary length. The Msgbuff is expanded as necessary. The only
// visible data/routines are msginit(), msgadd(), msg(), msgleng().
#define MSGINCREMENT ((SignedWord)128)
//
//#############################################################################
//#############################################################################
//
void
MidiParse::msginit()
{
Check(this);
Msgindex = 0;
}
//
//#############################################################################
//#############################################################################
//
char*
MidiParse::msg()
{
Check(this);
return Msgbuff;
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::msgleng()
{
Check(this);
return Msgindex;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::msgadd(SignedWord c)
{
Check(this);
// If necessary, allocate larger message buffer.
if ( Msgindex >= Msgsize )
msgenlarge();
Msgbuff[Msgindex++] = (char)c;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::msgenlarge()
{
Check(this);
char *newmess;
char *oldmess = Msgbuff;
SignedWord oldleng = Msgsize;
Msgsize += MSGINCREMENT;
#if 0
newmess = (char*)malloc( sizeof(char)*Msgsize );
#else
newmess = new char[Msgsize];
#endif
Register_Pointer(newmess);
// copy old message into larger new one
if ( oldmess != 0 )
{
char *p = newmess;
char *q = oldmess;
char *endq = &oldmess[oldleng];
for ( ; q!=endq ; p++,q++ )
*p = *q;
Unregister_Pointer(oldmess);
#if 0
free(oldmess);
#else
delete[] oldmess;
#endif
}
Msgbuff = newmess;
}
// METHODS TO OVERRIDE
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
MidiParse::Mf_getc()
{
Fail("MidiParse::Mf_getc - Should never reach here");
return 0;
}
//
//#############################################################################
//#############################################################################
//
void
MidiParse::Mf_error(char*)
{
Fail("MidiParse::Mf_error - Should never reach here");
}
+166
View File
@@ -0,0 +1,166 @@
//===========================================================================//
// File: audmidi.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 10/23/95 ECH Initial code
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDMIDI_HPP)
# define AUDMIDI_HPP
# if !defined(NODE_HPP)
# include <node.hpp>
# endif
//##########################################################################
//########################## MidiParse ###############################
//##########################################################################
class MidiParse:
public Node
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
typedef long SignedLongWord; // 4 bytes
typedef short int SignedWord; // 2 bytes
typedef char SignedByte; // 1 bytes
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
MidiParse();
~MidiParse();
Logical
TestInstance() const;
void
Parse();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Accessors
//
protected:
SignedLongWord
CurTime();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Sub-class callbacks
//
private:
virtual SignedWord
Mf_getc();
virtual void
Mf_error(char *);
virtual void
Mf_starttrack() {}
virtual void
Mf_endtrack() {}
virtual void
Mf_eot() {}
virtual void
Mf_header(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_on(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_off(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_pressure(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_controller(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_pitchbend(SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_program(SignedWord,SignedWord) {}
virtual void
Mf_chanpressure(SignedWord,SignedWord) {}
virtual void
Mf_sysex(SignedWord,char*) {}
virtual void
Mf_arbitrary(SignedWord,char*) {}
virtual void
Mf_metamisc(SignedWord,SignedWord,char*) {}
virtual void
Mf_seqnum(SignedWord) {}
virtual void
Mf_smpte(SignedWord,SignedWord,SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_timesig(SignedWord,SignedWord,SignedWord,SignedWord) {}
virtual void
Mf_tempo(SignedLongWord) {}
virtual void
Mf_keysig(SignedWord,SignedWord) {}
virtual void
Mf_sqspecific(SignedWord,char*) {}
virtual void
Mf_text(SignedWord,SignedWord,char*) {}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
SignedWord
readmt(char *s,SignedWord skip);
SignedWord
egetc();
SignedWord
readheader();
void
readtrack();
void
badbyte(SignedWord c);
void
metaevent(SignedWord type);
void
sysex();
void
chanmessage(SignedWord status,SignedWord c1,SignedWord c2);
SignedLongWord
readvarinum();
SignedLongWord
to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4);
SignedWord
to16bit(SignedWord c1,SignedWord c2);
SignedLongWord
read32bit();
SignedWord
read16bit();
void
mferror(char *s);
void
msginit();
char*
msg();
SignedWord
msgleng();
void
msgadd(SignedWord c);
void
msgenlarge();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
SignedWord Mf_nomerge;
SignedLongWord Mf_currtime;
SignedWord Mf_skipinit;
SignedLongWord Mf_toberead;
char *Msgbuff;
SignedWord Msgsize;
SignedWord Msgindex;
};
#endif
+894
View File
@@ -0,0 +1,894 @@
//===========================================================================//
// File: audseq.cpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDSEQ_HPP)
# include <audseq.hpp>
#endif
#if !defined(OBJSTRM_HPP)
#include <objstrm.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlEvent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlEvent::AudioControlEvent(
AudioTick start_tick,
AudioControlID audio_control_ID,
AudioControlValue audio_control_value
):
Plug(AudioControlEventClassID)
{
startTick = start_tick;
audioControlID = audio_control_ID;
audioControlValue = audio_control_value;
}
//
//#############################################################################
//#############################################################################
//
AudioControlEvent::AudioControlEvent():
Plug(AudioControlEventClassID)
{
startTick = 0;
audioControlID = NullAudioControlID;
audioControlValue = 0.0f;
}
//
//#############################################################################
//#############################################################################
//
AudioControlEvent::~AudioControlEvent()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlEvent::TestInstance() const
{
Plug::TestInstance();
Verify(
(Enumeration)audioControlID >= (Enumeration)0 &&
(Enumeration)audioControlID < (Enumeration)AudioControlIDCount
);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlEvent::Send(AudioComponent *audio_component)
{
Check(this);
Check(audio_component);
audio_component->ReceiveControl(audioControlID, audioControlValue);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlEvent::Chase(AudioComponent *audio_component)
{
Check(this);
Check(audio_component);
switch (audioControlID)
{
case StartAudioControlID:
return False;
case StopAudioControlID:
Send(audio_component);
return False;
default:
break;
}
return True;
}
//
//#############################################################################
//#############################################################################
//
MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
AudioControlEvent *control_event
)
{
Check(stream);
Check_Signature(control_event);
MemoryStream_Read(stream, &control_event->startTick);
MemoryStream_Read(stream, &control_event->audioControlID);
MemoryStream_Read(stream, &control_event->audioControlValue);
Check(control_event);
return *stream;
}
//
//#############################################################################
//#############################################################################
//
MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const AudioControlEvent *control_event
)
{
Check(stream);
Check(control_event);
MemoryStream_Write(stream, &control_event->startTick);
MemoryStream_Write(stream, &control_event->audioControlID);
MemoryStream_Write(stream, &control_event->audioControlValue);
return *stream;
}
//
//#############################################################################
//#############################################################################
//
ostream&
operator << (
ostream &strm,
const AudioControlEvent &control_event
)
{
Check(&control_event);
strm << "[" ;
strm << control_event.startTick << ",";
strm << control_event.audioControlID << ",";
strm << control_event.audioControlValue;
strm << "]";
return strm;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
AudioControlSequence::AudioControlSequence(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream),
audioComponentSocket(NULL),
audioControlEventSocket(NULL)
{
Logical dump_value;
Logical is_looped;
AudioComponent *audio_component;
AudioControlEvent *audio_control_event;
CollectionSize i, number_of_control_events;
AudioDivisionsPerBeat divisions_per_beat;
AudioTempo tempo;
MemoryStream_Read(stream, &dump_value);
MemoryStream_Read(stream, &is_looped);
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component);
MemoryStream_Read(stream, &divisions_per_beat);
MemoryStream_Read(stream, &tempo);
MemoryStream_Read(stream, &number_of_control_events);
for (i = 0; i < number_of_control_events; i++)
{
audio_control_event = new AudioControlEvent;
Register_Object(audio_control_event);
MemoryStream_Read(stream, audio_control_event);
audioControlEventSocket.Add(audio_control_event);
}
AudioControlSequenceX(
audio_component,
entity,
is_looped,
divisions_per_beat,
tempo,
dump_value
);
}
//
//#############################################################################
//#############################################################################
//
#if DEBUG_LEVEL>0
void
AudioControlSequence::AudioControlSequenceX(
AudioComponent *audio_component,
Entity *entity,
Logical is_looped,
AudioDivisionsPerBeat divisions_per_beat,
AudioTempo the_tempo,
Logical dump_value
)
#else
void
AudioControlSequence::AudioControlSequenceX(
AudioComponent *audio_component,
Entity *entity,
Logical is_looped,
AudioDivisionsPerBeat divisions_per_beat,
AudioTempo the_tempo,
Logical
)
#endif
{
Check(audio_component);
audioComponentSocket.Add(audio_component);
isLooped = is_looped;
isRunning = False;
startTime = AudioTime::Null;
audioControlEventIterator = NULL;
divisionsPerBeat = divisions_per_beat;
tempo = the_tempo;
#if DEBUG_LEVEL>0
dumpValue = dump_value;
#endif
audio_component->AddWatcher(this);
Check(entity);
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
AudioControlSequence::~AudioControlSequence()
{
StopSequence();
Verify(!isRunning);
Verify(audioControlEventIterator == NULL);
AudioControlEventIterator iterator(&audioControlEventSocket);
Check(&iterator);
iterator.DeletePlugs();
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSequence::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, is_looped);
//
// Write audio component
//
CString audio_component_name("audio_component");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name);
//
// Read tempo
//
AudioTempo tempo = 100;
if (name_list->FindData("tempo") != NULL)
{
Check_Pointer(name_list->FindData("tempo"));
Convert_From_Ascii((const char *)name_list->FindData("tempo"), &tempo);
}
//
// Read midi file
//
DynamicMemoryStream midi_file_stream;
{
CString midi_file_name;
Check_Pointer(name_list->FindData("midi_file"));
midi_file_name = (const char*)name_list->FindData("midi_file");
ifstream input_midi_file(midi_file_name, ios::in|ios::binary);
#if DEBUG_LEVEL>0
if (!input_midi_file)
{
Dump(midi_file_name);
}
#endif
MemoryStream_Write(&midi_file_stream, &input_midi_file);
midi_file_stream.Rewind();
}
//
// Parse midi stream
//
DynamicMemoryStream control_event_stream;
CreateAudioControlEventStream midi_parser;
Check(&midi_file_stream);
Check(&control_event_stream);
Check(&midi_parser);
midi_parser.Parse(&midi_file_stream, &control_event_stream, tempo);
control_event_stream.Rewind();
//
// Write the divisions per beat and tempo
//
AudioDivisionsPerBeat divisions_per_beat;
divisions_per_beat = midi_parser.GetDivisionsPerBeat();
tempo = midi_parser.GetTempo();
MemoryStream_Write(stream, &divisions_per_beat);
MemoryStream_Write(stream, &tempo);
//
// Write control event stream
//
CollectionSize number_of_control_events;
number_of_control_events = midi_parser.GetNumberOfEvents();
MemoryStream_Write(stream, &number_of_control_events);
MemoryStream_Write(stream, &control_event_stream);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlSequence::TestInstance() const
{
AudioComponent::TestInstance();
Check(&audioComponentSocket);
Check(&audioControlEventSocket);
if (isRunning)
{
Check(audioControlEventIterator);
}
else
{
Verify(audioControlEventIterator == NULL);
}
Verify(tempo >= 1 && tempo <= 600);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSequence::StartSequence()
{
Check(this);
//
// If already running, stop sequence
//
if (isRunning)
{
StopSequence();
}
//
// Make an iterator for the control sequence
//
Verify(audioControlEventIterator == NULL);
audioControlEventIterator =
new AudioControlEventIterator(&audioControlEventSocket);
Register_Object(audioControlEventIterator);
startTime = AudioTime::Now();
isRunning = True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSequence::StopSequence()
{
Check(this);
//
// If not running, return
//
if (!isRunning)
return;
//
// Find next on or off event
//
AudioControlEvent *control_event;
Check(audioControlEventIterator);
while ((control_event = audioControlEventIterator->ReadAndNext()) != NULL)
{
Check(control_event);
if (!control_event->Chase(audioComponentSocket.GetCurrent()))
break;
}
//
// Destroy the iterator for the control sequence
//
Unregister_Object(audioControlEventIterator);
delete audioControlEventIterator;
audioControlEventIterator = NULL;
isRunning = False;
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSequence::RunSequence()
{
Check(this);
//
// If the sequence is not running, then return
//
if (!isRunning)
return;
//
// Play events which have a start time less then the
// current time
//
AudioControlEvent *control_event;
Check(audioControlEventIterator);
control_event = audioControlEventIterator->GetCurrent();
while (
control_event != NULL &&
IsEventReady(control_event)
)
{
#if DEBUG_LEVEL>0
if (dumpValue)
{
Dump(*control_event);
}
#endif
#if 0
//
// HACK - convert start control to use duration
//
Verify(control_event->audioControlID != StopAudioControlID);
if (control_event->audioControlID == StartAudioControlID)
{
//
// Convert ticks to seconds
// seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s))
//
Scalar denominator =
(Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f;
Verify(!Small_Enough(denominator));
control_event->audioControlValue =
control_event->audioControlValue / denominator;
}
#endif
//
// Send the controller to the connected audio component
//
Check(control_event);
control_event->Send(audioComponentSocket.GetCurrent());
//
// Step to next event
//
audioControlEventIterator->Next();
control_event = audioControlEventIterator->GetCurrent();
}
//
// If there are no more events to be played then stop running
//
if (control_event == NULL)
{
StopSequence();
if (isLooped)
{
StartSequence();
}
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioControlSequence::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
switch(control_ID)
{
case StartAudioControlID:
StartSequence();
break;
case StopAudioControlID:
StopSequence();
break;
case IdleAudioControlID:
RunSequence();
break;
case TempoAudioControlID:
tempo = control_value;
Verify(tempo >= 1 && tempo <= 600);
break;
default:
break;
}
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioControlSequence::IsEventReady(AudioControlEvent *audio_control_event)
{
Check(this);
AudioTime offset_time(startTime);
offset_time += CalculateEventSeconds(audio_control_event);
return (offset_time <= AudioTime::Now());
}
//
//#############################################################################
//#############################################################################
//
Scalar
AudioControlSequence::CalculateEventSeconds(
AudioControlEvent *audio_control_event
)
{
Check(this);
Check(audio_control_event);
//
// Convert ticks to seconds
// seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s))
//
Scalar denominator = (Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f;
Verify(!Small_Enough(denominator));
return (Scalar)audio_control_event->GetStartTick() / denominator;
}
//#############################################################################
//#################### CreateAudioControlEventStream ####################
//#############################################################################
CreateAudioControlEventStream::CreateAudioControlEventStream():
audioControlEventSocket(NULL, False)
{
inputStream = NULL;
outputStream = NULL;
divisionsPerBeat = 120;
tempo = 100;
}
//
//#############################################################################
//#############################################################################
//
CreateAudioControlEventStream::~CreateAudioControlEventStream(void)
{
AudioControlEventIterator iterator(&audioControlEventSocket);
Check(&iterator);
iterator.DeletePlugs();
}
//
//#############################################################################
//#############################################################################
//
Logical
CreateAudioControlEventStream::TestInstance() const
{
MidiParse::TestInstance();
Check(&audioControlEventSocket);
return True;
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Parse(
MemoryStream *input_stream,
MemoryStream *output_stream,
SignedLongWord tempo_argument
)
{
Check(this);
Check(input_stream);
Check(output_stream);
inputStream = input_stream;
outputStream = output_stream;
//
// Parse the stream
//
tempo = tempo_argument;
Verify(GetNumberOfEvents() == 0);
MidiParse::Parse();
//
// Write the events
//
AudioControlEventIterator iterator(&audioControlEventSocket);
AudioControlEvent *control_event;
Check(&iterator);
while ((control_event = iterator.ReadAndNext()) != NULL)
{
Check(control_event);
MemoryStream_Write(outputStream, control_event);
}
}
//
//#############################################################################
//#############################################################################
//
CollectionSize
CreateAudioControlEventStream::GetNumberOfEvents()
{
Check(this);
AudioControlEventIterator iterator(&audioControlEventSocket);
Check(&iterator);
return iterator.GetSize();
}
//
//#############################################################################
//#############################################################################
//
MidiParse::SignedWord
CreateAudioControlEventStream::Mf_getc()
{
Check(this);
unsigned char c;
MemoryStream_Read(inputStream, &c);
return c;
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Mf_error(char *str)
{
Check(this);
Check_Pointer(str);
Fail(str);
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Mf_header(
SignedWord,
SignedWord,
SignedWord division
)
{
Check(this);
divisionsPerBeat = division;
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Mf_on(
SignedWord channel,
SignedWord pitch,
SignedWord vol
)
{
Check(this);
//
// Interpret vol 0 as note off
//
if (vol == 0)
{
Mf_off(channel, pitch, vol);
return;
}
//
// Verify that last event was a stop
//
#if DEBUG_LEVEL>0
{
AudioControlEventIterator iterator(&audioControlEventSocket);
AudioControlEvent *last_control_event;
iterator.Last();
if ((last_control_event = iterator.GetCurrent()) != NULL)
{
Check(last_control_event);
Verify(last_control_event->audioControlID == StopAudioControlID);
}
}
#endif
AudioTick current_ticks = CurTime();
AudioControlEvent *audio_control_event;
//
// Add note value event
//
audio_control_event
= new AudioControlEvent(
current_ticks,
NoteAudioControlID,
(Scalar)pitch
);
Register_Object(audio_control_event);
audioControlEventSocket.AddValue(audio_control_event, current_ticks);
//
// Add velocity event
//
audio_control_event
= new AudioControlEvent(
current_ticks,
AttackVolumeAudioControlID,
(Scalar)vol / (Scalar)127
);
Register_Object(audio_control_event);
audioControlEventSocket.AddValue(audio_control_event, current_ticks);
//
// Add start event
//
audio_control_event
= new AudioControlEvent(
current_ticks,
StartAudioControlID,
0.0f
);
Register_Object(audio_control_event);
audioControlEventSocket.AddValue(audio_control_event, current_ticks);
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Mf_off(
SignedWord,
SignedWord pitch,
SignedWord
)
{
Check(this);
AudioTick current_ticks = CurTime();
AudioControlEvent *audio_control_event;
#if 0
//
// HACK - convert start control to use duration
//
AudioControlEventIterator
iterator(&audioControlEventSocket);
iterator.Last();
audio_control_event = iterator.GetCurrent();
Check(audio_control_event);
Verify(audio_control_event->audioControlID == StartAudioControlID);
audio_control_event->audioControlValue =
current_ticks - audio_control_event->startTick;
#else
//
// Add note value event
//
audio_control_event
= new AudioControlEvent(
current_ticks,
NoteAudioControlID,
(Scalar)pitch
);
Register_Object(audio_control_event);
audioControlEventSocket.AddValue(audio_control_event, current_ticks);
//
// Add stop event
//
audio_control_event
= new AudioControlEvent(
current_ticks,
StopAudioControlID,
0.0f
);
Register_Object(audio_control_event);
audioControlEventSocket.AddValue(audio_control_event, current_ticks);
#endif
}
//
//#############################################################################
//#############################################################################
//
void
CreateAudioControlEventStream::Mf_tempo(SignedLongWord)
{
Check(this);
// tempo = i1; // HACK - Cakewalk appears to produce bogus tempo
}
+279
View File
@@ -0,0 +1,279 @@
//===========================================================================//
// File: audseq.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDSEQ_HPP)
# define AUDSEQ_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
# if !defined(AUDMIDI_HPP)
# include <audmidi.hpp>
# endif
# if !defined(VCHAIN_HPP)
# include <vchain.hpp>
# endif
# if !defined(AUDTIME_HPP)
# include <audtime.hpp>
# endif
//##########################################################################
//####################### AudioControlEvent ##########################
//##########################################################################
class AudioControlEvent:
public Plug
{
friend MemoryStream&
MemoryStream_Read(
MemoryStream *stream,
AudioControlEvent *control_event
);
friend MemoryStream&
MemoryStream_Write(
MemoryStream *stream,
const AudioControlEvent *control_event
);
public:
AudioControlEvent(
AudioTick start_tick,
AudioControlID audio_control_ID,
AudioControlValue audio_control_value
);
AudioControlEvent();
~AudioControlEvent();
Logical
AudioControlEvent::TestInstance() const;
AudioTick
GetStartTick()
{return startTick;}
void
Send(AudioComponent *audio_component);
Logical
Chase(AudioComponent *audio_component);
public:
friend ostream&
operator << (
ostream &strm,
const AudioControlEvent &control_event
);
// private: // HACK
AudioTick
startTick;
AudioControlID
audioControlID;
AudioControlValue
audioControlValue;
};
//##########################################################################
//####################### AudioControlSequence #######################
//##########################################################################
class AudioControlSequence:
public AudioComponent
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
AudioControlSequence(
PlugStream *stream,
Entity *entity
);
void
AudioControlSequenceX(
AudioComponent *audio_component,
Entity *entity,
Logical is_looped,
AudioDivisionsPerBeat divisions_per_beat,
AudioTempo tempo,
Logical dump_value
);
~AudioControlSequence();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// BuildFromPage
//--------------------------------------------------------------------
//
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Sequence methods
//
public:
//
//--------------------------------------------------------------------
// Controller methods
//--------------------------------------------------------------------
//
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
//
//--------------------------------------------------------------------
// Sequence control
//--------------------------------------------------------------------
//
void
StartSequence();
void
RunSequence();
void
StopSequence();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
Logical
IsEventReady(AudioControlEvent *audio_control_event);
Scalar
CalculateEventSeconds(AudioControlEvent *audio_control_event);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
typedef SChainOf<AudioControlEvent*>
AudioControlEventSocket;
typedef SChainIteratorOf<AudioControlEvent*>
AudioControlEventIterator;
Logical isLooped;
Logical isRunning;
AudioTime startTime;
AudioDivisionsPerBeat divisionsPerBeat;
AudioTempo tempo;
SlotOf<AudioComponent*>
audioComponentSocket;
AudioControlEventSocket
audioControlEventSocket;
AudioControlEventIterator
*audioControlEventIterator;
#if DEBUG_LEVEL>0
Logical
dumpValue;
#endif
};
//##########################################################################
//################### CreateAudioControlEventStream ##################
//##########################################################################
class CreateAudioControlEventStream:
public MidiParse
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
CreateAudioControlEventStream();
~CreateAudioControlEventStream();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Parsing
//
public:
void
Parse(
MemoryStream *input_stream,
MemoryStream *output_stream,
SignedLongWord tempo=100
);
AudioDivisionsPerBeat
GetDivisionsPerBeat()
{return divisionsPerBeat;}
AudioTempo
GetTempo()
{return tempo;}
CollectionSize
GetNumberOfEvents();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Implementations
//
private:
SignedWord
Mf_getc();
void
Mf_error(char *);
void
Mf_header(SignedWord,SignedWord,SignedWord);
void
Mf_on(SignedWord,SignedWord,SignedWord);
void
Mf_off(SignedWord,SignedWord,SignedWord);
void
Mf_tempo(SignedLongWord);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
typedef VChainOf<AudioControlEvent*, AudioTick>
AudioControlEventSocket;
typedef VChainIteratorOf<AudioControlEvent*, AudioTick>
AudioControlEventIterator;
MemoryStream
*inputStream;
MemoryStream
*outputStream;
AudioDivisionsPerBeat
divisionsPerBeat;
AudioTempo
tempo;
AudioControlEventSocket
audioControlEventSocket;
};
#endif
+848
View File
@@ -0,0 +1,848 @@
//===========================================================================//
// File: audsrc.cpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDSRC_HPP)
# include <audsrc.hpp>
#endif
#if !defined(AUDREND_HPP)
# include <audrend.hpp>
#endif
#if !defined(OBJSTRM_HPP)
#include <objstrm.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
#define DEFAULT_NOTE (60)
AudioSourceStartState::AudioSourceStartState()
{
noteValue = DEFAULT_NOTE;
isDurationSet = False;
hasDuration = False;
duration = 0.0f;
startTime = 0.0f;
endTime = 0.0f;
}
//
//#############################################################################
//#############################################################################
//
AudioSourceStartState::~AudioSourceStartState()
{
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioSourceStartState::TestInstance() const
{
if (isDurationSet || hasDuration)
{
Verify(duration >= 0.0f);
}
if (hasDuration)
{
Verify(endTime >= startTime);
}
return True;
}
//
//#############################################################################
//#############################################################################
//
void
AudioSourceStartState::CalculateDuration(AudioControlValue control_value)
{
//
// Calculate duration
//
if (control_value > 0.0f)
{
hasDuration = True;
endTime = AudioTime::Now();
endTime += control_value;
}
else if (isDurationSet)
{
hasDuration = True;
endTime = AudioTime::Now();
endTime += duration;
isDurationSet = False;
}
else
{
hasDuration = False;
endTime = 0.0f;
}
}
#if 0
//
//#############################################################################
//#############################################################################
//
AudioTime
AudioSourceStartState::GetCurrentRunningTime()
{
Check(this);
AudioTime current_duration = AudioTime::Now();
return (current_duration -= startTime);
}
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
//#############################################################################
//
const Receiver::HandlerEntry
AudioSource::MessageHandlerEntries[]=
{
{
AudioSource::StartMessageID,
"Start",
(AudioSource::Handler)&AudioSource::StartMessageHandler
},
{
AudioSource::StopMessageID,
"Stop",
(AudioSource::Handler)&AudioSource::StopMessageHandler
}
};
AudioSource::MessageHandlerSet
AudioSource::MessageHandlers(
ELEMENTS(AudioSource::MessageHandlerEntries),
AudioSource::MessageHandlerEntries,
AudioComponent::MessageHandlers
);
//
//#############################################################################
//#############################################################################
//
Derivation
AudioSource::ClassDerivations(
AudioComponent::ClassDerivations,
"AudioSource"
);
AudioSource::SharedData
AudioSource::DefaultData(
AudioSource::ClassDerivations,
AudioSource::MessageHandlers
);
//
//#############################################################################
//#############################################################################
//
AudioSource::AudioSource(
PlugStream *stream,
Entity *entity
):
AudioComponent(stream, DefaultData)
{
AudioResource *audio_resource;
AudioLocation *audio_location;
AudioSourcePriority priority;
AudioSourceMixPresence mix_presence;
AudioControlValue volume_mix_level;
AudioPitchCents pitch_mix_offset;
AudioControlValue brightness_mix_level;
Logical has_compression_curve;
Scalar seconds;
AudioTime compression_duration;
Logical use_brightness_scale;
Logical use_attack_time_scale;
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource);
PlugStream_ReadObjectIDAndFindPlug(stream, &audio_location);
MemoryStream_Read(stream, &priority);
MemoryStream_Read(stream, &mix_presence);
MemoryStream_Read(stream, &volume_mix_level);
MemoryStream_Read(stream, &pitch_mix_offset);
MemoryStream_Read(stream, &brightness_mix_level);
MemoryStream_Read(stream, &has_compression_curve);
MemoryStream_Read(stream, &seconds);
compression_duration = seconds;
MemoryStream_Read(stream, &use_brightness_scale);
MemoryStream_Read(stream, &use_attack_time_scale);
AudioSourceX(
audio_resource,
audio_location,
entity,
priority,
mix_presence,
volume_mix_level,
pitch_mix_offset,
brightness_mix_level,
has_compression_curve,
compression_duration,
use_brightness_scale,
use_attack_time_scale
);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
)
{
AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID);
//
// Store fields
//
CString audio_resource_name("resource");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_resource_name);
CString audio_location_name("location");
PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_location_name);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, priority);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, mix_presence);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, volume_mix_level);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioPitchCents, pitch_mix_offset);
MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, brightness_mix_level);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, has_compression_curve);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, compression_duration);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_brightness_scale);
MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_attack_time_scale);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::AudioSourceX(
AudioResource *audio_resource,
AudioLocation *audio_location,
Entity *entity,
AudioSourcePriority priority,
AudioSourceMixPresence mix_presence,
AudioControlValue volume_mix_level,
AudioPitchCents pitch_mix_offset,
AudioControlValue brightness_mix_level,
Logical has_compression_curve,
const AudioTime &compression_duration,
Logical use_brightness_scale,
Logical use_attack_time_scale
)
{
Check(audio_resource);
Check(audio_location);
Check(entity);
audioLocation = audio_location;
audioResource = audio_resource;
audioSourceState = StoppedAudioSourceState;
attackVolumeScale = 1.0f;
useAttackTimeScale = use_attack_time_scale;
attackTimeScale = 0.0f;
audioSourcePriority = priority;
audioSourceMixPresence = mix_presence;
volumeCompressionScale = 1.0f;
hasCompressionCurve = has_compression_curve;
compressionDuration = compression_duration;
volumeMixScale = volume_mix_level;
pitchMixOffset = pitch_mix_offset;
useBrightnessScale = use_brightness_scale;
brightnessMixScale = brightness_mix_level;
volumeScale = 1.0f;
pitchOffset = 0.0f;
brightnessScale = 1.0f;
nextExecuteFrame = NullAudioFrameCount;
suspendFinishedFrame = NullAudioFrameCount;
entity->AddAudioComponent(this);
}
//
//#############################################################################
//#############################################################################
//
AudioSource::~AudioSource()
{
Verify(audioSourceState == StoppedAudioSourceState);
}
//
//#############################################################################
//#############################################################################
//
Logical
AudioSource::TestInstance() const
{
AudioComponent::TestInstance();
return True;
}
//
// Resource methods
//
//
//#############################################################################
//#############################################################################
//
void
AudioSource::SetAudioResource(AudioResource *audio_resource)
{
Check(this);
Check(audio_resource);
Verify(audioSourceState == StoppedAudioSourceState);
Check(audioResource);
audioResource = audio_resource;
}
//
// Current State/Status Accessors
//
//
//#############################################################################
//#############################################################################
//
void
AudioSource::AssignAudioSourceState(AudioSourceState audio_source_state)
{
Check(this);
//
// Initialize the next start state if the source is now running
//
if (audio_source_state == RunningAudioSourceState)
{
AudioSourceStartState null_state;
nextStartState = null_state;
}
audioSourceState = audio_source_state;
}
//
// Mixing & Logical compression methods
//
//
//#############################################################################
//#############################################################################
//
AudioControlValue
AudioSource::CalculateSourceCompressionEffect()
{
Check(this);
//
// Get current volume level
//
AudioControlValue current_volume_level;
current_volume_level = CalculateSourceVolumeScale();
Verify(current_volume_level >= 0.0f && current_volume_level <= 1.0f);
//
// Calculate the amount of this to apply to compression
//
if (hasCompressionCurve)
{
//
// scale = 1 / (1 + ((1/comp_dur) * duration)^2)
//
Scalar current_running_time = GetCurrentRunningTime();
Scalar compression_duration = compressionDuration;
Scalar duration_factor;
Scalar denominator;
AudioControlValue compression_effect;
Verify(!Small_Enough(compression_duration));
duration_factor =
pow((1.0f/compression_duration) * current_running_time, 2.0);
// Warn(!(duration_factor > 0.0f));
denominator = 1.0f + duration_factor;
Verify(!Small_Enough(denominator));
compression_effect = 1.0f / denominator;
Verify(compression_effect >= 0.0f && compression_effect <=1.0f);
return compression_effect * current_volume_level;
}
return current_volume_level;
}
//
//#############################################################################
//#############################################################################
//
AudioControlValue
AudioSource::CalculateSourceVolumeScale()
{
Check(this);
//
// Execute the watchers that will update the volume related
// member parameters
//
ExecuteWatchers();
//
// Calculate the resulting volume scale
//
AudioControlValue
volume_scale;
volume_scale = volumeScale * volumeMixScale * volumeCompressionScale;
Clamp(volume_scale, MinAudioVolume, MaxAudioVolume);
return volume_scale;
}
//
//#############################################################################
//#############################################################################
//
AudioControlValue
AudioSource::CalculateSourceBrightnessScale()
{
Check(this);
AudioControlValue brightness_mix_scale;
brightness_mix_scale = brightnessScale * brightnessMixScale;
Clamp(brightness_mix_scale, MinAudioBrightness, MaxAudioBrightness);
return brightness_mix_scale;
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
)
{
Check(this);
switch (control_ID)
{
//
//----------------------------------------------------------------------
// StartAudioControlID
//----------------------------------------------------------------------
//
case StartAudioControlID:
{
StartMessage message(control_value);
Check(application);
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->PostAudioRequestMessage(
this,
&message
);
}
break;
//
//----------------------------------------------------------------------
// StopAudioControlID
//----------------------------------------------------------------------
//
case StopAudioControlID:
{
StopMessage message;
Check(application);
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->PostAudioRequestMessage(
this,
&message
);
}
break;
//
//----------------------------------------------------------------------
// Misc...
//----------------------------------------------------------------------
//
case VolumeAudioControlID:
VolumeAudioHandler(control_value);
break;
case PitchAudioControlID:
PitchAudioHandler(control_value);
break;
case BrightnessAudioControlID:
BrightnessAudioHandler(control_value);
break;
case AttackVolumeAudioControlID:
AttackVolumeAudioHandler(control_value);
break;
case AttackTimeAudioControlID:
AttackTimeAudioHandler(control_value);
break;
case NoteAudioControlID:
NoteAudioHandler(control_value);
break;
case DurationAudioControlID:
DurationAudioHandler(control_value);
break;
case FlushMessagesAudioControlID:
Check(application);
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->FlushAudioMessages(this);
break;
case NullAudioControlID:
case IdleAudioControlID:
break;
default:
Fail("AudioSource::ReceiveControl - Should never reach here");
break;
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::StartMessageHandler(StartMessage *message)
{
SET_AUDIO_RENDERER();
SET_AUDIO_RENDERER_START_HANDLER();
Check(this);
Check(message);
Verify(message->messageID == StartMessageID);
//
//--------------------------------------------------------------------------
// if double trigger condition exists
// then return
//--------------------------------------------------------------------------
//
AudioTime double_trigger_cutoff(AudioDoubleTriggerCutoff);
#if 0
double_trigger_cutoff = AudioDoubleTriggerCutoff;
#endif
if (
audioSourceState == RunningAudioSourceState &&
GetCurrentRunningTime() <= double_trigger_cutoff
)
{
#ifdef LAB_ONLY
Check(application);
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->doubleTriggerCount++;
#endif
CLEAR_AUDIO_RENDERER_START_HANDLER();
CLEAR_AUDIO_RENDERER();
return;
}
//
//--------------------------------------------------------------------------
// If the source is not stopped then stop it
//--------------------------------------------------------------------------
//
if (audioSourceState != StoppedAudioSourceState)
{
StopMessage stop_message;
StopMessageHandler(&stop_message);
}
//
//--------------------------------------------------------------------------
// Verify that the state is stopped
// Copy the next start state into the current start state
// Calculate duration
//--------------------------------------------------------------------------
//
Verify(audioSourceState == StoppedAudioSourceState);
currentStartState = nextStartState;
currentStartState.CalculateDuration(message->controlValue);
//
//--------------------------------------------------------------------------
// Implementation specific start request
//--------------------------------------------------------------------------
//
StartMessageImplementation();
CLEAR_AUDIO_RENDERER_START_HANDLER();
CLEAR_AUDIO_RENDERER();
}
//
//#############################################################################
//#############################################################################
//
void
#if DEBUG_LEVEL>0
AudioSource::StopMessageHandler(StopMessage *message)
#else
AudioSource::StopMessageHandler(StopMessage*)
#endif
{
SET_AUDIO_RENDERER();
SET_AUDIO_RENDERER_STOP_HANDLER();
Check(this);
Check(message);
Verify(message->messageID == StopMessageID);
//
// if the source is stopped
// then return
//
if (audioSourceState == StoppedAudioSourceState)
{
CLEAR_AUDIO_RENDERER_STOP_HANDLER();
CLEAR_AUDIO_RENDERER();
return;
}
//
// Implementation specific stop request
//
StopMessageImplementation();
CLEAR_AUDIO_RENDERER_STOP_HANDLER();
CLEAR_AUDIO_RENDERER();
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::VolumeAudioHandler(AudioControlValue control_value)
{
Check(this);
Clamp(control_value, MinAudioVolume, MaxAudioVolume);
volumeScale = control_value / (MaxAudioVolume - MinAudioVolume);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::PitchAudioHandler(AudioControlValue control_value)
{
Check(this);
pitchOffset = control_value;
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::BrightnessAudioHandler(AudioControlValue control_value)
{
Check(this);
Clamp(control_value, MinAudioBrightness, MaxAudioBrightness);
brightnessScale = control_value / (MaxAudioBrightness - MinAudioBrightness);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::AttackVolumeAudioHandler(AudioControlValue control_value)
{
Check(this);
Clamp(control_value, MinAudioAttack, MaxAudioAttack);
attackVolumeScale = control_value / (MaxAudioAttack - MinAudioAttack);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::AttackTimeAudioHandler(AudioControlValue control_value)
{
Check(this);
Clamp(control_value, MinAudioAttack, MaxAudioAttack);
attackTimeScale = control_value / (MaxAudioAttack - MinAudioAttack);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::NoteAudioHandler(AudioControlValue control_value)
{
Check(this);
nextStartState.SetNoteValue(control_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::DurationAudioHandler(AudioControlValue control_value)
{
Check(this);
nextStartState.SetDurationValue(control_value);
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::StartImplementation()
{
currentStartState.Start();
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::StopImplementation()
{
Fail("AudioSource::StopImplementation - Should never reach here");
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::SuspendImplementation()
{
StopImplementation();
Check(application);
Check(application->GetAudioRenderer());
Check(audioResource);
suspendFinishedFrame =
application->GetAudioRenderer()->GetAudioFrameCount() +
audioResource->GetSuspendDelay();
#ifdef LAB_ONLY
application->GetAudioRenderer()->sourceSuspendCount++;
#endif
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::ResumeImplementation()
{
StartImplementation();
suspendFinishedFrame = NullAudioFrameCount;
#ifdef LAB_ONLY
Check(application);
Check(application->GetAudioRenderer());
application->GetAudioRenderer()->sourceResumeCount++;
#endif
}
//
//#############################################################################
//#############################################################################
//
void
AudioSource::Execute()
{
Check(this);
//
// Execute source if this is the next execution frame
//
AudioRenderer
*audio_renderer;
Check(application);
audio_renderer = application->GetAudioRenderer();
Check(audio_renderer);
if (nextExecuteFrame <= audio_renderer->GetAudioFrameCount())
{
nextExecuteFrame =
audio_renderer->GetAudioFrameCount() + DefaultAudioFrameDelay;
//
// Update the sources spatial model
// Execute inherited method
// Execute this sources sound model
//
UpdateSpatialModel(audio_renderer->GetAudioHead());
AudioComponent::Execute();
ExecuteModel(False);
}
}
+699
View File
@@ -0,0 +1,699 @@
//===========================================================================//
// File: audsrc.hpp //
// Project: MUNGA Brick: Audio manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/30/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDSRC_HPP)
# define AUDSRC_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
# if !defined(AUDLOC_HPP)
# include <audloc.hpp>
# endif
# if !defined(AUDLVL_HPP)
# include <audlvl.hpp>
# endif
# if !defined(AUDWGT_HPP)
# include <audwgt.hpp>
# endif
# if !defined(AUDTIME_HPP)
# include <audtime.hpp>
# endif
//##########################################################################
//##################### AudioSourceStartState ########################
//##########################################################################
class AudioSourceStartState SIGNATURED
{
public:
AudioSourceStartState();
~AudioSourceStartState();
Logical
TestInstance() const;
void
CalculateDuration(AudioControlValue control_value);
Logical
IsFinishedPlaying();
AudioTime
GetCurrentRunningTime();
void
SetNoteValue(AudioControlValue note_value)
{noteValue = note_value;}
AudioControlValue
GetNoteValue()
{return noteValue;}
void
SetDurationValue(AudioControlValue duration_value);
void
Start()
{startTime = AudioTime::Now();}
private:
AudioControlValue
noteValue;
Logical
isDurationSet;
Logical
hasDuration;
Scalar
duration;
AudioTime
startTime;
AudioTime
endTime;
};
//~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState inlines ~~~~~~~~~~~~~~~~~~~~~~
inline Logical
AudioSourceStartState::IsFinishedPlaying()
{
Check(this);
if (hasDuration)
{
return (AudioTime::Now() > endTime);
}
return False;
}
inline void
AudioSourceStartState::SetDurationValue(AudioControlValue duration_value)
{
Check(this);
isDurationSet = True;
duration = duration_value;
}
inline AudioTime
AudioSourceStartState::GetCurrentRunningTime()
{
Check(this);
return (AudioTime::Now() - startTime);
}
//##########################################################################
//######################### AudioSource ##############################
//##########################################################################
class AudioSource__RequestMessage;
class AudioSource__StartMessage;
class AudioSource__StopMessage;
class AudioSource:
public AudioComponent
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
AudioSource(
PlugStream *stream,
Entity *entity
);
void
AudioSource::AudioSourceX(
AudioResource *audio_resource,
AudioLocation *audio_location,
Entity *entity,
AudioSourcePriority priority,
AudioSourceMixPresence mix_presence,
AudioControlValue volume_mix_level,
AudioPitchCents pitch_mix_offset,
AudioControlValue brightness_mix_level,
Logical has_compression_curve,
const AudioTime &compression_duration,
Logical use_brightness_scale,
Logical use_attack_time_scale
);
~AudioSource();
Logical
TestInstance() const;
static void
BuildFromPage(
PlugStream *stream,
NameList *name_list,
ClassID class_ID,
ObjectID object_ID
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Location methods
//
public:
AudioLocation*
GetAudioLocation();
void
UpdateSpatialModel(AudioHead *audio_head);
Scalar
GetDistanceToSource();
Logical
IsAudioSourceClipped(AudioHead *audio_head);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Resource methods
//
public:
void
SetAudioResource(AudioResource *audio_resource);
AudioResource*
GetAudioResource();
AudioVoiceCount
GetAudioVoiceCount();
AudioRenderType
GetAudioRenderType();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Current State/Status Accessors
//
public:
void
AssignAudioSourceState(AudioSourceState audio_source_state);
AudioSourceState
GetAudioSourceState();
Logical
IsFinishedPlaying();
AudioTime
GetCurrentRunningTime();
AudioControlValue
GetCurrentNoteValue();
AudioControlValue
CalculateSourceAttackVolumeScale();
Logical
UseSourceAttackTime();
AudioControlValue
CalculateSourceAttackTime();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Priority Accessors
//
public:
void
SetAudioSourcePriority(AudioSourcePriority audio_source_priority);
AudioSourcePriority
GetAudioSourcePriority();
AudioWeighting
CalculateAudioWeighting();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Mixing & Logical compression methods
//
public:
AudioSourceMixPresence
GetAudioSourceMixPresence();
void
SetVolumeCompressionScale(AudioControlValue compression_scale);
AudioControlValue
CalculateSourceCompressionEffect();
virtual AudioControlValue
CalculateSourceVolumeScale();
virtual AudioPitchCents
CalculateSourcePitchOffset();
Logical
UseSourceBrightnessScale();
virtual AudioControlValue
CalculateSourceBrightnessScale();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Controller methods
//
public:
void
ReceiveControl(
AudioControlID control_ID,
AudioControlValue control_value
);
virtual void
VolumeAudioHandler(AudioControlValue);
virtual void
PitchAudioHandler(AudioControlValue);
virtual void
BrightnessAudioHandler(AudioControlValue);
virtual void
AttackVolumeAudioHandler(AudioControlValue);
virtual void
AttackTimeAudioHandler(AudioControlValue);
virtual void
NoteAudioHandler(AudioControlValue);
virtual void
DurationAudioHandler(AudioControlValue);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// State implementations
//
public:
virtual void
StartImplementation();
virtual void
StopImplementation();
virtual void
SuspendImplementation();
virtual void
ResumeImplementation();
protected:
virtual void
StartMessageImplementation() {}
virtual void
StopMessageImplementation() {}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Execution
//
public:
Logical
RequiresMaintenance(AudioHead *audio_head);
Logical
CanResume(AudioHead *audio_head);
void
Execute();
protected:
virtual void
ExecuteModel(Logical force_update) {}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
enum {
StartMessageID = AudioComponent::NextMessageID,
StopMessageID,
NextMessageID
};
typedef AudioSource__RequestMessage
RequestMessage;
typedef AudioSource__StartMessage
StartMessage;
typedef AudioSource__StopMessage
StopMessage;
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
void
StartMessageHandler(StartMessage *message);
void
StopMessageHandler(StopMessage *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation
ClassDerivations;
static SharedData
DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
//
// Location data
//
AudioLocation
*audioLocation;
//
// Resource data
//
AudioResource
*audioResource;
//
// State/Status data
//
AudioSourceState
audioSourceState;
AudioSourceStartState
nextStartState,
currentStartState;
AudioControlValue
attackVolumeScale;
Logical
useAttackTimeScale;
AudioControlValue
attackTimeScale;
//
// Priority data
//
AudioSourcePriority
audioSourcePriority;
//
// Mixing and compression
//
AudioSourceMixPresence
audioSourceMixPresence;
AudioControlValue
volumeCompressionScale;
Logical
hasCompressionCurve;
AudioTime
compressionDuration;
AudioControlValue
volumeMixScale;
AudioPitchCents
pitchMixOffset;
Logical
useBrightnessScale;
AudioControlValue
brightnessMixScale;
AudioControlValue
volumeScale;
AudioPitchCents
pitchOffset;
AudioControlValue
brightnessScale;
//
// Execution
//
AudioFrameCount
nextExecuteFrame;
AudioFrameCount
suspendFinishedFrame;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Location methods
//
inline AudioLocation*
AudioSource::GetAudioLocation()
{
Check(this);
return audioLocation;
}
inline void
AudioSource::UpdateSpatialModel(AudioHead *audio_head)
{
Check(this);
Check(audioLocation);
audioLocation->UpdateSpatialModel(audio_head);
}
inline Scalar
AudioSource::GetDistanceToSource()
{
Check(this);
Check(audioLocation);
return audioLocation->GetDistanceToSource();
}
inline Logical
AudioSource::IsAudioSourceClipped(AudioHead *audio_head)
{
Check(this);
Check(audioLocation);
return audioLocation->IsAudioLocationClipped(audio_head);
}
//
// Resource methods
//
inline AudioResource*
AudioSource::GetAudioResource()
{
Check(this);
return audioResource;
}
inline AudioVoiceCount
AudioSource::GetAudioVoiceCount()
{
Check(this);
Check(audioResource);
return audioResource->GetVoiceCount();
}
inline AudioRenderType
AudioSource::GetAudioRenderType()
{
Check(this);
Check(audioResource);
return audioResource->GetAudioRenderType();
}
//
// Current State/Status Accessors
//
inline AudioSourceState
AudioSource::GetAudioSourceState()
{
Check(this);
return audioSourceState;
}
inline Logical
AudioSource::IsFinishedPlaying()
{
Check(this);
return currentStartState.IsFinishedPlaying();
}
inline AudioTime
AudioSource::GetCurrentRunningTime()
{
Check(this);
Verify(audioSourceState == RunningAudioSourceState);
return currentStartState.GetCurrentRunningTime();
}
inline AudioControlValue
AudioSource::GetCurrentNoteValue()
{
Check(this);
return currentStartState.GetNoteValue();
}
inline AudioControlValue
AudioSource::CalculateSourceAttackVolumeScale()
{
Check(this);
return attackVolumeScale;
}
inline Logical
AudioSource::UseSourceAttackTime()
{
Check(this);
return useAttackTimeScale;
}
inline AudioControlValue
AudioSource::CalculateSourceAttackTime()
{
Check(this);
return attackTimeScale;
}
//
// Priority Accessors
//
inline void
AudioSource::SetAudioSourcePriority(
AudioSourcePriority audio_source_priority
)
{
Check(this);
audioSourcePriority = audio_source_priority;
}
inline AudioSourcePriority
AudioSource::GetAudioSourcePriority()
{
Check(this);
return audioSourcePriority;
}
inline AudioWeighting
AudioSource::CalculateAudioWeighting()
{
Check(this);
AudioWeighting
audio_weight(
GetAudioSourcePriority(),
CalculateSourceVolumeScale()
);
return audio_weight;
}
//
// Mixing & Logical compression methods
//
inline AudioSourceMixPresence
AudioSource::GetAudioSourceMixPresence()
{
Check(this);
return audioSourceMixPresence;
}
inline void
AudioSource::SetVolumeCompressionScale(
AudioControlValue compression_level
)
{
Check(this);
volumeCompressionScale = compression_level;
}
inline AudioPitchCents
AudioSource::CalculateSourcePitchOffset()
{
Check(this);
return pitchMixOffset + pitchOffset;
}
inline Logical
AudioSource::UseSourceBrightnessScale()
{
Check(this);
return useBrightnessScale;
}
//
// Execute
//
inline Logical
AudioSource::RequiresMaintenance(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
return (nextExecuteFrame <= audio_head->GetAudioFrameCount());
}
inline Logical
AudioSource::CanResume(AudioHead *audio_head)
{
Check(this);
Check(audio_head);
return (suspendFinishedFrame <= audio_head->GetAudioFrameCount());
}
//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__RequestMessage ~~~~~~~~~~~~~~~~~~~~~~~
class AudioSource__RequestMessage:
public Receiver::Message
{
public:
AudioSource__RequestMessage(
Receiver::MessageID id,
size_t message_length,
AudioControlID control_ID,
AudioControlValue control_value
);
AudioControlID
controlID;
AudioControlValue
controlValue;
};
inline AudioSource__RequestMessage::AudioSource__RequestMessage(
Receiver::MessageID message_ID,
size_t message_length,
AudioControlID control_ID,
AudioControlValue control_value
):
Receiver::Message(
message_ID,
message_length
)
{
controlID = control_ID;
controlValue = control_value;
}
//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StartMessage ~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioSource__StartMessage:
public AudioSource::RequestMessage
{
public:
AudioSource__StartMessage(AudioControlValue control_value);
};
inline AudioSource__StartMessage::AudioSource__StartMessage(
AudioControlValue control_value
):
AudioSource::RequestMessage(
AudioSource::StartMessageID,
sizeof(AudioSource__StartMessage),
StartAudioControlID,
control_value
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StopMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~
class AudioSource__StopMessage:
public AudioSource::RequestMessage
{
public:
AudioSource__StopMessage();
};
inline AudioSource__StopMessage::AudioSource__StopMessage():
AudioSource::RequestMessage(
AudioSource::StopMessageID,
sizeof(AudioSource__StopMessage),
StopAudioControlID,
0.0f
)
{
}
#endif
+83
View File
@@ -0,0 +1,83 @@
//===========================================================================//
// File: audtime.cpp //
// Project: MUNGA Brick: Audio Renderer //
// Contents: Interface declarations for AudioTim //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/08/96 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDTIME_HPP)
#include <audtime.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(AUDREND_HPP)
#include <audrend.hpp>
#endif
//#############################################################################
//############################# AudioTime ###############################
//#############################################################################
const AudioTime
AudioTime::Null;
//
//#############################################################################
//#############################################################################
//
Logical
AudioTime::TestInstance() const
{
return True;
}
//
//#############################################################################
//#############################################################################
//
AudioTime
AudioTime::Now()
{
Check(application);
Check(application->GetAudioRenderer());
return AudioTime(application->GetAudioRenderer()->GetAudioFrameCount());
}
//
//#############################################################################
//#############################################################################
//
AudioFrameCount
AudioTime::Seconds_To_Frames(Scalar seconds) const
{
Check(application);
Check(application->GetAudioRenderer());
return
(seconds * application->GetAudioRenderer()->GetCalibrationRate() + 0.5f);
}
//
//#############################################################################
//#############################################################################
//
Scalar
AudioTime::Frames_To_Seconds(AudioFrameCount frames) const
{
Check(application);
Check(application->GetAudioRenderer());
return
((Scalar)frames / application->GetAudioRenderer()->GetCalibrationRate());
}
+279
View File
@@ -0,0 +1,279 @@
//===========================================================================//
// File: audtime.hpp //
// Project: MUNGA Brick: Audio Renderer //
// Contents: Interface declarations for AudioTim //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/08/96 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDTIME_HPP)
# define AUDTIME_HPP
# if !defined(SCALAR_HPP)
# include <scalar.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
//##########################################################################
//########################## AudioTime ###############################
//##########################################################################
class AudioTime SIGNATURED
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
AudioTime();
AudioTime(const AudioTime&);
AudioTime(Scalar seconds);
AudioTime(AudioFrameCount frame_count);
~AudioTime();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Assignment
//
public:
AudioTime&
operator=(const AudioTime&);
AudioTime&
operator=(Scalar seconds);
AudioTime&
operator=(AudioFrameCount frame_count);
operator Scalar() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Logical Operators
//
public:
Logical
operator<(const AudioTime&) const;
Logical
operator<=(const AudioTime&) const;
Logical
operator>(const AudioTime&) const;
Logical
operator>=(const AudioTime&) const;
Logical
operator==(const AudioTime&) const;
Logical
operator!=(const AudioTime&) const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Addition Operators
//
public:
operator AudioFrameCount() const;
AudioTime
operator+(const AudioTime&) const;
AudioTime
operator-(const AudioTime&) const;
AudioTime&
operator+=(const AudioTime &t);
AudioTime&
operator-=(const AudioTime &t);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public Constants
//
public:
static const AudioTime
Null;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Current Time
//
public:
static AudioTime
Now();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Methods
//
private:
AudioFrameCount
Seconds_To_Frames(Scalar seconds) const;
Scalar
Frames_To_Seconds(AudioFrameCount frames) const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
AudioFrameCount
frameCount;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTime inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Construction, Destruction, and Testing
//
inline AudioTime::AudioTime():
frameCount(NullAudioFrameCount)
{
}
inline AudioTime::AudioTime(const AudioTime &audio_time):
frameCount(audio_time.frameCount)
{
}
inline AudioTime::AudioTime(Scalar seconds)
{
frameCount = Seconds_To_Frames(seconds);
}
inline AudioTime::AudioTime(AudioFrameCount frame_count):
frameCount(frame_count)
{
}
inline AudioTime::~AudioTime()
{
}
//
// Assignment
//
inline AudioTime&
AudioTime::operator=(const AudioTime &audio_time)
{
Check(this);
Check(&audio_time);
frameCount = audio_time.frameCount;
return *this;
}
inline AudioTime&
AudioTime::operator=(Scalar seconds)
{
Check(this);
frameCount = Seconds_To_Frames(seconds);
return *this;
}
inline AudioTime&
AudioTime::operator=(AudioFrameCount frame_count)
{
Check(this);
frameCount = frame_count;
return *this;
}
inline
AudioTime::operator Scalar() const
{
Check(this);
return Frames_To_Seconds(frameCount);
}
//
// Logical Operators
//
inline Logical
AudioTime::operator<(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount < audio_time.frameCount;
}
inline Logical
AudioTime::operator<=(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount <= audio_time.frameCount;
}
inline Logical
AudioTime::operator>(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount > audio_time.frameCount;
}
inline Logical
AudioTime::operator>=(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount >= audio_time.frameCount;
}
inline Logical
AudioTime::operator==(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount == audio_time.frameCount;
}
inline Logical
AudioTime::operator!=(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return frameCount != audio_time.frameCount;
}
//
// Addition Operators
//
inline AudioTime::operator AudioFrameCount() const
{
Check(this);
return frameCount;
}
inline AudioTime
AudioTime::operator+(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return AudioTime(frameCount + audio_time.frameCount);
}
inline AudioTime
AudioTime::operator-(const AudioTime &audio_time) const
{
Check(this);
Check(&audio_time);
return AudioTime(frameCount - audio_time.frameCount);
}
inline AudioTime&
AudioTime::operator+=(const AudioTime &audio_time)
{
Check(this);
Check(&audio_time);
frameCount += audio_time.frameCount;
return *this;
}
inline AudioTime&
AudioTime::operator-=(const AudioTime &audio_time)
{
Check(this);
Check(&audio_time);
frameCount -= audio_time.frameCount;
return *this;
}
#endif
+160
View File
@@ -0,0 +1,160 @@
//===========================================================================//
// File: l4audres.cpp //
// Project: MUNGA Brick: Audio Renderer Manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/10/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDTOOLS_HPP)
# include <audtools.hpp>
#endif
#include <fstream.h>
#include <io.h>
#include <sys\stat.h>
#if !defined(AUDIO_HPP)
# include <audio.hpp>
#endif
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
//#############################################################################
//###################### AudioCreateSymbols #############################
//#############################################################################
//
//#############################################################################
//#############################################################################
//
AudioCreateSymbols::AudioCreateSymbols()
{
}
//
//#############################################################################
//#############################################################################
//
AudioCreateSymbols::~AudioCreateSymbols()
{
}
//
//#############################################################################
//#############################################################################
//
void
AudioCreateSymbols::MakeFileReadWrite(const CString &file_name)
{
if (access(file_name, 0) == 0)
{
int amode = S_IREAD|S_IWRITE;
#if DEBUG_LEVEL>0
int ret =
#endif
chmod(file_name, amode);
Verify(ret == 0);
}
}
//
//#############################################################################
//#############################################################################
//
void
AudioCreateSymbols::Execute()
{
//
// Make file read/write
//
CString file_name("audio\\symbols.scp");
MakeFileReadWrite(file_name);
//
// Open the file for writing
//
ofstream symbol_file(file_name, ios::out);
Verify(symbol_file);
symbol_file << "[macro]\n";
//
// Audio
//
WriteEntryStream(symbol_file);
}
//
//#############################################################################
//#############################################################################
//
void
AudioCreateSymbols::WriteEntryStream(ofstream &symbol_file)
{
#define WRITE_ENTRY(name)\
{\
Verify(symbol_file);\
symbol_file << #name;\
symbol_file << "=";\
symbol_file << name;\
symbol_file << "\n";\
}
//
// Solids
//
WRITE_ENTRY(BoxedSolid::StoneMaterial);
WRITE_ENTRY(BoxedSolid::GravelMaterial);
WRITE_ENTRY(BoxedSolid::ConcreteMaterial);
WRITE_ENTRY(BoxedSolid::WoodMaterial);
WRITE_ENTRY(BoxedSolid::RockMaterial);
WRITE_ENTRY(BoxedSolid::OurCraftMaterial);
WRITE_ENTRY(BoxedSolid::OtherCraftMaterial);
//
// Audio
//
WRITE_ENTRY(TransientAudioRenderType);
WRITE_ENTRY(SustainedAudioRenderType);
WRITE_ENTRY(MinAudioSourcePriority);
WRITE_ENTRY(LowAudioSourcePriority);
WRITE_ENTRY(MedAudioSourcePriority);
WRITE_ENTRY(HighAudioSourcePriority);
WRITE_ENTRY(MaxAudioSourcePriority);
WRITE_ENTRY(MinAudioSourceMixPresence);
WRITE_ENTRY(LowAudioSourceMixPresence);
WRITE_ENTRY(MedAudioSourceMixPresence);
WRITE_ENTRY(HighAudioSourceMixPresence);
WRITE_ENTRY(MaxAudioSourceMixPresence);
WRITE_ENTRY(ManualAudioSourceMixPresence);
WRITE_ENTRY(NullAudioControlID);
WRITE_ENTRY(NoteAudioControlID);
WRITE_ENTRY(AttackVolumeAudioControlID);
WRITE_ENTRY(AttackTimeAudioControlID);
WRITE_ENTRY(DurationAudioControlID);
WRITE_ENTRY(VolumeAudioControlID);
WRITE_ENTRY(PitchAudioControlID);
WRITE_ENTRY(BrightnessAudioControlID);
WRITE_ENTRY(StartAudioControlID);
WRITE_ENTRY(StopAudioControlID);
WRITE_ENTRY(IdleAudioControlID);
WRITE_ENTRY(FlushMessagesAudioControlID);
WRITE_ENTRY(TempoAudioControlID);
}
+51
View File
@@ -0,0 +1,51 @@
//===========================================================================//
// File: audtools.hpp //
// Project: MUNGA Brick: Audio Renderer Manager //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/10/95 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDTOOLS_HPP)
# define AUDTOOLS_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(CSTR_HPP)
# include <cstr.hpp>
# endif
//##########################################################################
//##################### AudioCreateSymbols ###########################
//##########################################################################
class AudioCreateSymbols
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction and testing
//
public:
AudioCreateSymbols();
~AudioCreateSymbols();
void Execute();
private:
static void
MakeFileReadWrite(const CString &file_name);
protected:
virtual void
WriteEntryStream(ofstream &symbol_file);
};
#endif
+38
View File
@@ -0,0 +1,38 @@
//===========================================================================//
// File: audwgt.cpp //
// Project: MUNGA Brick: Audio Renderer //
// Contents: Implementation for audio weighting //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/02/96 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AUDWGT_HPP)
# include <audwgt.hpp>
#endif
//#############################################################################
//########################## AudioWeighting #############################
//#############################################################################
const AudioWeighting
AudioWeighting::Null;
//
//#############################################################################
//#############################################################################
//
Logical
AudioWeighting::TestInstance() const
{
return True;
}
+164
View File
@@ -0,0 +1,164 @@
//===========================================================================//
// File: audwgt.hpp //
// Project: MUNGA Brick: Audio Renderer //
// Contents: Interface specification for audio weighting //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/02/96 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1996, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AUDWGT_HPP)
#define AUDWGT_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(AUDIO_HPP)
# include <audio.hpp>
# endif
//##########################################################################
//######################## AudioWeighting ############################
//##########################################################################
class AudioWeighting SIGNATURED
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, and Testing
//
public:
AudioWeighting();
AudioWeighting(const AudioWeighting&);
AudioWeighting(
AudioSourcePriority audio_priority,
AudioControlValue audio_volume
);
AudioWeighting&
operator=(const AudioWeighting&);
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Logical Operators
//
public:
Logical
operator<(const AudioWeighting&) const;
Logical
operator<=(const AudioWeighting&) const;
Logical
operator>(const AudioWeighting&) const;
Logical
operator>=(const AudioWeighting&) const;
Logical
operator==(const AudioWeighting&) const;
Logical
operator!=(const AudioWeighting&) const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public Constants
//
public:
static const AudioWeighting
Null;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
Scalar
weight;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioWeighting inlines ~~~~~~~~~~~~~~~~~~~~~~~
inline AudioWeighting::AudioWeighting():
weight(0.0f)
{
}
inline AudioWeighting::AudioWeighting(const AudioWeighting &audio_weighting):
weight(audio_weighting.weight)
{
}
inline AudioWeighting::AudioWeighting(
AudioSourcePriority audio_priority,
AudioControlValue audio_volume
)
{
Verify(
(Enumeration)audio_priority >= 0 &&
(Enumeration)audio_priority < AUDIO_SOURCE_PRIORITY_COUNT
);
Verify(
(Enumeration)audio_priority >= (Enumeration)MinAudioSourcePriority &&
(Enumeration)audio_priority <= (Enumeration)MaxAudioSourcePriority
);
Verify(
audio_volume >= 0.0f &&
audio_volume <= 1.0f
);
weight = 0.0f -(Scalar)audio_priority - audio_volume;
}
inline AudioWeighting&
AudioWeighting::operator=(const AudioWeighting &audio_weighting)
{
Check(this);
weight = audio_weighting.weight;
return *this;
}
inline Logical
AudioWeighting::operator<(const AudioWeighting &audio_weighting) const
{
Check(this);
return weight < audio_weighting.weight;
}
inline Logical
AudioWeighting::operator<=(const AudioWeighting &audio_weighting) const
{
Check(this);
return weight <= audio_weighting.weight;
}
inline Logical
AudioWeighting::operator>(const AudioWeighting &audio_weighting) const
{
Check(this);
return weight > audio_weighting.weight;
}
inline Logical
AudioWeighting::operator>=(const AudioWeighting &audio_weighting) const
{
Check(this);
return weight >= audio_weighting.weight;
}
inline Logical
AudioWeighting::operator==(const AudioWeighting &audio_weighting) const
{
Check(this);
return Close_Enough(weight, audio_weighting.weight, 0.01f);
}
inline Logical
AudioWeighting::operator!=(const AudioWeighting &audio_weighting) const
{
Check(this);
return !Close_Enough(weight, audio_weighting.weight, 0.01f);
}
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
//===========================================================================//
// File: average.cpp //
// Project: MUNGA Brick: Renderer //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 12/14/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(AVERAGE_HPP)
# include <average.hpp>
#endif
+317
View File
@@ -0,0 +1,317 @@
//===========================================================================//
// File: average.hpp //
// Project: MUNGA Brick: Renderer //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 12/14/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(AVERAGE_HPP)
# define AVERAGE_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
//##########################################################################
//########################### AverageOf ##############################
//##########################################################################
template <class T> class AverageOf SIGNATURED
{
public:
//
//-----------------------------------------------------------------------
// Constructor, Destructor, Testing
//-----------------------------------------------------------------------
//
AverageOf();
AverageOf(
size_t size,
T initial=(T)0
);
~AverageOf();
Logical
TestInstance() const;
//
//-----------------------------------------------------------------------
// SetSize
//-----------------------------------------------------------------------
//
void
SetSize(
size_t size,
T initial=(T)0
);
//
//-----------------------------------------------------------------------
// Add
//-----------------------------------------------------------------------
//
void
Add(T value);
//
//-----------------------------------------------------------------------
// CalculateAverage
//-----------------------------------------------------------------------
//
T
CalculateAverage();
//
//-----------------------------------------------------------------------
// CalculateOlympicAverage
//-----------------------------------------------------------------------
//
T
CalculateOlympicAverage();
//
//-----------------------------------------------------------------------
// Calculate Trend of Average
//-----------------------------------------------------------------------
//
Scalar
CalculateTrend();
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
size_t size;
size_t next;
T *array;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AverageOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AverageOf<T>::AverageOf()
{
array = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AverageOf<T>::AverageOf(
size_t the_size,
T initial
)
{
array = NULL;
SetSize(the_size, initial);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AverageOf<T>::SetSize(
size_t the_size,
T initial
)
{
if (array != NULL)
{
Unregister_Pointer(array);
delete[] array;
}
size = the_size;
array = new T[size];
Register_Pointer(array);
next = 0;
for (size_t i = 0; i < size; i++)
{
Check_Pointer(array);
Verify(i < size);
array[i] = initial;
Check_Fpu();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
AverageOf<T>::~AverageOf()
{
Unregister_Pointer(array);
delete[] array;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> Logical
AverageOf<T>::TestInstance() const
{
Check_Pointer(array);
Verify(next < size);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> void
AverageOf<T>::Add(T value)
{
Check(this);
Check_Pointer(array);
Verify(next < size);
array[next] = value;
++next;
if (next >= size)
{
Verify(next == size);
next = 0;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> T
AverageOf<T>::CalculateAverage()
{
Check(this);
size_t i;
T accumulate;
for (i = 0, accumulate = (T)0; i < size; i++)
{
Check_Pointer(array);
Verify(i < size);
accumulate += array[i];
Check_Fpu();
}
Verify(!Small_Enough((T)size));
return (accumulate / (T)size);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> T
AverageOf<T>::CalculateOlympicAverage()
{
Check(this);
size_t i;
T accumulate, min_value, max_value;
Verify(0 < size);
min_value = array[0];
max_value = array[0];
Check_Fpu();
for (i = 0, accumulate = (T)0; i < size; i++)
{
Check_Pointer(array);
Verify(i < size);
accumulate += array[i];
Check_Fpu();
min_value = Min(array[i], min_value);
max_value = Max(array[i], max_value);
Check_Fpu();
}
accumulate -= min_value;
accumulate -= max_value;
Check_Fpu();
Verify(!Small_Enough((T)(size - 2)));
return (accumulate / (T)(size - 2));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> Scalar
AverageOf<T>::CalculateTrend()
{
Check(this);
size_t i;
Scalar f = 0.0f;
Scalar fx = 0.0f;
Scalar x1 = size;
Scalar x2 = x1*x1/2.0f;
Scalar x3 = x2 + x1*x1*x1/3.0f + x1/6.0f;
x2 += x1/2.0f;
i = next;
Scalar t = 1.0f;
do
{
f += array[i];
fx += t*array[i];
t += 1.0f;
if (++i == size)
{
i = 0;
}
} while (i != next);
return (x1*fx - x2*f) / (x1*x3 - x2*x2);
}
//##########################################################################
//######################## StaticAverageOf ###########################
//##########################################################################
template <class T> class StaticAverageOf SIGNATURED
{
public:
//
//-----------------------------------------------------------------------
// Constructor, Destructor, Testing
//-----------------------------------------------------------------------
//
StaticAverageOf()
{size = (T)0; total = (T)0;}
~StaticAverageOf()
{}
Logical
TestInstance() const
{return True;}
//
//-----------------------------------------------------------------------
// Add
//-----------------------------------------------------------------------
//
void
Add(T value)
{Check(this); size++; total += value;}
//
//-----------------------------------------------------------------------
// CalculateAverage
//-----------------------------------------------------------------------
//
T
CalculateAverage()
{Check(this); return (size == 0) ? ((T)0) : (total / (T)size);}
//
//-----------------------------------------------------------------------
// GetSize
//-----------------------------------------------------------------------
//
size_t
GetSize()
{Check(this); return size;}
private:
//
//-----------------------------------------------------------------------
// Private data
//-----------------------------------------------------------------------
//
size_t size;
T total;
};
#endif
+458
View File
@@ -0,0 +1,458 @@
//===========================================================================//
// File: bndgbox.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box based spatialization //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/08/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BNDGBOX_HPP)
# include <bndgbox.hpp>
#endif
#if !defined(ORIGIN_HPP)
#include <origin.hpp>
#endif
#if !defined(LINE_HPP)
#include <line.hpp>
#endif
//#############################################################################
//############################## BoundingBox ############################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox::BoundingBox(const ExtentBox &extents):
ExtentBox(extents)
{
Check_Pointer(this);
Check(&extents);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox::BoundingBox()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
BoundingBox::PlaceBoundingBox(const Origin& origin)
{
Check(this);
Check(&origin);
Dump(origin);
minX += origin.linearPosition.x;
maxX += origin.linearPosition.x;
minY += origin.linearPosition.y;
maxY += origin.linearPosition.y;
minZ += origin.linearPosition.z;
maxZ += origin.linearPosition.z;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox::~BoundingBox()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::Intersects(const ExtentBox &extents)
{
Check(this);
Check(&extents);
if (ExtentBox::Intersects(extents))
{
ExtentBox slice;
slice.Intersect(*this, extents);
return IntersectsBounded(slice);
}
else
{
return False;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::Intersects(
const ExtentBox &extents,
ExtentBox *slice
)
{
Check(this);
Check(&extents);
Check_Pointer(slice);
if (ExtentBox::Intersects(extents))
{
slice->Intersect(*this, extents);
return IntersectsBounded(*slice);
}
else
{
return False;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::Contains(const Point3D &point)
{
Check(this);
Check(&point);
if (ExtentBox::Contains(point))
{
return ContainsBounded(point);
}
else
{
return False;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoundingBox::FindDistanceBelow(const Point3D &point)
{
Check(this);
Check(&point);
if (
minX <= point.x && maxX >= point.x && minY <= point.y
&& minZ <= point.z && maxZ >= point.z
)
{
return FindDistanceBelowBounded(point);
}
else
{
return -1.0f;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::HitBy(Line *line)
{
Check(this);
Check(line);
Scalar
enter,
leave,
perpendicular,
drift,
distance;
//
//--------------------
// Set up for the test
//--------------------
//
Logical entered = False;
Logical left = False;
for (int i=0; i<6; ++i)
{
//
//--------------------------------------------------------------------
// Figure out what axis we are dealing with, then based upon the
// direction of the face, find out the distance from the origin to the
// place against the normal, and find out how fast the perpendicular
// distance changes with a unit movement along the line
//--------------------------------------------------------------------
//
int face = i;
int axis = face >> 1;
if (face&1)
{
perpendicular = line->origin[axis] - (*this)[face];
drift = line->direction[axis];
}
else
{
perpendicular = (*this)[face] - line->origin[axis];
drift = -line->direction[axis];
}
//
//-------------------------------------------------------------------
// If the line is parallel to the face, figure out whether or not the
// line origin lies within the face's half-space
//-------------------------------------------------------------------
//
if (Small_Enough(drift))
{
if (perpendicular > 0.0f)
{
return False;
}
else
{
continue;
}
}
//
//--------------------------------------------------------------------
// If the drift is towards the plane's halfspace, this plane is one of
// the one through which the line could enter the node
//--------------------------------------------------------------------
//
distance = -perpendicular / drift;
if (drift < 0.0f)
{
if (!entered)
{
entered = True;
enter = distance;
}
else if (distance > enter)
{
enter = distance;
}
if (enter > line->length)
{
return False;
}
}
//
//--------------------------------------------------------------------
// If the drift is towards the plane's halfspace, this plane is one of
// the one through which the line could enter the node
//--------------------------------------------------------------------
//
else
{
if (!left)
{
left = True;
leave = distance;
}
else if (distance < leave)
{
leave = distance;
}
if (leave < 0.0f)
{
return False;
}
}
}
//
//-----------------------------------------------------------------------
// If we exit the loop, then make sure that we actually hit the interior,
// and let the box figure out if the what happens inside it
//-----------------------------------------------------------------------
//
if (enter <= leave)
{
return HitByBounded(line, enter, leave);
}
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
#if DEBUG_LEVEL>0
BoundingBox::IntersectsBounded(const ExtentBox &extents)
#else
BoundingBox::IntersectsBounded(const ExtentBox &)
#endif
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
#if DEBUG_LEVEL>0
BoundingBox::ContainsBounded(const Point3D &point)
#else
BoundingBox::ContainsBounded(const Point3D &)
#endif
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoundingBox::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
Scalar result = point.y - maxY;
return Max(result, 0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::HitByBounded(
Line *line,
Scalar enters,
#if DEBUG_LEVEL>0
Scalar leaves
#else
Scalar
#endif
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
line->length = Max(enters, 0.0f);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBox::TestInstance() const
{
return True;
}
//#############################################################################
//######################### BoundingBoxCollision ########################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBoxCollision::TestInstance() const
{
return True;
}
//#############################################################################
//####################### BoundingBoxCollisionList ######################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBoxCollisionList::BoundingBoxCollisionList(int max_length)
{
listStart = new BoundingBoxCollision[max_length];
Register_Pointer(listStart);
maxCollisions = max_length;
Reset();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxCollisionList::AddCollisionToList(
BoundingBox *tree_volume,
const ExtentBox &slice
)
{
Check(tree_volume);
Check(&slice);
Check(this);
Check_Pointer(nextCollision);
Verify(collisionsLeft);
nextCollision->treeVolume = tree_volume;
nextCollision->collisionSlice = slice;
++nextCollision;
--collisionsLeft;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBoxCollisionList::TestInstance() const
{
return True;
}
//#############################################################################
//########################### TaggedBoundingBox #########################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
TaggedBoundingBox::TaggedBoundingBox(void *tag)
{
tagPointer = tag;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
TaggedBoundingBox::TaggedBoundingBox(
const ExtentBox &extents,
void *tag
):
BoundingBox(extents)
{
tagPointer = tag;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
TaggedBoundingBox::~TaggedBoundingBox()
{
}
#if defined(TEST_CLASS)
# include "bndgbox.tcp"
#endif
+214
View File
@@ -0,0 +1,214 @@
//===========================================================================//
// File: bndgbox.hh //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Interface specification of bounding-box based spatialization //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/08/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(BNDGBOX_HPP)
# define BNDGBOX_HPP
# if !defined(EXTNTBOX_HPP)
# include <extntbox.hpp>
# endif
class Line;
class Point3D;
class Origin;
class BoundingBoxTreeNode;
class BoundingBoxList;
class BoundingBoxCollision;
//##########################################################################
//########################### BoundingBox ############################
//##########################################################################
class BoundingBox:
public ExtentBox
{
friend class BoundingBoxTreeNode;
friend class BoundingBoxList;
public:
BoundingBox();
BoundingBox(const ExtentBox &extents);
virtual ~BoundingBox();
Logical
Intersects(const ExtentBox &extents);
Logical
Intersects(
const ExtentBox &extents,
ExtentBox *slice
);
Logical
Contains(const Point3D &point);
Scalar
FindDistanceBelow(const Point3D &point);
Logical
HitBy(Line *line);
void
PlaceBoundingBox(const Origin& origin);
protected:
virtual Logical
IntersectsBounded(const ExtentBox &extents);
virtual Logical
ContainsBounded(const Point3D &point);
virtual Scalar
FindDistanceBelowBounded(const Point3D &point);
virtual Logical
HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
);
public:
static Logical
TestClass();
virtual Logical
TestInstance() const;
};
//##########################################################################
//###################### BoundingBoxCollision ########################
//##########################################################################
class BoundingBoxCollision SIGNATURED
{
public:
BoundingBox
*treeVolume;
ExtentBox
collisionSlice;
BoundingBox*
GetTreeVolume()
{Check(this); return treeVolume;}
Logical
TestInstance() const;
};
//##########################################################################
//#################### BoundingBoxCollisionList ######################
//##########################################################################
class BoundingBoxCollisionList SIGNATURED
{
friend class BoundingBoxTreeNode;
friend class BoundingBoxList;
protected:
BoundingBoxCollision
*listStart,
*nextCollision;
int
maxCollisions,
collisionsLeft;
public:
BoundingBoxCollisionList(int max_length);
~BoundingBoxCollisionList()
{Check(this); Unregister_Pointer(listStart); delete[] listStart;}
void
Reset()
{nextCollision = listStart; collisionsLeft = maxCollisions;}
void
AddCollisionToList(
BoundingBox *tree_volume,
const ExtentBox &slice
);
BoundingBoxCollision&
operator[](int index)
{
Check(this); Verify((unsigned)index < maxCollisions);
return listStart[index];
}
int
GetCollisionCount()
{Check(this); return maxCollisions - collisionsLeft;}
int
GetCollisionsLeft()
{Check(this); return collisionsLeft;}
Logical
TestInstance() const;
};
//##########################################################################
//######################## TaggedBoundingBox #########################
//##########################################################################
class TaggedBoundingBox:
public BoundingBox
{
public:
void*
GetTagPointer()
{Check(this); return tagPointer;}
protected:
TaggedBoundingBox(void *tag = NULL);
TaggedBoundingBox(
const ExtentBox &extents,
void *tag = NULL
);
~TaggedBoundingBox();
void *tagPointer;
};
//##########################################################################
//####################### TaggedBoundingBoxOf ########################
//##########################################################################
template <class T> class TaggedBoundingBoxOf:
public TaggedBoundingBox
{
public:
TaggedBoundingBoxOf(T *tag);
TaggedBoundingBoxOf(
const ExtentBox &extents,
T *tag = NULL
);
~TaggedBoundingBoxOf();
T*
GetTagPointer()
{return (T*)tagPointer;}
};
//~~~~~~~~~~~~~~~~~~~~~~~~ TaggedBoundingBoxOf templates ~~~~~~~~~~~~~~~~~~~
template <class T>
TaggedBoundingBoxOf<T>::TaggedBoundingBoxOf(T *tag):
TaggedBoundingBox(tag)
{
}
template <class T>
TaggedBoundingBoxOf<T>::TaggedBoundingBoxOf(
const ExtentBox &extents,
T *tag
):
TaggedBoundingBox(extents, tag)
{
}
template <class T>
TaggedBoundingBoxOf<T>::~TaggedBoundingBoxOf()
{
}
#endif
+484
View File
@@ -0,0 +1,484 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(LINE_HPP)
# include <line.hpp>
#endif
//#############################################################################
//############################### BoxedCone #############################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedCone::BoxedCone(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, ConeType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedCone::~BoxedCone()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedCone::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//------------------------------------------------------------------------
// Find the center point in the XZ plane of the cone, and find the biggest
// radius of the cone by measuring in the X axis, along with its height
//------------------------------------------------------------------------
//
Vector3D center;
center.x = (minX + maxX) * 0.5f;
center.y = minY;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
Verify(!Small_Enough(radius));
//
//--------------------------------------------------------------------------
// Convert the closest point in the slice to the coordinates of the cone,
// putting the apex of the cone at the origin, then make sure that the point
// isn't in one of the corners of the box
//--------------------------------------------------------------------------
//
Vector3D nearest(center);
extents.Constrain(&nearest);
center.y = maxY;
nearest.Subtract(center,nearest);
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
if (r > radius*radius)
{
return False;
}
//
//--------------------------------------------------------------------------
// Compute the distance from the axis, and then see if the slope of the line
// from the cone apex to the test point is less than the slope of the cone
//--------------------------------------------------------------------------
//
r = Sqrt(r);
Scalar height = maxY - minY;
return r*height <= nearest.y*radius;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedCone::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Find the center point in the XZ plane of the cone, and find the biggest
// radius of the cone by measuring in the X axis, along with its height
//------------------------------------------------------------------------
//
Vector3D center;
center.x = (minX + maxX) * 0.5f;
center.y = maxY;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
Verify(!Small_Enough(radius));
//
//--------------------------------------------------------------------------
// Convert the closest point in the slice to the coordinates of the cone,
// putting the apex of the cone at the origin, then make sure that the point
// isn't in one of the corners of the box
//--------------------------------------------------------------------------
//
Vector3D nearest;
nearest.Subtract(center, point);
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
if (r > radius*radius)
{
return False;
}
//
//--------------------------------------------------------------------------
// Compute the distance from the axis, and then see if the slope of the line
// from the cone apex to the test point is less than the slope of the cone
//--------------------------------------------------------------------------
//
r = Sqrt(r);
Scalar height = maxY - minY;
return r*height <= nearest.y*radius;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedCone::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Find the center point in the XZ plane of the cone, and find the biggest
// radius of the cone by measuring in the X axis, along with its height
//------------------------------------------------------------------------
//
Vector3D center;
center.x = (minX + maxX) * 0.5f;
center.y = maxY;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
Verify(!Small_Enough(radius));
//
//--------------------------------------------------------------------------
// Convert the closest point in the slice to the coordinates of the cone,
// putting the apex of the cone at the origin, then make sure that the point
// isn't in one of the corners of the box
//--------------------------------------------------------------------------
//
Vector3D nearest;
nearest.Subtract(point, center);
Scalar r = nearest.x*nearest.x + nearest.z*nearest.z;
if (r > radius*radius)
{
return -1.0f;
}
//
//--------------------------------------------------------------------------
// Compute the distance from the axis, and then see if the slope of the line
// from the cone apex to the test point is less than the slope of the cone
//--------------------------------------------------------------------------
//
r = Sqrt(r);
Scalar height = maxY - minY;
nearest.y += r*(height/radius);
return Max(nearest.y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// This function is a helper function used in the derivation for the terms of
// the quadratic equation to find t when colliding a line and a cone. I'm not
// real clear on the physical representation of this kind of dot product
//
static Scalar
Special_Cone_Dot_Product(
const Vector3D &v1,
const Vector3D &v2,
Scalar squared_tan
)
{
return v1.x*v2.x - squared_tan*v1.y*v2.y + v1.z*v2.z;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedCone::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//--------------------------------------------------------------------------
// Find out the size of the box, and set up the height and maximum radius of
// the cone, along with the squared tangent of the spread angle
//--------------------------------------------------------------------------
//
Vector3D center;
center.x = (minX + maxX) * 0.5f;
center.y = maxY;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
Scalar height = maxY - minY;
Verify(!Small_Enough(height));
Scalar squared_tan = radius*radius/(height*height);
//
//-------------------------------------------------------------------------
// Find the line between the point of the cone and the origin of our line,
// then set up the conditions for the quadratic equation. The following
// equation sets up a*t^2 + b*t + c = 0. The terms a, b, and c are derived
// by solving the following equations for t:
//
// p == line->origin + line->direction * t
// r == p - cone->apex
// r.x^2 + r.z^2 == tan^2(cone_angle)*r.y^2
//
// The special cone dot product function is a handy way to reduce the
// complexity of the problem
//-------------------------------------------------------------------------
//
Vector3D v;
v.Subtract(line->origin,center);
//
//--------------------------------------------------------------------------
// If the line diverges from the axis at the same angle as the spread angle,
// we need to find the closest point on the line to the axis. We then drop
// a vertical plane containing the line through the cone at this point, thus
// generating a hyperbola. We then solve the hyperbola vs. line equation to
// get our intersection point
//--------------------------------------------------------------------------
//
Scalar a =
Special_Cone_Dot_Product(line->direction, line->direction, squared_tan);
if (Small_Enough(a))
{
}
//
//-----------------------------------------------
// Otherwise, continue solving the first equation
//-----------------------------------------------
//
else
{
Scalar b =
2.0f * Special_Cone_Dot_Product(v, line->direction, squared_tan);
Scalar c = Special_Cone_Dot_Product(v, v, squared_tan);
//
//-----------------------------------------------------------------------
// Now, use the quadratic equation to determine where the two points
// intersect the cone. If there is no solution, than the line missed the
// cone
//-----------------------------------------------------------------------
//
Verify(!Small_Enough(a));
Scalar t = -b / (2.0f * a);
Scalar i = b*b - 4.0f*a*c;
if (i < 0.0f)
{
return False;
}
//
//----------------------------------------------------------------------
// If the interval is zero, then the line hits the cone in one spot only
// (a tangential hit). Check to see if hits the lower half of the conic
// equation (our cone)
//----------------------------------------------------------------------
//
if (Small_Enough(i))
{
Scalar y = v.y + line->direction.y * t;
if (y > 0.0f)
{
return False;
}
//
//----------------------------------------------------------------
// It hit the lower cone, so see if it was entering or leaving the
// cone
//----------------------------------------------------------------
//
if (line->direction.y > 0.0f)
{
//
//-------------------------------------------------------------
// The line is leaving the cone, so see if we need to reset the
// leaving distance
//-------------------------------------------------------------
//
if (t < leaves)
{
leaves = t;
}
}
//
//------------------------------------------------------------
// The line is entering the cone, so see if we need to set the
// entering distance
//------------------------------------------------------------
//
else if (t > enters)
{
enters = t;
}
//
//-------------------------------------------------------------------
// See if we still have a collision with the cone, and if so, set the
// new line length
//-------------------------------------------------------------------
//
if (enters > leaves || enters > line->length || leaves < 0.0f)
{
return False;
}
line->length = Max(enters, 0.0f);
return True;
}
//
//----------------------------------------------------------------------
// If the interval is non-zero, then the conic section was struck in two
// places. Find out the lengths to those places and the y values for
// those points
//----------------------------------------------------------------------
//
i = Sqrt(i) / (2.0f * a);
Scalar t1,t2;
if (i > 0.0f)
{
t1 = t - i;
t2 = t + i;
}
else
{
t1 = t + i;
t2 = t - i;
}
Scalar y1 = v.y + line->direction.y * t1;
Scalar y2 = v.y + line->direction.y * t2;
//
//----------------------------------------------------------------------
// There are four combinations of the signs of the y values. Each has a
// different effect on missing/hitting, entering or leaving distances.
// First check to see if only the upper conic was hit
//----------------------------------------------------------------------
//
if (y1 > 0.0f)
{
if (y2 > 0.0f)
{
return False;
}
//
//-----------------------------------------------------------------
// The ray is entering our conic, so set the distance appropriately
//-----------------------------------------------------------------
//
if (t2 > enters)
{
enters = t2;
}
}
//
//----------------------------------------------------------------------
// See if the ray is leaving the lower conic, and if so, set the leaving
// distance accordingly
//----------------------------------------------------------------------
//
else
{
if (y2 > 0.0f)
{
if (t1 < leaves)
{
leaves = t1;
}
}
//
//--------------------------------------------------------------------
// Both spots are in the lower conic, so set both leaving and entering
// distances
//--------------------------------------------------------------------
//
else
{
if (t1 > enters)
{
enters = t1;
}
if (t2 < leaves)
{
leaves = t2;
}
}
}
//
//-----------------------------------------------------------------------
// See if we still have a collision with the cone, and if so, set the new
// line length
//-----------------------------------------------------------------------
//
if (enters > leaves || enters > line->length || leaves < 0.0f)
{
return False;
}
line->length = Max(enters, 0.0f);
}
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedCone::TestInstance() const
{
return solidType == ConeType;
}
File diff suppressed because it is too large Load Diff
+930
View File
@@ -0,0 +1,930 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(PLANE_HPP)
# include <plane.hpp>
#endif
extern Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
);
//#############################################################################
//##################### BoxedInvertedRampFacingNegativeZ ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeZ::BoxedInvertedRampFacingNegativeZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingNegativeZType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeZ::~BoxedInvertedRampFacingNegativeZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.maxY - minY;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingNegativeZ::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (z*rise <= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = minZ - maxZ;
ramp.normal.z = maxY - minY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = maxY*ramp.normal.y + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeZ::TestInstance() const
{
return solidType == InvertedRampFacingNegativeZType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingPositiveZ ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveZ::BoxedInvertedRampFacingPositiveZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingPositiveZType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveZ::~BoxedInvertedRampFacingPositiveZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.maxY - minY;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingPositiveZ::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (z*rise >= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = minZ - maxZ;
ramp.normal.z = minY - maxY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = minY*ramp.normal.y + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveZ::TestInstance() const
{
return solidType == InvertedRampFacingPositiveZType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingNegativeX ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeX::BoxedInvertedRampFacingNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingNegativeX::~BoxedInvertedRampFacingNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.minX - minX;
Scalar y = extents.maxY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (x*rise <= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = minX - maxX;
ramp.normal.x = maxY - minY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingNegativeX::TestInstance() const
{
return solidType == InvertedRampFacingNegativeXType;
}
//#############################################################################
//##################### BoxedInvertedRampFacingPositiveX ################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveX::BoxedInvertedRampFacingPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
InvertedRampFacingPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedInvertedRampFacingPositiveX::~BoxedInvertedRampFacingPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.maxX - maxX;
Scalar y = extents.maxY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= x*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedInvertedRampFacingPositiveX::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------
// If the point is above the ramp, it will hit the top of the ramp
//----------------------------------------------------------------
//
if (point.y > maxY)
{
return point.y - maxY;
}
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
return (x*rise >= y*run) ? 0.0f : -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = minX - maxX;
ramp.normal.x = minY - maxY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedInvertedRampFacingPositiveX::TestInstance() const
{
return solidType == InvertedRampFacingPositiveXType;
}
+329
View File
@@ -0,0 +1,329 @@
//===========================================================================//
// File: boxlist.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box based spatialization //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/08/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXLIST_HPP)
# include <boxlist.hpp>
#endif
//#############################################################################
//######################### BoundingBoxListNode #########################
//#############################################################################
MemoryBlock
BoundingBoxListNode::AllocatedMemory(
sizeof(BoundingBoxListNode),
500,
50,
"BoundingBoxList Nodes"
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBoxListNode::TestInstance() const
{
return True;
}
//#############################################################################
//########################### BoundingBoxList ###########################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBoxList::BoundingBoxList()
{
root = NULL;
nodeCount = 0;
scoreBoard = NULL;
boundingBoxIndex = NULL;
isXMajorAxis = True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBoxList::~BoundingBoxList()
{
if (scoreBoard)
{
Unregister_Pointer(scoreBoard);
delete scoreBoard;
}
if (boundingBoxIndex)
{
Unregister_Pointer(boundingBoxIndex);
delete boundingBoxIndex;
}
EraseList();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::Add(
BoundingBox* volume,
const ExtentBox &slice
)
{
Check(this);
Check(volume);
++nodeCount;
BoundingBoxListNode *node = new BoundingBoxListNode(volume, slice);
Register_Object(node);
node->previousNode = root;
root = node;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::Remove(BoundingBox* volume)
{
Check(this);
Check(volume);
//
//--------------------------------------------------------------------------
// Spin through all the boxes until we find the one we are after or until we
// run off the list
//--------------------------------------------------------------------------
//
BoundingBoxListNode
*p = NULL,
*c = root;
while (c)
{
Check(c);
if (c->boundingBox == volume)
{
break;
}
p = c;
c = c->previousNode;
}
//
//----------------------------------------------
// Unlink the node from the list if it was found
//----------------------------------------------
//
if (!c)
{
return;
}
Check(c);
if (p)
{
Check(p);
p->previousNode = c->previousNode;
}
else
{
root = c->previousNode;
}
//
//-----------------
// Delete this node
//-----------------
//
--nodeCount;
Unregister_Object(c);
delete c;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::EraseList()
{
Check(this);
//
//-----------------------------
// Delete each node in the list
//-----------------------------
//
BoundingBoxListNode *p = root;
while (p)
{
Check(p);
BoundingBoxListNode *q = p;
p = p->previousNode;
Unregister_Object(q);
delete q;
}
root = NULL;
nodeCount = 0;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox*
BoundingBoxList::FindBoundingBoxContaining(const Point3D &point)
{
Check(this);
Check(&point);
//
//--------------------------------------------------------------------------
// Spin through each of the boxes in reverse order until we find a box which
// contains the specified point. It will be default have priority over any
// boxes put in before it
//--------------------------------------------------------------------------
//
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
{
Check(p);
BoundingBox *box = p->boundingBox;
Check(box);
if (box->Contains(point))
{
return box;
}
}
return NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::FindBoundingBoxesContaining(
BoundingBox *volume,
BoundingBoxCollisionList &list
)
{
Check(this);
Check(volume);
Check(&list);
//
//-------------------------------------------------------------
// Spin through each of the boxes in reverse order, looking for
// intesections between the test volume and the box list
//-------------------------------------------------------------
//
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
{
Check(p);
BoundingBox *box = p->boundingBox;
Check(box);
if (box->ExtentBox::Intersects(*volume))
{
//
//----------------------------------------------------------------
// Build the intersection slice, and make sure that it really does
// intersect the list box
//----------------------------------------------------------------
//
ExtentBox slice;
slice.Intersect(*volume, *box);
if (box->IntersectsBounded(slice))
{
//
//------------------------------------------------------------
// It intersects, so add this to the list. If we are out of
// collisions in the list, we are finished detecting, and just
// return
//------------------------------------------------------------
//
Verify(list.collisionsLeft);
list.AddCollisionToList(box, slice);
if (!list.collisionsLeft)
{
return;
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox*
BoundingBoxList::FindBoundingBoxUnder(
const Point3D &point,
Scalar *height
)
{
Check(this);
Check(&point);
Check_Pointer(height);
//
//-----------------------------------------------------------------------
// Spin through each of the bounding boxes, keeping track of which box is
// hit after the shortest distance
//-----------------------------------------------------------------------
//
BoundingBox *best_box = NULL;
*height = -1.0f;
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
{
Check(p);
BoundingBox *box = p->boundingBox;
Check(box);
Scalar h = box->FindDistanceBelow(point);
if (h != -1.0f)
{
if (!best_box || *height > h)
{
best_box = box;
*height = h;
}
}
}
return best_box;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoundingBox*
BoundingBoxList::FindBoundingBoxHitBy(Line *line)
{
//
//-----------------------------------------------------------------------
// Spin through each of the boxes, letting each box in turn clip the line
// lengths
//-----------------------------------------------------------------------
//
BoundingBox *best_box = NULL;
for (BoundingBoxListNode *p=root; p; p = p->previousNode)
{
Check(p);
BoundingBox *box = p->boundingBox;
Check(box);
Logical h = box->HitBy(line);
if (h)
{
best_box = box;
}
}
return best_box;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoundingBoxList::TestInstance() const
{
return True;
}
+173
View File
@@ -0,0 +1,173 @@
//===========================================================================//
// File: bndgbox.hh //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Interface specification of bounding-box based spatialization //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/08/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(BOXLIST_HPP)
# define BOXLIST_HPP
# if !defined(BNDGBOX_HPP)
# include <bndgbox.hpp>
# endif
# if !defined(MEMBLOCK_HPP)
# include <memblock.hpp>
# endif
//##########################################################################
//####################### BoundingBoxListNode ########################
//##########################################################################
class BoundingBoxList;
class BoxedSolidList;
class BoundingBoxTree;
class BoundingBoxListNode SIGNATURED
{
friend class BoundingBoxList;
friend class BoxedSolidList;
//##########################################################################
// Memory Allocation
//
private:
static MemoryBlock
AllocatedMemory;
void*
operator new(size_t)
{return AllocatedMemory.New();}
void
operator delete(void *where)
{AllocatedMemory.Delete(where);}
//##########################################################################
// Construction and Destruction
//
protected:
BoundingBox
*boundingBox;
BoundingBoxListNode
*previousNode;
BoundingBoxListNode(
BoundingBox *volume,
const ExtentBox &slice
):
boundingBox(volume),
solidSlice(slice),
previousNode(NULL)
{Check_Pointer(this); Check(volume);}
~BoundingBoxListNode()
{Check(this);}
public:
ExtentBox
solidSlice;
BoundingBox*
GetBoundingBox()
{Check(this); return boundingBox;}
BoundingBoxListNode*
GetNextNode()
{Check(this); return previousNode;}
//##########################################################################
// Test Support
//
public:
Logical
TestInstance() const;
};
//##########################################################################
//######################## BoundingBoxList ###########################
//##########################################################################
class BoundingBoxList SIGNATURED
{
//##########################################################################
// Construction and Destruction
//
protected:
BoundingBoxListNode
*root;
int
nodeCount;
int*
scoreBoard;
BoundingBox
**boundingBoxIndex;
Logical
isXMajorAxis;
public:
BoundingBoxList();
~BoundingBoxList();
void
Add(
BoundingBox* volume,
const ExtentBox &slice
);
void
Remove(BoundingBox* volume);
void
EraseList();
BoundingBoxListNode*
GetRoot()
{Check(this); return root;}
//##########################################################################
// Tree Traversal Functions
//
public:
BoundingBox*
FindBoundingBoxContaining(const Point3D &point);
void
FindBoundingBoxesContaining(
BoundingBox *volume,
BoundingBoxCollisionList &list
);
BoundingBox*
FindBoundingBoxUnder(
const Point3D &point,
Scalar *height
);
BoundingBox*
FindBoundingBoxHitBy(Line *line);
void
Reduce();
void
SortForTree();
protected:
void
Sort(
BoundingBoxList &active_solids,
ExtentBox &clipping_box,
BoundingBoxTree &tree_so_far
);
//##########################################################################
// Test Support
//
public:
Logical
TestInstance() const;
};
#endif
+947
View File
@@ -0,0 +1,947 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(PLANE_HPP)
# include <plane.hpp>
#endif
#if !defined(LINE_HPP)
# include <line.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
)
{
//
//------------------------------------------------------------------------
// Find the perpendicular distance from the origin of the ray to the ramp,
// and find the direction of the ray relative to the ramp
//------------------------------------------------------------------------
//
Scalar distance = plane.DistanceTo(line->origin);
Scalar drift = line->direction*plane.normal;
//
//--------------------------------------------------------------------------
// If the ray is going out of the ramp and the origin of the
// ray is in the half-space that the plane's normal points to
//--------------------------------------------------------------------------
//
if (drift > 0 && distance > 0)
{
return False;
}
//
//--------------------------------------------------------------------------
// If the ray is parallel to the ramp, the ray will hit if the origin of the
// ray is not in the half-space that the plane's normal points to
//--------------------------------------------------------------------------
//
if (!drift)
{
if (distance <= 0.0f)
{
line->length = Max(enters, 0.0f);
return True;
}
return False;
}
//
//--------------------------------------------------------------------
// Otherwise, if the plane faces the ray, check to see how far the ray
// travels before hitting it
//--------------------------------------------------------------------
//
if (drift < 0.0f)
{
distance /= -drift;
//
//-----------------------------------------------------------------------
// If the ray strikes the plane after all other facing surfaces, then the
// ray enters the solid through this plane. So check to make sure that
// the ray does not miss the plane as clipped by the other surfaces, and
// if it hits, return this distance as the projection length. If the ray
// enters the ramp through an edge face of the bounding box, set the line
// length to the entering value calculated for the box
//-----------------------------------------------------------------------
//
if (distance > enters)
{
if (distance > leaves || distance > line->length)
{
return False;
}
enters = distance;
}
line->length = Max(enters, 0.0f);
return True;
}
//
//------------------------------------------------------------------------
// If the plane faces away from the ray, check to see how far the ray
// travels before exiting it, and ensure this is not before the ray enters
// the object
//------------------------------------------------------------------------
//
distance /= -drift;
if (distance >= enters)
{
line->length = Max(enters, 0.0f);
return True;
}
return False;
}
//#############################################################################
//######################### BoxedRampFacingNegativeZ ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeZ::BoxedRampFacingNegativeZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingNegativeZType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeZ::~BoxedRampFacingNegativeZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.minY - minY;
Scalar z = extents.minZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/z yields
// rise*z <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedRampFacingNegativeZ::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = minZ - maxZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - maxZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
y -= (rise/run)*z;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = maxZ - minZ;
ramp.normal.z = maxY - minY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = maxY*ramp.normal.y + minZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeZ::TestInstance() const
{
return solidType == RampFacingNegativeZType;
}
//#############################################################################
//######################### BoxedRampFacingPositiveZ ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveZ::BoxedRampFacingPositiveZ(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingPositiveZType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveZ::~BoxedRampFacingPositiveZ()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = extents.minY - minY;
Scalar z = extents.maxZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/z slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/z yields
// rise*z >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return z*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedRampFacingPositiveZ::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar rise = maxY - minY;
Scalar run = maxZ - minZ;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar y = point.y - minY;
Scalar z = point.z - minZ;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
y -= (rise/run)*z;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.x = 0.0f;
ramp.normal.y = maxZ - minZ;
ramp.normal.z = minY - maxY;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.z /= temp;
ramp.offset = minY*ramp.normal.y + minZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveZ::TestInstance() const
{
return solidType == RampFacingPositiveZType;
}
//#############################################################################
//######################### BoxedRampFacingNegativeX ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeX::BoxedRampFacingNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingNegativeXType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingNegativeX::~BoxedRampFacingNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.minX - maxX;
Scalar y = extents.minY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= y/x yields
// rise*x <= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise <= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
y -= (rise/run)*x;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = maxX - minX;
ramp.normal.x = maxY - minY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingNegativeX::TestInstance() const
{
return solidType == RampFacingNegativeXType;
}
//#############################################################################
//######################### BoxedRampFacingPositiveX ####################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveX::BoxedRampFacingPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, RampFacingPositiveXType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedRampFacingPositiveX::~BoxedRampFacingPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.maxX - minX;
Scalar y = extents.minY - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= x*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than y/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= y/x yields
// rise*x >= y*run, which avoids any divide-by-0 errors
//------------------------------------------------------------------------
//
return x*rise >= y*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedRampFacingPositiveX::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin. If the run is zero, make sure no divide by zero
// happens
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxY - minY;
Verify(!Small_Enough(run));
//
//----------------------------------------------------------
// Get the point coordinates local the the start of the ramp
//----------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar y = point.y - minY;
//
//-------------------------------------------------------------------
// Return the distance from the point to where it intersects the ramp
//-------------------------------------------------------------------
//
y -= (rise/run)*x;
return Max(y,0.0f);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
Scalar
temp;
//
//-------------------------------------------------------------------
// Make a vector pointing normal to the face of the north facing ramp
//-------------------------------------------------------------------
//
ramp.normal.y = maxX - minX;
ramp.normal.x = minY - maxY;
ramp.normal.z = 0.0f;
//
//-------------------------------------------------------------
// Scale the vector to a normal and figure out the plane offset
//-------------------------------------------------------------
//
temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x;
Verify(!Small_Enough(temp))
temp = Sqrt(temp);
ramp.normal.y /= temp;
ramp.normal.x /= temp;
ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedRampFacingPositiveX::TestInstance() const
{
return solidType == RampFacingPositiveXType;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+378
View File
@@ -0,0 +1,378 @@
#include <boxtree.hpp>
#include <boxlist.hpp>
#include <random.hpp>
#include <boxsolid.hpp>
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedSolid::TestClass()
{
//ofstream testout("gene.dat",ios::app); //GY
Tell("Start BoxedSolid::TestClass()..\n");
BoxedSolidTree tree;
BoxedSolidList list;
Point3D test_point;
ExtentBox eb;
BoxedSolid* solids[TEST_CLASS];
BoxedSolid *list_ptr;
BoxedSolid *tree_ptr;
//
//------------------------------------------------------------
// Create a bunch of boxes to test, and add them into the tree
//------------------------------------------------------------
//
int i;
for (i=0; i<ELEMENTS(solids); ++i)
{
eb.minX = 70.0f * Random - 40.0f;
eb.minY = 70.0f * Random - 40.0f;
eb.minZ = 70.0f * Random - 40.0f;
eb.maxX = 10.0f * Random + eb.minX;
eb.maxY = 10.0f * Random + eb.minY;
eb.maxZ = 10.0f * Random + eb.minZ;
Scalar min_size = 1.0f;
if ((eb.maxX - eb.minX) < min_size) eb.maxX = (eb.minX +min_size);
if ((eb.maxY - eb.minY) < min_size) eb.maxY = (eb.minY +min_size);
if ((eb.maxZ - eb.minZ) < min_size) eb.maxZ = (eb.minZ +min_size);
Type c = (Type)Random(SolidTypeCount);
//WedgeFacingNegativeZAndPositiveXType ok
//WedgeFacingNegativeZAndNegativeXType ok
//WedgeFacingPositiveZAndNegativeXType ok
//WedgeFacingPositiveZAndPositiveXType ok
//XAxisCylinderType ok
//YAxisCylinderType ok
//ZAxisCylinderType ok
//RampFacingNegativeZType ok
//RampFacingNegativeXType ok
//RampFacingPositiveZType ok
//RampFacingPositiveXType ok
//InvertedRampFacingNegativeXType ok
//InvertedRampFacingNegativeZType ok
//InvertedRampFacingPositiveXType ok
//InvertedRampFacingPositiveZType ok
//ConeType ok with avoiding special case of a=0 in Hit()
//c = ConeType;
switch (c)
{
case BlockType:
eb.maxZ = (eb.maxX - eb.minX) + eb.minZ;
solids[i] = new BoxedSolid(eb, StoneMaterial, NULL, NULL);
break;
// case SphereType: // Not implemented yet
case ConeType:
eb.maxZ = (eb.maxX - eb.minX) + eb.minZ;
solids[i] = new BoxedCone(eb, StoneMaterial, NULL, NULL);
break;
// case RampType=4,
case RampFacingNegativeZType:
solids[i] = new BoxedRampFacingNegativeZ(eb, StoneMaterial, NULL, NULL);
break;
case RampFacingNegativeXType:
solids[i] = new BoxedRampFacingNegativeX(eb, StoneMaterial, NULL, NULL);
break;
case RampFacingPositiveZType:
solids[i] = new BoxedRampFacingPositiveZ(eb, StoneMaterial, NULL, NULL);
break;
case RampFacingPositiveXType:
solids[i] = new BoxedRampFacingPositiveX(eb, StoneMaterial, NULL, NULL);
break;
// case InvertedRampType=8,
case InvertedRampFacingNegativeZType:
solids[i] = new BoxedInvertedRampFacingNegativeZ(eb, StoneMaterial, NULL, NULL);
break;
case InvertedRampFacingNegativeXType:
solids[i] = new BoxedInvertedRampFacingNegativeX(eb, StoneMaterial, NULL, NULL);
break;
case InvertedRampFacingPositiveZType:
solids[i] = new BoxedInvertedRampFacingPositiveZ(eb, StoneMaterial, NULL, NULL);
break;
case InvertedRampFacingPositiveXType:
solids[i] = new BoxedInvertedRampFacingPositiveX(eb, StoneMaterial, NULL, NULL);
break;
// case WedgeType=12,
case WedgeFacingNegativeZAndPositiveXType:
solids[i] = new BoxedWedgeFacingNegativeZAndPositiveX(eb, StoneMaterial, NULL, NULL);
break;
case WedgeFacingNegativeZAndNegativeXType:
solids[i] = new BoxedWedgeFacingNegativeZAndNegativeX(eb, StoneMaterial, NULL, NULL);
break;
case WedgeFacingPositiveZAndNegativeXType:
solids[i] = new BoxedWedgeFacingPositiveZAndNegativeX(eb, StoneMaterial, NULL, NULL);
break;
case WedgeFacingPositiveZAndPositiveXType:
solids[i] = new BoxedWedgeFacingPositiveZAndPositiveX(eb, StoneMaterial, NULL, NULL);
break;
case XAxisCylinderType:
eb.maxZ = (eb.maxY - eb.minY) + eb.minZ;
solids[i] = new BoxedXAxisCylinder(eb, StoneMaterial, NULL, NULL);
break;
case YAxisCylinderType:
eb.maxZ = (eb.maxX - eb.minX) + eb.minZ;
solids[i] = new BoxedYAxisCylinder(eb, StoneMaterial, NULL, NULL);
break;
case ZAxisCylinderType:
eb.maxY = (eb.maxX - eb.minX) + eb.minY;
solids[i] = new BoxedZAxisCylinder(eb, StoneMaterial, NULL, NULL);
break;
default:
--i;
continue;
}
Register_Pointer(solids[i]);
tree.Add(solids[i], *solids[i]);
list.Add(solids[i], *solids[i]);
}
//
//---------------------------------------------------------------------
// Test the centroids of the boxes against the tree and see if they hit
// where they are supposed to
//---------------------------------------------------------------------
//
for (i=0; i<ELEMENTS(solids); ++i)
{
test_point.x = (solids[i]->minX + solids[i]->maxX) * 0.5f;
test_point.y = (solids[i]->minY + solids[i]->maxY) * 0.5f;
test_point.z = (solids[i]->minZ + solids[i]->maxZ) * 0.5f;
tree_ptr = tree.FindBoundingBoxContaining(test_point);
list_ptr = list.FindBoundingBoxContaining(test_point);
Test(tree_ptr == list_ptr);
}
//
//---------------------------------------------------
// Now test a bunch of random points against the tree
//---------------------------------------------------
//
for (i=0; i<TEST_CLASS; ++i)
{
test_point.x = 80.0f * Random - 40.0f;
test_point.y = 80.0f * Random - 40.0f;
test_point.z = 80.0f * Random - 40.0f;
tree_ptr = tree.FindBoundingBoxContaining(test_point);
list_ptr = list.FindBoundingBoxContaining(test_point);
Test(tree_ptr == list_ptr);
}
//
//-------------------------------------------------------
// Try finding the boxes contained in random test volumes
//-------------------------------------------------------
//
for (i=0; i<TEST_CLASS; ++i)
{
BoundingBoxCollisionList tree_collisions(10);
BoundingBoxCollisionList list_collisions(10);
ExtentBox test_volume;
test_volume.minX = 72.0f * Random - 40.0f;
test_volume.minY = 78.0f * Random - 40.0f;
test_volume.minZ = 72.0f * Random - 40.0f;
test_volume.maxX = test_volume.minX + 8.0f;
test_volume.maxY = test_volume.minY + 2.0f;
test_volume.maxZ = test_volume.minZ + 8.0f;
BoxedYAxisCylinder test_disk(test_volume, SteelMaterial, NULL, NULL);
tree.FindBoundingBoxesContaining(&test_disk, tree_collisions);
list.FindBoundingBoxesContaining(&test_disk, list_collisions);
//
//--------------------------------------------------------------------
// If no collisions were found in the list, none should be in the tree
//--------------------------------------------------------------------
//
if (!list_collisions.GetCollisionCount())
{
Test(!tree_collisions.GetCollisionCount());
}
//
//-------------------------------------------------------------------
// If less then 10 collisions were found, then every collision in the
// tree should be in the list
//-------------------------------------------------------------------
//
else if (list_collisions.GetCollisionCount() < 10)
{
Test(tree_collisions.GetCollisionCount());
for (int c=0; c<tree_collisions.GetCollisionCount(); ++c)
{
int c2;
for (c2=0; c2<list_collisions.GetCollisionCount(); ++c2)
{
if (
tree_collisions[c].treeVolume
== list_collisions[c2].treeVolume
)
{
break;
}
}
Test(c2 != list_collisions.GetCollisionCount());
}
}
//
//----------------------------------------------------------------------
// Otherwise, anything could happen, so just make sure that the tree was
// not empty
//----------------------------------------------------------------------
//
else
{
Test(tree_collisions.GetCollisionCount());
}
}
//
//----------------------------------------------------------------------
// Try finding heights of random test points over any blocks, and verify
// if the rays should hit or not
//----------------------------------------------------------------------
//
Scalar tree_height;
Scalar list_height;
for (i=0; i<TEST_CLASS; ++i)
{
test_point.x = 80.0f * Random - 40.0f;
test_point.y = 20.0f * Random + 40.0f;
test_point.z = 80.0f * Random - 40.0f;
tree_ptr = tree.FindBoundingBoxUnder(test_point, &tree_height);
list_ptr = list.FindBoundingBoxUnder(test_point, &list_height);
Test(tree_ptr == list_ptr);
Test(tree_height == list_height);
Line line;
line.origin = test_point;
line.direction.x = 0.0f;
line.direction.y = -1.0f;
line.direction.z = 0.0f;
line.length = 200.0f;
BoundingBox *ray_ptr;
ray_ptr = list.FindBoundingBoxHitBy(&line);
Test(ray_ptr == list_ptr);
if (ray_ptr)
{
Test(Close_Enough(line.length, tree_height,1.0e-2));
} //a cone apix is the worst case
line.length = 200.0f;
ray_ptr = tree.FindBoundingBoxHitBy(&line);
Test(ray_ptr == tree_ptr);
if (ray_ptr)
{
Test(Close_Enough(line.length, tree_height,1.0e-2));
}
}
//
//-----------------------------------------------------------------
// Now test a bunch of random rays with origins outside the solids
//-----------------------------------------------------------------
//
for (i=0; i<TEST_CLASS; ++i)
{
test_point.x = 80.0f * Random - 40.0f;
test_point.y = 80.0f * Random - 40.0f;
test_point.z = 80.0f * Random - 40.0f;
tree_ptr = tree.FindBoundingBoxContaining(test_point);
list_ptr = list.FindBoundingBoxContaining(test_point);
Test(tree_ptr == list_ptr);
if (tree_ptr == NULL)
{
Scalar
ray_length = Random * 40.0f;
Line
line;
line.origin = test_point;
line.direction.x = Random;
line.direction.y = Random;
line.direction.z = Random;
Scalar temp = Sqrt(line.direction.x * line.direction.x +
line.direction.y * line.direction.y +
line.direction.z * line.direction.z);
if (!Close_Enough(temp, 0.0f, SMALL))
{
line.direction.x /= temp;
line.direction.y /= temp;
line.direction.z /= temp;
temp = Sqrt(line.direction.x * line.direction.x +
line.direction.y * line.direction.y +
line.direction.z * line.direction.z);
Test( Close_Enough(temp, 1.0f, SMALL));
line.length = ray_length;
list_ptr = list.FindBoundingBoxHitBy(&line);
Scalar list_length = line.length;
line.length = ray_length;
tree_ptr = tree.FindBoundingBoxHitBy(&line);
Scalar tree_length = line.length;
Test(list_ptr == tree_ptr);
if (list_ptr)
{
Test(Close_Enough(list_length, tree_length, 1.0e-2));
}
}
else
{
--i;
continue;
}
}
else
{
--i;
continue;
}
}
for (i=0; i<ELEMENTS(solids); ++i)
{
Unregister_Pointer(solids[i]);
delete solids[i];
}
//testout<<".......\n"; //GY
//testout.close();
//cerr<<"End \n";
return True;
}
+495
View File
@@ -0,0 +1,495 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(VECTOR3D_HPP)
# include <vector3d.hpp>
#endif
//#############################################################################
//########################### BoxedSolidList ############################
//#############################################################################
enum {
X_Axis_Bit = 1,
Y_Axis_Bit = 2,
Z_Axis_Bit = 4
};
enum {
Min_Side = 0x001,
Inside = 0x002,
Max_Side = 0x004,
Both_Sides = Min_Side|Max_Side,
Shift = 3,
X_Shift = 2 * Shift,
Min_X_Side = Min_Side << X_Shift,
Inside_X = Inside << X_Shift,
Max_X_Side = Max_Side << X_Shift,
X_Mask = Min_X_Side|Inside_X|Max_X_Side,
Y_Shift = Shift,
Min_Y_Side = Min_Side << Y_Shift,
Inside_Y = Inside << Y_Shift,
Max_Y_Side = Max_Side << Y_Shift,
Y_Mask = Min_Y_Side|Inside_Y|Max_Y_Side,
Z_Shift = 0,
Min_Z_Side = Min_Side << Z_Shift,
Inside_Z = Inside << Z_Shift,
Max_Z_Side = Max_Side << Z_Shift,
Z_Mask = Min_Z_Side|Inside_Z|Max_Z_Side
};
int
Legal_To_Fuse[BoxedSolid::SolidTypeCount]=
{
X_Axis_Bit|Y_Axis_Bit|Z_Axis_Bit, 0, 0, 0,
X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit,
X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit,
Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit,
X_Axis_Bit, Y_Axis_Bit, Z_Axis_Bit
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::Reduce()
{
Check(this);
BoundingBoxListNode
*i, *j, *previous;
//
//--------------------------------------------------------------------------
// Fuse the collision slices together into the largest possible chunks based
// upon the collision model of each of the involved slices. Repeat until no
// fusings were made in the last pass or only one collision slice remains
//--------------------------------------------------------------------------
//
Logical again = True;
while (again)
{
again = False;
//
//--------------------------------------------------------------------
// Check each collision slice against the remaining slices in the list
//--------------------------------------------------------------------
//
for (i=root; i; i = i->previousNode)
{
Check(i);
previous = i;
j = i->previousNode;
while (j)
{
Check(j);
//
//-------------------------------------------------------------
// If the model types are different, these two slices cannot be
// fused
//-------------------------------------------------------------
//
BoundingBox *first = i->boundingBox;
BoundingBox *second = j->boundingBox;
//
//----------------------------------------------------
// Make sure that the faces on two sets of sides match
//----------------------------------------------------
//
int matches = 0;
int face = -1;
for (int side=0; side<6; side += 2)
{
if (
(*first)[side] == (*second)[side]
&& (*first)[side+1] == (*second)[side+1]
)
{
++matches;
}
else if (face<0)
{
face = side;
}
}
if (matches != 2)
{
Next_Solid:
previous = j;
j = j->previousNode;
continue;
}
//
//----------------------------------------------------------------
// Check to make sure that the two solids have an opposing face in
// common, which will allow the solids to be fused
//----------------------------------------------------------------
//
if (
(*first)[face] != (*second)[face+1]
&& (*first)[face+1] != (*second)[face]
)
{
goto Next_Solid;
}
//
//----------------------------------------------------
// Find the face to fuse, and fuse the blocks together
//----------------------------------------------------
//
if ((*first)[face+1] == (*second)[face])
{
++face;
}
(*first)[face] = (*second)[face];
//
//-----------------------------------------------
// Erase the second solid from the collision list
//-----------------------------------------------
//
--nodeCount;
if (previous)
{
previous->previousNode = j->previousNode;
Unregister_Object(j);
delete(j);
j = previous->previousNode;
}
else
{
root = j->previousNode;
Unregister_Object(j);
delete(j);
j = root;
}
again = True;
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::SortForTree()
{
Check(this);
int
i, j;
BoundingBoxListNode
*p, *q;
//
//-----------------------------------------------------------------------
// Find out how many collision solids are in the list, and figure out the
// total extent box so that we can set the traversal order correctly
//-----------------------------------------------------------------------
//
ExtentBox map_extents;
map_extents.minX = 65535.9999f;
map_extents.minY = 65535.9999f;
map_extents.minZ = 65535.9999f;
map_extents.maxX = -65535.9999f;
map_extents.maxY = -65535.9999f;
map_extents.maxZ = -65535.9999f;
for (p=root; p; p = p->previousNode)
{
Check(p);
if (p->boundingBox->minX < map_extents.minX)
{
map_extents.minX = p->boundingBox->minX;
}
if (p->boundingBox->maxX > map_extents.maxX)
{
map_extents.maxX = p->boundingBox->maxX;
}
if (p->boundingBox->minY < map_extents.minY)
{
map_extents.minY = p->boundingBox->minY;
}
if (p->boundingBox->maxY > map_extents.maxY)
{
map_extents.maxY = p->boundingBox->maxY;
}
if (p->boundingBox->minZ < map_extents.minZ)
{
map_extents.minZ = p->boundingBox->minZ;
}
if (p->boundingBox->maxZ > map_extents.maxZ)
{
map_extents.maxZ = p->boundingBox->maxZ;
}
}
if (
map_extents.maxZ - map_extents.minZ
> map_extents.maxX - map_extents.minX
)
{
isXMajorAxis = False;
}
//
//----------------------------------------------------
// Allocate a scoreboard and fill it with sorting info
//----------------------------------------------------
//
Verify(!scoreBoard);
scoreBoard = new int[nodeCount * nodeCount];
Register_Pointer(scoreBoard);
int *score = scoreBoard;
boundingBoxIndex = new BoundingBox* [nodeCount];
Register_Pointer(boundingBoxIndex);
for (p=root,i=0; p; p = p->previousNode,++i)
{
Check(p);
BoundingBox *first = p->boundingBox;
boundingBoxIndex[i] = first;
for (q=root,j=0; q; q = q->previousNode,++j,++score)
{
//
//------------------------------
// Ignore scoring against itself
//------------------------------
//
Check(q);
*score = 0;
if (p == q)
{
continue;
}
BoundingBox *second = q->boundingBox;
//
//--------------------------------------------------------------------
// Step through the three axes and set the flags showing how the
// second solid is split up by the first solid. Make sure that if the
// second solid completely covers the first that this inside bit is
// set correctly
//--------------------------------------------------------------------
//
for (int axis = X_Axis; axis <= Z_Axis; --axis)
{
*score <<= Shift;
int face = axis << 1;
if ((*second)[face] < (*first)[face])
{
*score |= Min_Side;
}
else if ((*second)[face] < (*first)[face+1])
{
*score |= Inside;
}
if ((*second)[face+1] > (*first)[face+1])
{
*score |= Max_Side;
}
else if ((*second)[face+1] > (*first)[face])
{
*score |= Inside;
}
if ((*score & Both_Sides) == Both_Sides)
{
*score |= Inside;
}
}
}
}
//
//--------------------------------------------------------------------------
// Create a new BoxedSolid list for results to go into, and a third in which
// to pass the active list
//--------------------------------------------------------------------------
//
BoundingBoxList active;
active.root = root;
active.nodeCount = nodeCount;
root = NULL;
BoundingBoxTree tree_so_far;
Sort(
active,
map_extents,
tree_so_far
);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoundingBoxList::Sort(
BoundingBoxList &,//active,
ExtentBox &,//map_extents,
BoundingBoxTree &//tree_so_far
)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
BoxedSolidList::Reduce()
{
Check(this);
BoundingBoxListNode
*i, *j, *previous;
//
//--------------------------------------------------------------------------
// Fuse the collision slices together into the largest possible chunks based
// upon the collision model of each of the involved slices. Repeat until no
// fusings were made in the last pass or only one collision slice remains
//--------------------------------------------------------------------------
//
Logical again = True;
while (again)
{
again = False;
//
//--------------------------------------------------------------------
// Check each collision slice against the remaining slices in the list
//--------------------------------------------------------------------
//
for (i=root; i; i = i->previousNode)
{
Check(i);
previous = i;
j = i->previousNode;
while (j)
{
Check(j);
//
//-------------------------------------------------------------
// If the model types are different, these two slices cannot be
// fused
//-------------------------------------------------------------
//
BoxedSolid *first = Cast_Object(BoxedSolid*, i->boundingBox);
BoxedSolid *second = Cast_Object(BoxedSolid*, j->boundingBox);
if (first->solidType != second->solidType)
{
Next_Solid:
previous = j;
j = j->previousNode;
continue;
}
//
//----------------------------------------------------
// Make sure that the faces on two sets of sides match
//----------------------------------------------------
//
int matches = 0;
int face = -1;
for (int side=0; side<6; side += 2)
{
if (
(*first)[side] == (*second)[side]
&& (*first)[side+1] == (*second)[side+1]
)
{
++matches;
}
else if (face<0)
{
face = side;
}
}
if (matches != 2)
{
goto Next_Solid;
}
//
//----------------------------------------------------------------
// Check to make sure that the two solids have an opposing face in
// common, which will allow the solids to be fused
//----------------------------------------------------------------
//
if (
(*first)[face] != (*second)[face+1]
&& (*first)[face+1] != (*second)[face]
)
{
goto Next_Solid;
}
//
//---------------------------------------------------------------
// Make sure that this type of solid is legal to be fused in this
// direction
//---------------------------------------------------------------
//
if (!(Legal_To_Fuse[first->solidType] & (face>>1)))
{
goto Next_Solid;
}
//
//----------------------------------------------------
// Find the face to fuse, and fuse the blocks together
//----------------------------------------------------
//
if ((*first)[face+1] == (*second)[face])
{
++face;
}
(*first)[face] = (*second)[face];
//
//-----------------------------------------------
// Erase the second solid from the collision list
//-----------------------------------------------
//
if (previous)
{
previous->previousNode = j->previousNode;
Unregister_Object(j);
delete(j);
j = previous->previousNode;
}
else
{
root = j->previousNode;
Unregister_Object(j);
delete(j);
j = root;
}
again = True;
}
}
}
}
+260
View File
@@ -0,0 +1,260 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(ORIGIN_HPP)
# include <origin.hpp>
#endif
#if !defined(LINMTRX_HPP)
# include <linmtrx.hpp>
#endif
#if !defined(LINE_HPP)
# include <line.hpp>
#endif
//#############################################################################
//############################## BoxedSphere ############################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedSphere::BoxedSphere(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(extents, SphereType, material, owner, next_solid)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedSphere::~BoxedSphere()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedSphere::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------
// Find the centerpoint and radius of the sphere
//----------------------------------------------
//
Point3D center;
center.x = (minX + maxX) * 0.5f;
center.y = (minY + maxY) * 0.5f;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
//
//--------------------------------------------------------------------------
// Constrain the centerpoint of the sphere to be within the bounded extents.
// Then see if the constrained point is within the radius of the sphere. If
// so, it is an intersection
//--------------------------------------------------------------------------
//
Point3D closest = center;
extents.Constrain(&closest);
closest -= center;
return radius*radius >= closest.LengthSquared();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedSphere::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------
// Find the centerpoint and radius of the sphere
//----------------------------------------------
//
Point3D center;
center.x = (minX + maxX) * 0.5f;
center.y = (minY + maxY) * 0.5f;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
//
//-------------------------------------------------------------------------
// translate the test point into the sphere's frame of reference and see if
// it is close enough
//-------------------------------------------------------------------------
//
center -= point;
return radius*radius >= center.LengthSquared();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedSphere::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------
// Find the centerpoint and radius of the sphere
//----------------------------------------------
//
Point3D center;
center.x = (minX + maxX) * 0.5f;
center.y = (minY + maxY) * 0.5f;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
//
//-----------------------------------------------------------------------
// Convert the point to the coordinates of the sphere, putting the center
// point of the sphere at the origin. Note that we are subtracting the
// point from the center point as opposed to the normal way. This will
// result in both X and Y being negated, but since we are squaring them,
// this will not matter
//-----------------------------------------------------------------------
//
Scalar x = center.x - point.x;
Scalar z = center.z - point.z;
Scalar h = radius*radius - x*x - z*z;
if (h < SMALL)
{
return -1.0f;
}
//
//-------------------------------------------------------------------
// If the point is in the XZ shadow of the sphere, then the height is
// determined by the height of the sphere at that point
//-------------------------------------------------------------------
//
Scalar height = point.y - (center.y + Sqrt(h));
return Abs(height);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedSphere::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//----------------------------------------------
// Find the centerpoint and radius of the sphere
//----------------------------------------------
//
Point3D center;
center.x = (minX + maxX) * 0.5f;
center.y = (minY + maxY) * 0.5f;
center.z = (minZ + maxZ) * 0.5f;
Scalar radius = maxX - center.x;
//
//-------------------------------------------------------------------------
// Find the point of closest approach to the center of the sphere, and make
// sure that it is within the boundaries of the sphere
//-------------------------------------------------------------------------
//
Scalar midlen = line->LengthToClosestPointTo(center);
Point3D closest;
line->Project(midlen, &closest);
closest -= center;
Scalar v = radius*radius - closest.LengthSquared();
if (v < 0.0f)
{
return False;
}
//
//---------------------------------------------------------------------
// Find the closest possible length of ray traversal before hitting the
// sphere
//---------------------------------------------------------------------
//
v = Sqrt(v);
Scalar enter = midlen - v;
if (enter > enters)
{
enters = enter;
}
Scalar leave = midlen + v;
if (leave < leaves)
{
leaves = leave;
}
if (enters > leaves || enters > line->length || leaves < 0.0f)
{
return False;
}
line->length = Max(enters, 0.0f);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedSphere::TestInstance() const
{
return solidType == SphereType;
}
+672
View File
@@ -0,0 +1,672 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(ORIGIN_HPP)
# include <origin.hpp>
#endif
#if !defined(LINMTRX_HPP)
# include <linmtrx.hpp>
#endif
#if !defined(LINE_HPP)
# include <line.hpp>
#endif
#if !defined(PLANE_HPP)
# include <plane.hpp>
#endif
#if !defined(VECTOR2D_HPP)
# include <vector2d.hpp>
#endif
//#############################################################################
//######################### RightHandedTile ######################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RightHandedTile::RightHandedTile(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid,
Scalar *corners,
Type type
):
BoxedSolid(extents, type, material, owner, next_solid)
{
Check_Pointer(this);
for (int i=0; i<ELEMENTS(cornerHeight); ++i)
{
cornerHeight[i] = corners[i];
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
RightHandedTile::~RightHandedTile()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//-------------------------------------------------------------------
// See if the box hits the upper-right triangle anywhere on its plane
//-------------------------------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
Plane plane1(p0, p1, p2);
if (plane1.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
//
//------------------------------------------------------------------
// See if the box hits the lower-left triangle anywhere on its plane
//------------------------------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
Plane plane2(p0, p1, p2);
if (plane2.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(maxY >= point.y);
return FindDistanceBelowBounded(point) <= 0.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
RightHandedTile::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//---------------------------------------------------
// Figure out which triangle the point will reside in
//---------------------------------------------------
//
Scalar rise = maxX - minX;
Scalar run = maxZ - minZ;
Verify(rise > SMALL);
Verify(run > SMALL);
Scalar dx = point.x - minX;
Scalar dz = point.z - minZ;
//
//-----------------------------------------------------------------
// Set up the appropriate triangle based upon which have it lies in
//-----------------------------------------------------------------
//
Point3D p0,p1,p2;
if (dx*run > dz*rise)
{
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
}
else
{
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
}
//
//---------------------------------------------------------------------
// Make a plane out of the triangle, and have the plane solve for the Y
// coordinate
//---------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Verify(!Small_Enough(plane.normal.y));
Scalar height = point.y - plane.CalculateY(point.x, point.z);
Check_Fpu();
return height;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
static Scalar
LineHitsTriangle(
Line *line,
const Point3D &p0,
const Point3D &p1,
const Point3D &p2,
Scalar *cosine
)
{
//
//--------------------------------------------------------------------------
// Make the plane out of the three corner points, and figure out how far the
// ray must travel to reach this plane. Try some trivial rejections:
// parallel lines, lines starting outside the halfspace heading away from
// the plane, and lines starting outside the halfspace and heading towards
// the plane but are too far away
//--------------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Scalar length = line->DistanceTo(plane, cosine);
if (
Small_Enough(*cosine)
|| *cosine > 0.0f && length < 0.0f
|| *cosine < 0.0f && length > line->length
)
{
return -1.0f;
}
//
//--------------------------------------------------------
// Project the impact point and triangle unto the XZ plane
//--------------------------------------------------------
//
Point3D impact;
line->Project(length, &impact);
Vector2DOf<Scalar> proj(impact.x - p0.x, impact.z - p0.z);
Scalar x = p1.x - p0.x;
Scalar z = p2.z - p0.z;
//
//-------------------------------------------------------------------------
// Make sure that the area of the triangle made with the test point and the
// first leg is not negative or greater than the area of the triangle made
// by the two legs. The area of the triangle is half the cross product of
// the legs of that triangle
//-------------------------------------------------------------------------
//
Scalar area_ratio = z*x;
Verify(!Small_Enough(area_ratio));
area_ratio = x*proj.y / area_ratio;
Check_Fpu();
if (area_ratio >= 0.0f && area_ratio <= 1.0f)
{
//
//----------------------------------------------------------------------
// The area ratio represents the height of the test triangle relative to
// the given triangle. One edge of the value is represented by
// projecting the second leg a percentage equal to the ratio. The bounds
// of its variance is 1-area_ratio * the first leg of the triangle
//----------------------------------------------------------------------
//
Scalar span = proj.x / x;
Check_Fpu();
if (span >= 0.0f && span+area_ratio <= 1.0f)
{
return length;
}
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//----------------------------------------------
// See if the line hits the upper-right triangle
//----------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
Scalar cosine;
Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//---------------------------------------------
// See if the line hits the lower left triangle
//---------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//-------------------------------------------
// Neither triangle was entered, so we missed
//-------------------------------------------
//
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
RightHandedTile::TestInstance() const
{
return solidType == RightHandedTileType;
}
//#############################################################################
//######################### LeftHandedTile ######################
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LeftHandedTile::LeftHandedTile(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid,
Scalar *corners
):
RightHandedTile(
extents,
material,
owner,
next_solid,
corners,
LeftHandedTileType
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
LeftHandedTile::~LeftHandedTile()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::IntersectsBounded(const ExtentBox &extents)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//-------------------------------------------------------------------
// See if the box hits the upper-left triangle anywhere on its plane
//-------------------------------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[2];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[1];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[0];
p2.z = maxZ;
Plane plane1(p0, p1, p2);
if (plane1.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
//
//------------------------------------------------------------------
// See if the box hits the lower-right triangle anywhere on its plane
//------------------------------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[1];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[2];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[3];
p2.z = minZ;
Plane plane2(p0, p1, p2);
if (plane2.ContainsSomeOf(extents))
{
//
//-------------------------------------------------------------------
// Make sure the XZ projections of the triangle and the box intersect
//-------------------------------------------------------------------
//
return True;
}
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
LeftHandedTile::FindDistanceBelowBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//---------------------------------------------------
// Figure out which triangle the point will reside in
//---------------------------------------------------
//
Scalar rise = maxX - minX;
Scalar run = maxZ - minZ;
Verify(rise > SMALL);
Verify(run > SMALL);
Scalar dx = point.x - minX; // HACK - needs to be set up for other diagonal
Scalar dz = point.z - minZ;
//
//-----------------------------------------------------------------
// Set up the appropriate triangle based upon which have it lies in
//-----------------------------------------------------------------
//
Point3D p0,p1,p2;
if (dx*run > dz*rise)
{
p0.x = maxX;
p0.y = cornerHeight[1];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[0];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[3];
p2.z = maxZ;
}
else
{
p0.x = minX;
p0.y = cornerHeight[2];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[3];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[0];
p2.z = minZ;
}
//
//---------------------------------------------------------------------
// Make a plane out of the triangle, and have the plane solve for the Y
// coordinate
//---------------------------------------------------------------------
//
Plane plane(p0, p1, p2);
Verify(!Small_Enough(plane.normal.y));
Scalar height = point.y - plane.CalculateY(point.x, point.z);
Check_Fpu();
return height;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Check(this);
Check(line);
Verify(enters <= leaves);
Verify(leaves >= 0.0f);
//
//----------------------------------------------
// See if the line hits the upper-right triangle
//----------------------------------------------
//
Point3D p0,p1,p2;
p0.x = maxX;
p0.y = cornerHeight[2];
p0.z = minZ;
p1.x = minX;
p1.y = cornerHeight[1];
p1.z = minZ;
p2.x = maxX;
p2.y = cornerHeight[0];
p2.z = maxZ;
Scalar cosine;
Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//---------------------------------------------
// See if the line hits the lower left triangle
//---------------------------------------------
//
p0.x = minX;
p0.y = cornerHeight[1];
p0.z = maxZ;
p1.x = maxX;
p1.y = cornerHeight[2];
p1.z = maxZ;
p2.x = minX;
p2.y = cornerHeight[3];
p2.z = minZ;
length = LineHitsTriangle(line, p0, p1, p2, &cosine);
//
//--------------------------------------------------------------
// If we are entering the the plane, set the new entering length
//--------------------------------------------------------------
//
if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves)
{
line->length = length;
return True;
}
//
//-------------------------------------------
// Neither triangle was entered, so we missed
//-------------------------------------------
//
return False;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
LeftHandedTile::TestInstance() const
{
return solidType == LeftHandedTileType;
}
File diff suppressed because it is too large Load Diff
+892
View File
@@ -0,0 +1,892 @@
//===========================================================================//
// File: boxsolid.cc //
// Project: MUNGA Brick: Spatializer Library //
// Contents: Implementation details of bounding-box collision subtypes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 01/11/95 JMA Initial port back to C++ //
//---------------------------------------------------------------------------//
// Copyright (C) 1993-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(PLANE_HPP)
# include <plane.hpp>
#endif
extern Logical
BoxedRampContainsLine(
Line *line,
const Plane& plane,
Scalar enters,
Scalar leaves
);
//#############################################################################
//################# BoxedWedgeFacingNegativeZAndPositiveX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndPositiveX::BoxedWedgeFacingNegativeZAndPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingNegativeZAndPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndPositiveX::~BoxedWedgeFacingNegativeZAndPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.maxX - minX;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingNegativeZAndPositiveX::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Calculate the "slope" of the ramp when the NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise >= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = minZ - maxZ;
ramp.normal.y = 0.0f;
ramp.normal.z = maxX - minX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndPositiveX::TestInstance() const
{
return solidType == WedgeFacingNegativeZAndPositiveXType;
}
//#############################################################################
//################# BoxedWedgeFacingPositiveZAndNegativeX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndNegativeX::BoxedWedgeFacingPositiveZAndNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingPositiveZAndNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndNegativeX::~BoxedWedgeFacingPositiveZAndNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.minX - maxX;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise >= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingPositiveZAndNegativeX::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Calculate the "slope" of the ramp when the NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = minZ - maxZ;
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more positive than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run >= z/x yields
// rise*x >= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise >= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = maxZ - minZ;
ramp.normal.y = 0.0f;
ramp.normal.z = minX - maxX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndNegativeX::TestInstance() const
{
return solidType == WedgeFacingPositiveZAndNegativeXType;
}
//#############################################################################
//################# BoxedWedgeFacingPositiveZAndPositiveX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndPositiveX::BoxedWedgeFacingPositiveZAndPositiveX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingPositiveZAndPositiveXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingPositiveZAndPositiveX::~BoxedWedgeFacingPositiveZAndPositiveX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.maxX - minX;
Scalar z = extents.maxZ - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingPositiveZAndPositiveX::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Calculate the "slope" of the ramp when the NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = maxX - minX;
Scalar rise = minZ - maxZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - minX;
Scalar z = point.z - maxZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise <= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = minZ - maxZ;
ramp.normal.y = 0.0f;
ramp.normal.z = minX - maxX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = maxX*ramp.normal.x + minZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingPositiveZAndPositiveX::TestInstance() const
{
return solidType == WedgeFacingPositiveZAndPositiveXType;
}
//#############################################################################
//################# BoxedWedgeFacingNegativeZAndNegativeX ###############
//#############################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndNegativeX::BoxedWedgeFacingNegativeZAndNegativeX(
const ExtentBox &extents,
BoxedSolid::Material material,
Simulation *owner,
BoxedSolid *next_solid
):
BoxedSolid(
extents,
WedgeFacingNegativeZAndNegativeXType,
material,
owner,
next_solid
)
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
BoxedWedgeFacingNegativeZAndNegativeX::~BoxedWedgeFacingNegativeZAndNegativeX()
{
Check_Pointer(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::IntersectsBounded(
const ExtentBox &extents
)
{
Check(this);
Check(&extents);
Verify(minX <= extents.minX);
Verify(maxX >= extents.maxX);
Verify(minY <= extents.minY);
Verify(maxY >= extents.maxY);
Verify(minZ <= extents.minZ);
Verify(maxZ >= extents.maxZ);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = extents.minX - maxX;
Scalar z = extents.minZ - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::ContainsBounded(const Point3D &point)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(maxY >= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//----------------------------------------------------------------------
// Calculate the "slope" of the ramp when the base of the ramp is placed
// at the origin
//----------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
return x*rise <= z*run;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Scalar
BoxedWedgeFacingNegativeZAndNegativeX::FindDistanceBelowBounded(
const Point3D &point
)
{
Check(this);
Check(&point);
Verify(minX <= point.x);
Verify(maxX >= point.x);
Verify(minY <= point.y);
Verify(minZ <= point.z);
Verify(maxZ >= point.z);
//
//------------------------------------------------------------------------
// Calculate the "slope" of the ramp when the NW corner the ramp is placed
// at the origin
//------------------------------------------------------------------------
//
Scalar run = minX - maxX;
Scalar rise = maxZ - minZ;
Verify(!Small_Enough(run));
//
//-------------------------------------------------------------------
// Calculate the "slope" of the line from the base of the ramp to the
// lower-north edge of the block
//-------------------------------------------------------------------
//
Scalar x = point.x - maxX;
Scalar z = point.z - minZ;
//
//------------------------------------------------------------------------
// If the slope rise/run is more negative than z/x slope, then the extent
// box of the disk has clipped the ramp. Note that rise/run <= z/x yields
// rise*x <= z*run, which avoids any divide-by-0 errors.
//------------------------------------------------------------------------
//
if (x*rise <= z*run)
{
x = point.y - maxY;
return Max(x,0.0f);
}
return -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::HitByBounded(
Line *line,
Scalar enters,
Scalar leaves
)
{
Plane
ramp;
ramp.normal.x = maxZ - minZ;
ramp.normal.y = 0.0f;
ramp.normal.z = maxX - minX;
//
//-----------------------------
// Scale the vector to a normal
//-----------------------------
//
Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z;
Verify(!Small_Enough(temp));
temp = Sqrt(temp);
ramp.normal.x /= temp;
ramp.normal.z /= temp;
ramp.offset = minX*ramp.normal.x + maxZ*ramp.normal.z;
//
//---------------------------------------------------------------------
// Now that we have added a new plane into the definition of the convex
// polyhedron, call a common ramp line collider
//---------------------------------------------------------------------
//
return BoxedRampContainsLine(line, ramp, enters, leaves);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
BoxedWedgeFacingNegativeZAndNegativeX::TestInstance() const
{
return solidType == WedgeFacingNegativeZAndNegativeXType;
}
+590
View File
@@ -0,0 +1,590 @@
//===========================================================================//
// File: caminst.cc //
// Project: Munga //
// Contents: Class CameraInstance Data and Manipulation of one camera's //
// position and orientation //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/08/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
// Munga Includes
//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CAMINST_HPP)
# include <caminst.hpp>
#endif
#if !defined(NOTATION_HPP)
# include <notation.hpp>
#endif
//##########################################################################
//############################# CameraInstance #######################
//##########################################################################
//##########################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance::CameraInstance(
int camera_ID,
const Origin &camera_origin,
Enumeration camera_type
)
{
Str_Copy(cameraName, "camera", sizeof(cameraName));
itoa(camera_ID, cameraName+6, 10);
cameraID = camera_ID;
cameraDataType = camera_type;
SetLocalOrigin(camera_origin);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance::CameraInstance(StreamedInstance *model)
{
cameraID = model->cameraID;
localOrigin = model->localOrigin;
cameraToWorld = localOrigin;
cameraDataType = model->cameraType;
for (int i=0; i<4; ++i)
{
clampValues[i] = model->clampValues[i];
}
Str_Copy(cameraName, "camera", sizeof(cameraName));
itoa(cameraID, cameraName+6, 10);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define READ_CAMERA_ENTRY(name,value)\
if (\
!cam_file->GetEntry(\
camera_page_name,\
name,\
&value\
)\
)\
{ \
DEBUG_STREAM << camera_page_name << " missing " name "!\n";\
Fail("Bad cameras!");\
}
CameraInstance::CameraInstance(
NotationFile *cam_file,
const char *camera_page_name
)
{
Check(this);
Check(cam_file);
Check_Pointer(camera_page_name);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// PageName represents the cameraName
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Str_Copy(cameraName, camera_page_name, sizeof(cameraName));
//
//~~~~~~~~~~~~~~~~~~~~~
// Read in the position
//~~~~~~~~~~~~~~~~~~~~~
//
READ_CAMERA_ENTRY("tranx", localOrigin.linearPosition.x);
READ_CAMERA_ENTRY("trany", localOrigin.linearPosition.y);
READ_CAMERA_ENTRY("tranz", localOrigin.linearPosition.z);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// Read in the Orientation
//~~~~~~~~~~~~~~~~~~~~~~~~
//
READ_CAMERA_ENTRY("quatx", localOrigin.angularPosition.x);
READ_CAMERA_ENTRY("quaty", localOrigin.angularPosition.y);
READ_CAMERA_ENTRY("quatz", localOrigin.angularPosition.z);
READ_CAMERA_ENTRY("quatw", localOrigin.angularPosition.w);
cameraToWorld = localOrigin;
//
//---------------------
// Read in camera clamp
//---------------------
//
clampValues[0] = -PI;
cam_file->GetEntry(
camera_page_name,
"minYawClamp",
&clampValues[0].angle
);
clampValues[1] = PI;
cam_file->GetEntry(
camera_page_name,
"maxYawClamp",
&clampValues[1].angle
);
clampValues[2] = -PI_OVER_2;
cam_file->GetEntry(
camera_page_name,
"minPitchClamp",
&clampValues[2].angle
);
clampValues[3] = PI_OVER_2;
cam_file->GetEntry(
camera_page_name,
"maxPitchClamp",
&clampValues[3].angle
);
//
// Overwrite default cameraID
//
const char *camera_data_entry;
if(
!cam_file->GetEntry(
camera_page_name,
"cameraType",
&camera_data_entry
)
)
{
cameraDataType = DefaultCameraType;
}
else
{
Check_Pointer(camera_data_entry);
cameraDataType = FindCameraType(camera_data_entry);
}
READ_CAMERA_ENTRY("cameraID", cameraID);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance::~CameraInstance()
{
}
//##########################################################################
// Data Access Funtions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CameraInstance::FindCameraType(const char *camera_data_type)
{
if(strcmp("DefaultCameraType", camera_data_type) == 0)
{
return DefaultCameraType;
}
else if(strcmp("AlwaysSeesCameraType", camera_data_type) == 0)
{
return AlwaysSeesCameraType;
}
return ErrorCameraType;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::GetCameraTypeString(char *camera_type_string)
{
switch(cameraDataType)
{
case DefaultCameraType:
Str_Copy(
camera_type_string,
"DefaultCameraType",
(sizeof(char) * 128)
);
break;
case AlwaysSeesCameraType:
Str_Copy(
camera_type_string,
"AlwaysSeesCameraType",
(sizeof(char) * 128)
);
break;
default:
Tell(cameraDataType);
Warn(" Invalid cameraType !\n");
break;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::CalculateCameraRotation(
YawPitchRoll *result,
const Point3D &world
)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Given a Vector this function finds a rotation involving only
// pitch and yaw, roll will not be affected. In addition the rotation
// chosed will always be in the direction of least rotation
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(this);
Check(result);
Check(&world);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// find the vector from where we are to where we want to point
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Point3D local;
local.MultiplyByInverse(world, cameraToWorld);
if (Small_Enough(local.LengthSquared()))
{
*result = YawPitchRoll::Identity;
return;
}
//
//~~~~~~~~~~~~~~~~~~~~~
// Calculate the angles
//~~~~~~~~~~~~~~~~~~~~~
//
result->yaw = Radian::Normalize(Arctan(-local.x, -local.z));
Scalar xz_direction = Sqrt((local.x * local.x) + (local.z *local.z));
result->pitch = Radian::Normalize(Arctan(local.y, xz_direction));
result->roll = 0.0f;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::SetLocalOrigin(
const Origin &new_origin
)
{
Check(this);
Check(&new_origin);
YawPitchRoll ypr;
ypr = new_origin.angularPosition;
clampValues[0] = clampValues[1] = 0.0f;
clampValues[2] = clampValues[3] = ypr.pitch;
ypr.pitch = 0.0f;
localOrigin.linearPosition = new_origin.linearPosition;
localOrigin.angularPosition = ypr;
cameraToWorld = localOrigin;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::LookAt(
Origin *result,
const Point3D &world_point
)
{
result->linearPosition = localOrigin.linearPosition;
YawPitchRoll first,local;
first = localOrigin.angularPosition;
CalculateCameraRotation(&local, world_point);
Clamp(local.yaw, clampValues[0], clampValues[1]);
Clamp(local.pitch, clampValues[2], clampValues[3]);
first.yaw += local.yaw;
first.pitch = local.pitch;
result->angularPosition = first;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::AllowLookingAt(const Point3D &world)
{
YawPitchRoll local;
CalculateCameraRotation(&local, world);
if (local.yaw < clampValues[0])
{
clampValues[0] = local.yaw;
}
else if (local.yaw > clampValues[1])
{
clampValues[1] = local.yaw;
}
if (local.pitch < clampValues[2])
{
clampValues[2] = local.pitch;
}
else if (local.pitch > clampValues[3])
{
clampValues[3] = local.pitch;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define YAW_SLOP (PI/12.0)
#define PITCH_SLOP (0.75*(YAW_SLOP))
Logical
CameraInstance::CanCameraSee(const Point3D &world_point)
{
YawPitchRoll ypr;
CalculateCameraRotation(&ypr, world_point);
return
clampValues[0]-YAW_SLOP <= ypr.yaw
&& clampValues[1]+YAW_SLOP >= ypr.yaw
&& clampValues[2]-PITCH_SLOP <= ypr.pitch
&& clampValues[3]+PITCH_SLOP >= ypr.pitch;
}
//##########################################################################
// Test Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraInstance::TestInstance() const
{
return True;
}
//##########################################################################
// Tool Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstance::WriteNotationPage(NotationFile *camera_stream)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Output this camera's information to the given notation file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(this);
Check(camera_stream);
camera_stream->SetEntry(
cameraName,
"cameraID",
cameraID
);
char camera_type[128];
GetCameraTypeString(camera_type);
camera_stream->SetEntry(
cameraName,
"cameraType",
camera_type
);
camera_stream->SetEntry(
cameraName,
"tranx",
localOrigin.linearPosition.x
);
camera_stream->SetEntry(
cameraName,
"trany",
localOrigin.linearPosition.y
);
camera_stream->SetEntry(
cameraName,
"tranz",
localOrigin.linearPosition.z
);
camera_stream->SetEntry(
cameraName,
"quatx",
localOrigin.angularPosition.x
);
camera_stream->SetEntry(
cameraName,
"quaty",
localOrigin.angularPosition.y
);
camera_stream->SetEntry(
cameraName,
"quatz",
localOrigin.angularPosition.z
);
camera_stream->SetEntry(
cameraName,
"quatw",
localOrigin.angularPosition.w
);
camera_stream->SetEntry(
cameraName,
"minYawClamp",
clampValues[0]
);
camera_stream->SetEntry(
cameraName,
"maxYawClamp",
clampValues[1]
);
camera_stream->SetEntry(
cameraName,
"minPitchClamp",
clampValues[2]
);
camera_stream->SetEntry(
cameraName,
"maxPitchClamp",
clampValues[3]
);
camera_stream->AppendEntry(cameraName, NULL, (char *)NULL);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#undef READ_CAMERA_ENTRY
#define READ_CAMERA_ENTRY(name,value)\
if (\
!cam_file->GetEntry(\
camera_page_name,\
name,\
&value\
)\
)\
{ \
DEBUG_STREAM << camera_page_name << " missing " name "!\n";\
return False;\
}
Logical
CameraInstance::CreateStreamedInstance(
StreamedInstance *model,
NotationFile *cam_file,
const char *camera_page_name
)
{
Check_Pointer(model);
Check(cam_file);
Check_Pointer(camera_page_name);
//
//~~~~~~~~~~~~~~~~~~~~~
// Read in the position
//~~~~~~~~~~~~~~~~~~~~~
//
READ_CAMERA_ENTRY("tranx", model->localOrigin.linearPosition.x);
READ_CAMERA_ENTRY("trany", model->localOrigin.linearPosition.y);
READ_CAMERA_ENTRY("tranz", model->localOrigin.linearPosition.z);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// Read in the Orientation
//~~~~~~~~~~~~~~~~~~~~~~~~
//
READ_CAMERA_ENTRY("quatx", model->localOrigin.angularPosition.x);
READ_CAMERA_ENTRY("quaty", model->localOrigin.angularPosition.y);
READ_CAMERA_ENTRY("quatz", model->localOrigin.angularPosition.z);
READ_CAMERA_ENTRY("quatw", model->localOrigin.angularPosition.w);
//
//---------------------
// Read in camera clamp
//---------------------
//
model->clampValues[0] = -PI;
cam_file->GetEntry(
camera_page_name,
"minYawClamp",
&model->clampValues[0].angle
);
model->clampValues[1] = PI;
cam_file->GetEntry(
camera_page_name,
"maxYawClamp",
&model->clampValues[1].angle
);
model->clampValues[2] = -PI_OVER_2;
cam_file->GetEntry(
camera_page_name,
"minPitchClamp",
&model->clampValues[2].angle
);
model->clampValues[3] = PI_OVER_2;
cam_file->GetEntry(
camera_page_name,
"maxPitchClamp",
&model->clampValues[3].angle
);
//
// Overwrite default cameraID
//
const char *camera_data_entry;
if(
!cam_file->GetEntry(
camera_page_name,
"cameraType",
&camera_data_entry
)
)
{
model->cameraType = DefaultCameraType;
}
else
{
Check_Pointer(camera_data_entry);
model->cameraType = FindCameraType(camera_data_entry);
}
READ_CAMERA_ENTRY("cameraID", model->cameraID);
model->instanceSize = sizeof(*model);
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AlwaysSeesCameraInstance::AlwaysSeesCameraInstance(
int camera_ID,
const Origin &camera_origin,
Enumeration camera_type
):
CameraInstance(camera_ID, camera_origin, camera_type)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AlwaysSeesCameraInstance::AlwaysSeesCameraInstance(StreamedInstance *model):
CameraInstance(model)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AlwaysSeesCameraInstance::AlwaysSeesCameraInstance(
NotationFile *cam_file,
const char *camera_page_name
):
CameraInstance(cam_file, camera_page_name)
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
AlwaysSeesCameraInstance::CanCameraSee(const Point3D &)
{
return True;
}
+201
View File
@@ -0,0 +1,201 @@
//===========================================================================//
// File: caminst.hh //
// Project: Munga //
// Contents: CameraInstance Interface //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/08/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CAMINST_HPP)
# define CAMINST_HPP
# if !defined (PLUG_HPP)
# include <plug.hpp>
# endif
# if !defined (ORIGIN_HPP)
# include <origin.hpp>
# endif
# if !defined (ROTATION_HPP)
# include <rotation.hpp>
# endif
# if !defined(LINMTRX_HPP)
# include <linmtrx.hpp>
# endif
class NotationFile;
struct CameraInstance__StreamedInstance
{
size_t instanceSize;
int
cameraType,
cameraID;
Origin
localOrigin;
Radian
clampValues[4];
};
//##########################################################################
//############################# CameraInstance #######################
//##########################################################################
class CameraInstance :
public Plug
{
friend class CameraInstanceManager;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// local member data
//
public:
enum {
ErrorCameraType,
DefaultCameraType,
AlwaysSeesCameraType,
CameraTypeCount,
};
Radian
clampValues[4];
protected:
Origin
localOrigin;
LinearMatrix
cameraToWorld;
static int
FindCameraType(const char *camera_data_type);
void
GetCameraTypeString(char *camera_type_string);
Enumeration
cameraDataType;
int
cameraID;
char
cameraName[128];
void
CalculateCameraRotation(
YawPitchRoll *result,
const Point3D &world
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// public member data access functions
//
public:
int
GetCameraID()
{Check(this); return cameraID;}
const char*
GetCameraName()
{Check(this); return cameraName;}
void
SetCameraName(const char* camera_name)
{Str_Copy(cameraName, camera_name, sizeof(cameraName));}
const Enumeration
GetCameraType()
{Check(this); return cameraDataType;}
const Origin&
GetLocalOrigin()
{Check(this); return localOrigin;}
void
SetLocalOrigin(const Origin &new_origin);
const Point3D&
GetPosition()
{Check(this); return localOrigin.linearPosition;}
void
LookAt(
Origin *result,
const Point3D &world_point
);
void
AllowLookingAt(const Point3D &world);
virtual Logical
CanCameraSee(const Point3D &world_point);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Class Support
//
public:
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Contruction and Destruction Support
//
public:
typedef CameraInstance__StreamedInstance StreamedInstance;
CameraInstance(
int camera_ID,
const Origin &camera_origin,
Enumeration camera_type = DefaultCameraType
);
CameraInstance(StreamedInstance *model);
CameraInstance(
NotationFile *cam_file,
const char *camera_page_name
);
~CameraInstance();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Tool Support
//
public:
void
WriteNotationPage(NotationFile *camera_stream);
static Logical
CreateStreamedInstance(
StreamedInstance *model,
NotationFile *cam_file,
const char *camera_page_name
);
};
//##########################################################################
//############################# CameraInstance #######################
//##########################################################################
class AlwaysSeesCameraInstance :
public CameraInstance
{
public:
AlwaysSeesCameraInstance(
int camera_ID,
const Origin &camera_origin,
Enumeration camera_type = DefaultCameraType
);
AlwaysSeesCameraInstance(StreamedInstance *model);
AlwaysSeesCameraInstance(
NotationFile *cam_file,
const char *camera_page_name
);
Logical
CanCameraSee(const Point3D &world_point);
};
#endif
+779
View File
@@ -0,0 +1,779 @@
//===========================================================================//
// File: cammgr.cc //
// Project: Munga //
// Contents: Implementation details of vectored thrust vehicles //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/09/95 JM Initial coding. //
// Classes: CameraInstanceManager //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
// Munga Includes
//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CAMMGR_HPP)
# include <cammgr.hpp>
#endif
#if !defined(MISSION_HPP)
# include <mission.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(NOTATION_HPP)
#include <notation.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
//##########################################################################
//##################### CameraInstanceManager #######################
//##########################################################################
//##########################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstanceManager::CameraInstanceManager() :
cameraList(NULL)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize local member data
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
cameraIterator = new SChainIteratorOf<CameraInstance*>(cameraList);
Register_Object(cameraIterator);
InitializeCameraInstances();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstanceManager::~CameraInstanceManager()
{
DeleteCameraList();
Unregister_Object(cameraIterator);
delete cameraIterator;
cameraIterator = NULL;
Check_Fpu();
}
//##########################################################################
// CameraInstance Creation and Deletion Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
CameraInstanceManager::FindUniqueCameraID()
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Finds a cameraID that has been freed up or the next sequential number
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
int camera_ID = 0;
Logical ID_exists = False;
while(1)
{
//
//~~~~~~~~~~~~~~~~~~~~
// Reset the iterator
//~~~~~~~~~~~~~~~~~~~~
//
iterator.First();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Iterate through the list of all cameraInstances for every ID Chosen
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
if(camera_ID == camera_instance->GetCameraID())
{
ID_exists = True;
break;
}
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If this cameraID not already used return the ID
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if(!ID_exists)
{
break;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Otherwise increment the ID and reset the boolean
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
++camera_ID;
ID_exists = False;
}
Check_Fpu();
return camera_ID;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::SetCamera(
const Origin &new_origin,
CameraInstance *camera_instance
)
{
if(!camera_instance)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// No camera passed as an argument use cameraIterator
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
camera_instance = cameraIterator->GetCurrent();
if(!camera_instance)
{
CreateCameraInstance(new_origin);
}
else
{
camera_instance->SetLocalOrigin(new_origin);
}
}
else
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Camera passed in set its origin
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
camera_instance->SetLocalOrigin(new_origin);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::CreateCameraInstance(const Origin &new_origin)
{
Check(this);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// Find a Unique CameraID
//~~~~~~~~~~~~~~~~~~~~~~~~
//
int camera_ID;
camera_ID = FindUniqueCameraID();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the new cameraInstance
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance *camera_instance =
new CameraInstance(
camera_ID,
new_origin
);
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
Check_Fpu();
return camera_instance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance)
{
Check(this);
Check(cameraIterator);
Check(&cameraList);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Insert the new Camera Instance into the cameraList
// & Point the cameraIterator to it
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (!cameraIterator->GetCurrent())
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// If nothing in the cameraList create the first element
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
cameraList.Add(camera_instance);
cameraIterator->First();
Tell("Created the First Camera Instance \n");
}
else
{
cameraList.Add(camera_instance);
cameraIterator->Next();
Tell("Created a Camera Instance \n");
}
Check_Fpu();
return camera_instance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::DeleteCameraInstance()
{
CameraInstance *camera_instance = cameraIterator->GetCurrent();
if(!camera_instance)
{
return NULL;
}
cameraIterator->Remove();
if(!cameraIterator->GetCurrent())
{
cameraIterator->First();
}
Unregister_Object(camera_instance);
delete camera_instance;
return GetCurrent();
}
//##########################################################################
// CameraList Manipulator Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::DeleteCameraList()
{
while (cameraIterator->GetCurrent() != NULL)
{
DeleteCameraInstance();
}
}
//##########################################################################
// CameraList Iterator Manipulator Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::IncrementIterator()
{
Check(this);
if (cameraIterator->GetCurrent())
{
Check(cameraIterator);
cameraIterator->ReadAndNext();
if (!cameraIterator->GetCurrent())
{
cameraIterator->First();
}
}
Check_Fpu();
return GetCurrent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::DecrementIterator()
{
Check(this);
if (cameraIterator->GetCurrent())
{
Check(cameraIterator);
cameraIterator->ReadAndPrevious();
if (!cameraIterator->GetCurrent())
{
cameraIterator->Last();
}
}
Check_Fpu();
return GetCurrent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Search for the camera_instance in the cameraList
// Iterator points to camera_instance upon return
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(&camera_instance);
Check(&cameraList);
Check(cameraIterator);
CameraInstance *current_instance;
cameraIterator->First();
while((current_instance = cameraIterator->GetCurrent()) != NULL)
{
if(current_instance == &camera_instance)
{
Check_Fpu();
return current_instance;
}
cameraIterator->Next();
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// camera_instance not found return NULL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check_Fpu();
return NULL;
}
//##########################################################################
// CameraList Searching and Query Functions
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance*
CameraInstanceManager::FindClosestCamera(const Point3D &point_3D)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Use a Simple distance formula to find closest camera
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Check(this);
CameraInstance *closest_camera = NULL;
Scalar dist_to_goal, min_dist=1e8f;
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
Check(camera_instance);
if (camera_instance->CanCameraSee(point_3D))
{
Vector3D v;
v.Subtract(point_3D, camera_instance->GetPosition());
dist_to_goal = v.LengthSquared();
Check_Fpu();
if (dist_to_goal < min_dist)
{
min_dist = dist_to_goal;
closest_camera = camera_instance;
}
}
}
Check_Fpu();
return closest_camera;
}
//##########################################################################
// Test Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraInstanceManager::TestInstance() const
{
return True;
}
//##########################################################################
// Tool Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::InitializeCameraInstances()
{
Check(application);
ResourceDescription::ResourceID map_ID;
map_ID = application->GetCurrentMission()->GetMapID();
ResourceFile *res_file;
res_file = application->GetResourceFile();
Check(res_file);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the camera filename from the map name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResourceDescription *res = res_file->FindResourceDescription(map_ID);
Check(res);
Str_Copy(
cameraFilename,
"cameras\\",
sizeof(cameraFilename)
);
//
// cam name matches map name
//
Str_Cat(
cameraFilename,
res->resourceName,
sizeof(cameraFilename)
);
//
// trunc cam name to DOS filename size
//
int name_length = strlen(cameraFilename);
if(name_length > 17)
{
cameraFilename[17] = '\0';
}
//
// Add the extension
//
Str_Cat(
cameraFilename,
".cam",
sizeof(cameraFilename)
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// See if the file exists
//~~~~~~~~~~~~~~~~~~~~~~~~
//
fstream cam_file;
cam_file.open(cameraFilename, ios::nocreate | ios::in | ios::out);
if(cam_file)
{
cam_file.close();
ReadNotationFile();
}
else
{
cam_file.close();
CreateStreamedCameraInstances(res_file, res->resourceName);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::ReadNotationFile()
{
Check(this);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create a Notation file out of the camera file
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NotationFile *cam_file = new NotationFile(cameraFilename);
Register_Object(cam_file);
NameList* camera_namelist = cam_file->MakePageList();
Register_Object(camera_namelist);
NameList::Entry *camera_entry = camera_namelist->GetFirstEntry();
char
camera_page_name[128];
while (camera_entry)
{
Str_Copy(
camera_page_name,
camera_entry->GetName(),
sizeof(camera_page_name)
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create a new camera Instance for this page
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraInstance *camera_instance;
const char *camera_data_entry;
int cam_type;
if(
!cam_file->GetEntry(
camera_page_name,
"cameraType",
&camera_data_entry
)
)
{
cam_type = CameraInstance::DefaultCameraType;
}
else
{
Check_Pointer(camera_data_entry);
cam_type = CameraInstance::FindCameraType(camera_data_entry);
}
switch (cam_type)
{
case CameraInstance::DefaultCameraType:
camera_instance = new CameraInstance(cam_file, camera_page_name);
break;
case CameraInstance::AlwaysSeesCameraType:
camera_instance =
new AlwaysSeesCameraInstance(cam_file, camera_page_name);
break;
}
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
camera_entry = camera_entry->GetNextEntry();
}
Unregister_Object(camera_namelist);
delete camera_namelist;
Unregister_Object(cam_file);
delete cam_file;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define PAGE_NAME_SIZE 128
void
CameraInstanceManager::CreateStreamedCameraInstances(
ResourceFile *res_file,
const char *map_name
)
{
Check(this);
Check_Pointer(res_file);
Check_Pointer(map_name);
ResourceDescription *res =
res_file->FindResourceDescription(
map_name,
ResourceDescription::CameraStreamResourceType
);
if (!res)
{
Check_Fpu();
return;
}
res->Lock();
MemoryStream camera_stream(res->resourceAddress, res->resourceSize);
int camera_count = *(int*)camera_stream.GetPointer();
camera_stream.AdvancePointer(sizeof(camera_count));
//
//--------------------
// Read in each camera
//--------------------
//
while (camera_count--)
{
Check(&camera_stream);
CameraInstance::StreamedInstance *model =
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
Check_Pointer(model);
CameraInstance *camera_instance;
switch (model->cameraType)
{
case CameraInstance::DefaultCameraType:
camera_instance = new CameraInstance(model);
break;
case CameraInstance::AlwaysSeesCameraType:
camera_instance = new AlwaysSeesCameraInstance(model);
break;
}
Register_Object(camera_instance);
AddCameraInstance(camera_instance);
camera_stream.AdvancePointer(model->instanceSize);
}
res->Unlock();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraInstanceManager::WriteNotationFile()
{
Check(this);
Check(&cameraList);
NotationFile *camera_stream = new NotationFile();
Register_Object(camera_stream);
if(!camera_stream)
{
Fail("Error Opening Camera File\n");
}
SChainIteratorOf<CameraInstance*> iterator(cameraList);
CameraInstance *camera_instance;
iterator.First();
while ( (camera_instance = iterator.ReadAndNext()) != NULL)
{
camera_instance->WriteNotationPage(camera_stream);
}
camera_stream->WriteFile(cameraFilename);
Unregister_Object(camera_stream);
delete camera_stream;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
#define PAGE_NAME_SIZE 128
ResourceDescription::ResourceID
CameraInstanceManager::CreateCameraInstancesStream(
ResourceFile *resource_file,
const char *camera_name,
const ResourceDirectories *directories
)
{
Check_Pointer(camera_name);
Check_Pointer(directories);
//
//-------------------
// Open the .cam file
//-------------------
//
int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1;
char *filename = new char[length];
Register_Pointer(filename);
Str_Copy(filename, directories->mapDirectory, length);
strncat(filename, camera_name, strlen(camera_name)-3);
Str_Cat(filename, "cam", length);
NotationFile *camera_notation = new NotationFile(filename);
Register_Object(camera_notation);
if (camera_notation->PageCount() == 0)
{
DEBUG_STREAM << "Missing .cam file" << endl;
Dump_And_Die:
Unregister_Object(camera_notation);
delete camera_notation;
Unregister_Pointer(filename);
delete[] filename;
return ResourceDescription::NullResourceID;
}
int camera_count = 0;
NameList *pagelist = camera_notation->MakePageList();
Register_Object(pagelist);
NameList::Entry *entry = pagelist->GetFirstEntry();
char page_name[PAGE_NAME_SIZE];
while (entry)
{
++camera_count;
entry = entry->GetNextEntry();
}
size_t array_size =
sizeof(CameraInstance::StreamedInstance) * camera_count * 2;
long *camera_array = new long[(array_size+3) >> 2];
Register_Pointer(camera_array);
MemoryStream camera_stream(camera_array, array_size);
*(int*)camera_stream.GetPointer() = camera_count;
camera_stream.AdvancePointer(sizeof(camera_count));
entry = pagelist->GetFirstEntry();
while (entry)
{
Str_Copy(
page_name,
entry->GetName(),
sizeof(page_name)
);
if(strcmp(page_name, "CameraInfo") == 0)
{
entry = entry->GetNextEntry();
continue;
}
Check(&camera_stream);
CameraInstance::StreamedInstance *model =
(CameraInstance::StreamedInstance*)camera_stream.GetPointer();
Check_Pointer(model);
if (
!CameraInstance::CreateStreamedInstance(
model,
camera_notation,
page_name
)
)
{
Unregister_Pointer(camera_array);
delete[] camera_array;
Unregister_Object(pagelist);
delete pagelist;
goto Dump_And_Die;
}
camera_stream.AdvancePointer(model->instanceSize);
entry = entry->GetNextEntry();
}
//
//-------------------------------
// Write the stream out to disk.
//
Str_Copy(filename, camera_name, length);
filename[strlen(camera_name)-4] = '\0';
ResourceDescription *new_res =
resource_file->AddResource(
filename,
ResourceDescription::CameraStreamResourceType,
1,
ResourceDescription::LoadOnDemandFlag,
camera_array,
camera_stream.GetBytesUsed()
);
Check(new_res);
//-----------
// Free Mem
//
Unregister_Pointer(camera_array);
delete[] camera_array;
Unregister_Pointer(filename);
delete[] filename;
Unregister_Object(camera_notation);
delete camera_notation;
Unregister_Object(pagelist);
delete pagelist;
return new_res->resourceID;
}
+159
View File
@@ -0,0 +1,159 @@
//===========================================================================//
// File: cammgr.hh //
// Project: Munga //
// Contents: Camera Interface //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/08/95 JM Initial coding. //
// Classes: CameraInstanceManager //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CAMMGR_HPP)
# define CAMMGR_HPP
# if !defined(RESOURCE_HPP)
# include <resource.hpp>
# endif
# if !defined(SCHAIN_HPP)
# include <schain.hpp>
# endif
# if !defined(CAMINST_HPP)
# include <caminst.hpp>
# endif
//##########################################################################
//##################### CameraInstanceManager #######################
//##########################################################################
class CameraInstanceManager SIGNATURED
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// local member data
//
protected:
//
// cameraList is a circular Linked list
// which holds cameraInstances
//
SChainOf<CameraInstance*> cameraList;
//
// CameraIterator holds the current position in the
// camera list for the lifetime of the class
// & == NULL if the list is empty
//
SChainIteratorOf<CameraInstance*> *cameraIterator;
int
FindUniqueCameraID();
char
cameraFilename[128];
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public Member Manipulation Functions
//
public:
//
// CameraList Manipulator Functions
//
void
SetCamera(
const Origin &new_origin,
CameraInstance *camera_instance = NULL
);
CameraInstance*
CreateCameraInstance(const Origin &new_origin);
CameraInstance*
AddCameraInstance(CameraInstance *camera_instance);
CameraInstance*
DeleteCameraInstance();
void
DeleteCameraList();
//
// Iterator Manipulator Functions (Circular Chain)
//
CameraInstance*
IncrementIterator();
CameraInstance*
DecrementIterator();
CameraInstance*
AdvanceIterator(const CameraInstance &camera_instance);
CameraInstance*
GetCurrent() const
{Check(this); return cameraIterator->GetCurrent();}
CameraInstance*
First()
{
Check(this);
Check(cameraIterator->GetCurrent());
cameraIterator->First();
return GetCurrent();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CameraList Searching and Query Functions
//
public:
CameraInstance*
FindClosestCamera(const Point3D &point_3D);
CameraInstance*
FindClosestCameraShowing(const Point3D *points);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Class Support
//
public:
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
public:
CameraInstanceManager();
~CameraInstanceManager();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Tool Support
//
protected:
void
InitializeCameraInstances();
public:
void
ReadNotationFile();
void
CreateStreamedCameraInstances(
ResourceFile *res_file,
const char *map_name
);
void
WriteNotationFile();
static ResourceDescription::ResourceID
CreateCameraInstancesStream(
ResourceFile *resource_file,
const char *camera_name,
const ResourceDirectories *directories
);
};
#endif
+262
View File
@@ -0,0 +1,262 @@
//===========================================================================//
// File: cammppr.hpp. //
// Project: MUNGA Brick: Camera Controls Mapper //
// Contents: Interface specification for camera mapper //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/20/95 JM Initial Coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
// Munga
//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CAMMPPR_HPP)
# include <cammppr.hpp>
#endif
//#############################################################################
// Shared Data Support
//
CameraControlsMapper::SharedData
CameraControlsMapper::DefaultData(
CameraControlsMapper::ClassDerivations,
CameraControlsMapper::MessageHandlers,
CameraControlsMapper::AttributeIndex,
CameraControlsMapper::StateCount
);
Derivation
CameraControlsMapper::ClassDerivations(
Subsystem::ClassDerivations,
"CameraControlsMapper"
);
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
CameraControlsMapper::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(CameraControlsMapper, Keypress),
MESSAGE_ENTRY(CameraControlsMapper, DirectorMode),
MESSAGE_ENTRY(CameraControlsMapper, IncrementCamera),
MESSAGE_ENTRY(CameraControlsMapper, DecrementCamera),
MESSAGE_ENTRY(CameraControlsMapper, CreateCameraInstance),
MESSAGE_ENTRY(CameraControlsMapper, DeleteCameraInstance),
MESSAGE_ENTRY(CameraControlsMapper, OutputCameraInstances)
};
CameraControlsMapper::MessageHandlerSet
CameraControlsMapper::MessageHandlers(
ELEMENTS(CameraControlsMapper::MessageHandlerEntries),
CameraControlsMapper::MessageHandlerEntries,
Subsystem::MessageHandlers
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::KeypressMessageHandler(
ReceiverDataMessageOf<ControlsKey> *message
)
{
Check(this);
Check(message);
switch (message->dataContents)
{
case 'd':
case 'D':
{
ReceiverDataMessageOf<ControlsButton>
button_message2(
CameraControlsMapper::DirectorModeMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
Dispatch(&button_message2);
break;
}
case 'o':
case 'O':
{
ReceiverDataMessageOf<ControlsButton>
button_message2(
CameraControlsMapper::OutputCameraInstancesMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
Dispatch(&button_message2);
break;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::DirectorModeMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if (message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
if(camera->GetSimulationState() != CameraShip::ConfigureCamerasState)
{
camera->SetPerformance(&CameraShip::DriveCamera);
camera->SetSimulationState(CameraShip::ConfigureCamerasState);
CameraInstance *cam = camera->GetCurrentCamera();
Check(cam);
DEBUG_STREAM << cam->GetCameraName() << endl;
}
else
{
camera->SetPerformance(&CameraShip::FollowGoal);
camera->SetSimulationState(CameraShip::DefaultState);
camera->lastSwitch = Now();
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::IncrementCameraMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if(message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
camera->IncrementCameraInstance();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::DecrementCameraMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if (message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
camera->DecrementCameraInstance();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::CreateCameraInstanceMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if (message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
camera->CreateCameraInstance();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::DeleteCameraInstanceMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if (message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
camera->DeleteCameraInstance();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraControlsMapper::OutputCameraInstancesMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
if (message->dataContents > 0)
{
CameraShip *camera = GetEntity();
Check(camera);
camera->OutputCameraList();
}
}
//#############################################################################
// Attribute Support
//
const CameraControlsMapper::IndexEntry
CameraControlsMapper::AttributePointers[]=
{
ATTRIBUTE_ENTRY(CameraControlsMapper, StickPosition, stickPosition),
ATTRIBUTE_ENTRY(CameraControlsMapper, ThrottlePosition, throttlePosition),
ATTRIBUTE_ENTRY(CameraControlsMapper, PedalsPosition, pedalsPosition),
ATTRIBUTE_ENTRY(CameraControlsMapper, ReverseThrust, reverseThrust),
ATTRIBUTE_ENTRY(CameraControlsMapper, DriveCamera, driveCamera),
ATTRIBUTE_ENTRY(CameraControlsMapper, SlideOrClamp, slideOrClamp)
};
CameraControlsMapper::AttributeIndexSet
CameraControlsMapper::AttributeIndex(
ELEMENTS(CameraControlsMapper::AttributePointers),
CameraControlsMapper::AttributePointers,
Subsystem::AttributeIndex
);
//#############################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraControlsMapper::CameraControlsMapper(
CameraShip *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
):
Subsystem(owner, subsystem_ID, subsystem_resource, shared_data)
{
stickPosition.x = 0.0f;
stickPosition.y = 0.0f;
throttlePosition = 0.0f;
pedalsPosition = 0.0f;
driveCamera = 0;
slideOrClamp = 0;
reverseThrust = 0;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraControlsMapper::~CameraControlsMapper()
{
}
Logical
CameraControlsMapper::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
+163
View File
@@ -0,0 +1,163 @@
//===========================================================================//
// File: cammppr.hpp. //
// Project: MUNGA Brick: Camera Controls Mapper //
// Contents: Interface specification for camera mapper //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/20/95 JM Initial Coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CAMMPPR_HPP)
# define CAMMPPR_HPP
# if !defined (SUBSYSTM_HPP)
# include <subsystm.hpp>
# endif
# if !defined (CAMSHIP_HPP)
# include <camship.hpp>
# endif
# if !defined (CONTROLS_HPP)
# include <controls.hpp>
# endif
//##########################################################################
//####################### CameraControlsMapper ########################
//##########################################################################
class CameraControlsMapper:
public Subsystem
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support
//
public:
enum {
KeypressMessageID = Subsystem::NextMessageID,
DirectorModeMessageID,
IncrementCameraMessageID,
DecrementCameraMessageID,
CreateCameraInstanceMessageID,
DeleteCameraInstanceMessageID,
OutputCameraInstancesMessageID,
NextMessageID
};
void
KeypressMessageHandler(ReceiverDataMessageOf<ControlsKey> *message);
void
DirectorModeMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
void
IncrementCameraMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
void
DecrementCameraMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
void
CreateCameraInstanceMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
void
DeleteCameraInstanceMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
void
OutputCameraInstancesMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
);
protected:
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
enum {
StickPositionAttributeID = Subsystem::NextAttributeID,
ThrottlePositionAttributeID,
PedalsPositionAttributeID,
ReverseThrustAttributeID,
DriveCameraAttributeID,
SlideOrClampAttributeID,
NextAttributeID
};
private:
static const IndexEntry AttributePointers[];
protected:
static AttributeIndexSet AttributeIndex;
//
// public attribute declarations go here
//
public:
ControlsJoystick stickPosition;
Scalar throttlePosition;
Scalar pedalsPosition;
ControlsButton
reverseThrust,
driveCamera,
slideOrClamp;
//##########################################################################
// Model support
//
public:
CameraShip*
GetEntity()
{return (CameraShip*)Subsystem::GetEntity();}
typedef void
(CameraControlsMapper::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
protected:
CameraControlsMapper(
CameraShip *owner,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
);
public:
~CameraControlsMapper();
Logical
TestInstance() const;
};
#endif
+767
View File
@@ -0,0 +1,767 @@
//===========================================================================//
// File: camship.cc //
// Project: Munga //
// Contents: CameraShip Controls the current viewpoint of the cameraShip & //
// manages the simulation modes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/09/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
// munga Includes
//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CAMSHIP_HPP)
# include <camship.hpp>
#endif
#if !defined(PLAYER_HPP)
# include <player.hpp>
#endif
#if !defined(MISSION_HPP)
# include <mission.hpp>
#endif
#if !defined(CAMMPPR_HPP)
# include <cammppr.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(HOSTMGR_HPP)
#include <hostmgr.hpp>
#endif
//##########################################################################
//############################# CameraShip ################################
//##########################################################################
//#############################################################################
// Shared Data Support
//
Derivation
CameraShip::ClassDerivations(
Mover::ClassDerivations,
"CameraShip"
);
CameraShip::SharedData
CameraShip::DefaultData(
CameraShip::ClassDerivations,
CameraShip::MessageHandlers,
CameraShip::AttributeIndex,
CameraShip::StateCount,
(Entity::MakeHandler)CameraShip::Make
);
//#############################################################################
// Attribute Support
//
const CameraShip::IndexEntry
CameraShip::AttributePointers[]=
{
ATTRIBUTE_ENTRY(CameraShip, MapRange, mapRange),
ATTRIBUTE_ENTRY(CameraShip, MapLinearPosition, mapLinearPosition),
ATTRIBUTE_ENTRY(CameraShip, MapAngularPosition, mapAngularPosition)
};
CameraShip::AttributeIndexSet
CameraShip::AttributeIndex(
ELEMENTS(CameraShip::AttributePointers),
CameraShip::AttributePointers,
Mover::AttributeIndex
);
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
CameraShip::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(CameraShip, Direction)
};
CameraShip::MessageHandlerSet
CameraShip::MessageHandlers(
ELEMENTS(CameraShip::MessageHandlerEntries),
CameraShip::MessageHandlerEntries,
Entity::MessageHandlers
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DirectionMessageHandler(DirectionMessage *message)
{
Check(this);
Check(message);
Check(application);
HostManager *host = application->GetHostManager();
Check(host);
SetGoalEntity(host->GetEntityPointer(message->goalEntity));
Check(goalEntity);
mapLinearPosition = &goalEntity->localOrigin.linearPosition;
focusOffset = message->focusOffset;
SetSimulationState(DefaultState);
timeOnCamera = message->timeOnCamera;
lastSwitch = Now();
lastSwitch -= timeOnCamera;
Check_Fpu();
}
//#############################################################################
// ControlsMapper Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::SetMappingSubsystem(CameraControlsMapper *mapper)
{
Check(this);
Check(mapper);
if(subsystemArray[ControlsMapperSubsystem])
{
Unregister_Object(subsystemArray[ControlsMapperSubsystem]);
delete subsystemArray[ControlsMapperSubsystem];
}
subsystemArray[ControlsMapperSubsystem] = mapper;
Check_Fpu();
}
//#############################################################################
// Simulation Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DriveCamera(Scalar time_slice)
{
Check(this);
CameraControlsMapper* controls =
Cast_Object(
CameraControlsMapper*,
GetSubsystem(CameraShip::ControlsMapperSubsystem)
);
Check(controls);
//
//-----------------------------------------------
// If we are in positioning mode, move the camera
//-----------------------------------------------
//
if (controls->driveCamera > 0)
{
ApplyControlledPanAndTilt(controls, time_slice);
ApplyControlledCameraMotion(controls, time_slice);
ApplyControlledCameraHeight(controls);
currentCamera->SetLocalOrigin(localOrigin);
}
//
//------------------------------------------------------------------------
// Operate in camera mode, obeying the limits of the camera as established
// by the clamps
//------------------------------------------------------------------------
//
else
{
//
//-------------------------
// Stop any existing motion
//-------------------------
//
worldLinearVelocity = Vector3D::Identity;
//
//-----------------------------------------------------------------------
// Read the controls for panning the camera, and if the clamp override is
// on, tell the camera to allow this orientation
//-----------------------------------------------------------------------
//
ApplyControlledPanAndTilt(controls, time_slice);
localToWorld = localOrigin;
//
//---------------------------------------------------------------------
// Establish an aim point along negative Z and figure out where that is
// in world space, then point the camera there. The camera clamps will
// automatically do their thing
//---------------------------------------------------------------------
//
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
if (controls->slideOrClamp > 0)
{
currentCamera->AllowLookingAt(world_aim);
}
AimCameraAtPoint(world_aim);
}
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledPanAndTilt(
CameraControlsMapper *controls,
Scalar time_slice
)
{
Check(this);
Check(controls);
//
//-----------------------------------------
// Point the Camera in the direction of the
// Joystick Position Calc Pitch and Yaw only
//-----------------------------------------
//
Scalar rotation_amount;
if(controls->stickPosition.x < -0.02f)
{
rotation_amount = controls->stickPosition.x + 0.02f;
rotation_amount *= rotation_amount;
rotation_amount *= -1.0f;
}
else if (controls->stickPosition.x > 0.02f)
{
rotation_amount = controls->stickPosition.x - 0.02f;
rotation_amount *= rotation_amount;
}
else
{
rotation_amount = 0.0f;
}
YawPitchRoll ypr;
ypr = localOrigin.angularPosition;
ypr.yaw += rotation_amount * PI * time_slice;
ypr.pitch += controls->stickPosition.y * PI * 0.2f * time_slice;
localOrigin.angularPosition = ypr;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledCameraHeight(CameraControlsMapper *controls)
{
Check(this);
Check(controls);
//
//----------------------------------------------------
// Raise and lower the cameraShip according to the pedals
//----------------------------------------------------
//
localOrigin.linearPosition.y += controls->pedalsPosition;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::ApplyControlledCameraMotion(
CameraControlsMapper *controls,
Scalar time_slice
)
{
Check(this);
Check(controls);
localAcceleration.linearMotion.z =
-25.0f * controls->throttlePosition * time_slice;
if (controls->reverseThrust > 0)
{
localAcceleration.linearMotion.z = -localAcceleration.linearMotion.z;
}
//
//~~~~~~~~~~~~~~~~~~~
// Apply Linear Drag
//~~~~~~~~~~~~~~~~~~~
//
Vector3D drag_force;
drag_force.Multiply(
localVelocity.linearMotion,
positiveLinearDragCoefficients
);
Vector3D new_accel;
new_accel.Subtract(
localAcceleration.linearMotion,
drag_force
);
localAcceleration.linearMotion = new_accel;
//
//~~~~~~~~~~~~~~~~~~~~~~~~
// ApplyWorldAccelerations
//~~~~~~~~~~~~~~~~~~~~~~~~
localVelocity.linearMotion += localAcceleration.linearMotion;
worldLinearVelocity.Multiply(
localVelocity.linearMotion,
localToWorld
);
localOrigin.linearPosition += worldLinearVelocity;
Check_Fpu();
}
//#############################################################################
// Follow GoalEntity Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::FollowGoal(Scalar time_slice)
{
Check(this);
//
//-----------------------------------------------
// If no goalEntity assigned ask for one and wait
//-----------------------------------------------
//
if (!goalEntity)
{
return;
}
Check(goalEntity);
Point3D target;
target.Multiply(focusOffset, goalEntity->localToWorld);
//
//------------------------------------------------------------------------
// If time has not yet expired on this camera, keep with it if can see the
// goal entity
//------------------------------------------------------------------------
//
Check(currentCamera);
if (
lastPerformance - lastSwitch > timeOnCamera
|| !currentCamera->CanCameraSee(target)
)
{
CameraInstance *old_camera = currentCamera;
GoToClosestCamera(target);
if (!currentCamera)
{
currentCamera = old_camera;
}
Check(currentCamera);
//
//------------------------------------------------------------------------
// If we need to switch cameras, have the new camera point directly at the
// target
//------------------------------------------------------------------------
//
if (currentCamera != old_camera)
{
AimCameraAtPoint(target);
lastSwitch = lastPerformance;
}
else
{
goto Rotate_Camera;
}
}
//
//---------------------------------------------------
// Otherwise, rotate the camera as needed and allowed
//---------------------------------------------------
//
else
{
Rotate_Camera:
RotateCameraToPoint(time_slice, target);
}
//
//------------------------
// Set the tranform matrix
//------------------------
//
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::GoToClosestCamera(const Point3D &point_3D)
{
Check(this);
currentCamera = cameraManager.FindClosestCamera(point_3D);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::AimCameraAtPoint(const Point3D &point_3D)
{
Check(this);
Check(currentCamera);
currentCamera->LookAt(&localOrigin, point_3D);
localVelocity.angularMotion = Vector3D::Identity;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::RotateCameraToPoint(
Scalar time_slice,
const Point3D &point_3D
)
{
Check(this);
Check(currentCamera);
Check(&point_3D);
//
//---------------------------------------------------------
// Calculate the rotation needed to point to the goalEntity
//---------------------------------------------------------
//
Origin target;
currentCamera->LookAt(&target, point_3D);
YawPitchRoll new_yaw_pitch_roll;
new_yaw_pitch_roll = target.angularPosition;
Vector3D new_pos(new_yaw_pitch_roll.pitch, new_yaw_pitch_roll.yaw, 0.0f);
YawPitchRoll old_pos_euler;
old_pos_euler = localOrigin.angularPosition;
Vector3D old_pos(old_pos_euler.pitch, old_pos_euler.yaw, 0.0f);
old_pos.x = Radian::Normalize(old_pos.x);
old_pos.y = Radian::Normalize(old_pos.y);
//
// new - old position
//
if (new_pos.x-old_pos.x > PI) {
new_pos.x -= TWO_PI;
}
else if (new_pos.x-old_pos.x < -PI) {
new_pos.x += TWO_PI;
}
if (new_pos.y-old_pos.y > PI) {
new_pos.y -= TWO_PI;
}
else if (new_pos.y-old_pos.y < -PI) {
new_pos.y += TWO_PI;
}
Vector3D delta_rot;
delta_rot.Subtract(
new_pos,
old_pos
);
//
//-------------------
// Apply Angular Drag
//-------------------
//
Vector3D
drag;
drag.Multiply(
localVelocity.angularMotion,
angularDragCoefficients
);
//
//~~~~~~~~~~~~~~~~~~~~~
// Apply SpringConstant
//~~~~~~~~~~~~~~~~~~~~~
//
Vector3D
delta_rot_spring;
delta_rot_spring.Multiply(
delta_rot,
elasticityCoefficient
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Calculate the new angular acceleration
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
localAcceleration.angularMotion.Subtract(
delta_rot_spring,
drag
);
Scalar halft_squared = 0.5 *(time_slice * time_slice);
Vector3D
accel_comp;
accel_comp.Multiply(
localAcceleration.angularMotion,
halft_squared
);
//
// velocity * delta time
//
Vector3D
scaled_velocity;
scaled_velocity.Multiply(
localVelocity.angularMotion,
time_slice
);
Vector3D
tmp_position;
tmp_position.Add(
scaled_velocity,
accel_comp
);
Vector3D
clamped_accel;
clamped_accel.Add(
old_pos,
tmp_position
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Apply Acceleration to angular Position
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
YawPitchRoll
new_yawpitchroll(clamped_accel.y, clamped_accel.x, clamped_accel.z);
LinearMatrix
rot_matrix(LinearMatrix::Identity);
rot_matrix = new_yawpitchroll;
localOrigin.angularPosition = rot_matrix;
//
// Calc new Velocity
//
Vector3D
scaled_accel;
scaled_accel.Multiply(
localAcceleration.angularMotion,
time_slice
);
Vector3D
ang_vel;
ang_vel.Add(
localVelocity.angularMotion,
scaled_accel
);
localVelocity.angularMotion = ang_vel;
Check_Fpu();
}
//#############################################################################
// CameraInstanceManager Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::CreateCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.CreateCameraInstance(localOrigin);
DEBUG_STREAM << currentCamera->GetCameraName() << endl;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DeleteCameraInstance()
{
Check(this);
//
//---------------------------------------------
// If this is the last camera, don't delete it!
//---------------------------------------------
//
Check(&cameraManager);
CameraInstance *next_camera = cameraManager.IncrementIterator();
if (next_camera == currentCamera)
{
return;
}
currentCamera = cameraManager.DeleteCameraInstance();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << endl;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::IncrementCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.IncrementIterator();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << endl;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraShip::DecrementCameraInstance()
{
Check(this);
Check(&cameraManager);
currentCamera = cameraManager.DecrementIterator();
Check(currentCamera);
DEBUG_STREAM << currentCamera->GetCameraName() << endl;
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
Check_Fpu();
}
//#############################################################################
// Motion Support Functions
//
//#############################################################################
// Construction and Destruction Support
//
CameraShip::CameraShip(
CameraShip::MakeMessage *creation_message,
CameraShip::SharedData &virtual_data
):
Mover(creation_message, virtual_data)
{
SetValidFlag();
if (GetInstance() == ReplicantInstance)
{
return;
}
//
//----------------------------
// Initialize local variables
//----------------------------
//
goalEntity = NULL;
localOrigin = Origin::Identity;
focusOffset = Vector3D::Identity;
//
//------------------------------
// Initialize attributes
//------------------------------
//
mapRange = 1000.0; // number of meters across display
mapLinearPosition = NULL; // force nav display to use object's lin. pos
mapAngularPosition = NULL; // force nav display to not turn or tilt
//
//------------------------------
// Initialize the subsystemArray
//------------------------------
//
subsystemCount = BasicSubsystemCount;
Verify(!subsystemArray);
subsystemArray = new (Subsystem (*[subsystemCount]));
Register_Pointer(subsystemArray);
subsystemArray[ControlsMapperSubsystem] = NULL;
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialize the camera's viewpoint to the first camera
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
currentCamera = cameraManager.GetCurrent();
if (!currentCamera)
{
CreateCameraInstance();
}
Check(currentCamera);
localOrigin = currentCamera->GetLocalOrigin();
localToWorld = localOrigin;
Point3D local_aim(0.0f, 0.0f, -1.0f);
Point3D world_aim;
world_aim.Multiply(local_aim, localToWorld);
AimCameraAtPoint(world_aim);
localToWorld = localOrigin;
lastSwitch = Now();
timeOnCamera = 0.0f;
SetPerformance(&CameraShip::FollowGoal);
SetSimulationState(DefaultState);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraShip*
CameraShip::Make(MakeMessage *creation_message)
{
return new CameraShip(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraShip::~CameraShip()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
CameraShip::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
+284
View File
@@ -0,0 +1,284 @@
//===========================================================================//
// File: camship.hh //
// Project: Munga //
// Contents: Camera Interface //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/08/95 JM Initial coding. //
// Classes: CameraShip //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CAMSHIP_HPP)
# define CAMSHIP_HPP
# if !defined (MOVER_HPP)
# include <mover.hpp>
# endif
# if !defined (CAMMGR_HPP)
# include <cammgr.hpp>
# endif
class CameraControlsMapper;
//##########################################################################
//############### CameraShip::DirectionMessage #################
//##########################################################################
class CameraShip__DirectionMessage :
public Mover::Message
{
public:
EntityID
goalEntity;
Scalar
timeOnCamera;
Point3D
focusOffset;
CameraShip__DirectionMessage(
Receiver::MessageID message_ID,
size_t length,
const EntityID& goal_entity,
Scalar time_on_camera,
const Point3D& focus
):
Entity::Message(message_ID, length),
goalEntity(goal_entity),
timeOnCamera(time_on_camera),
focusOffset(focus)
{}
};
//##########################################################################
//############################# CameraShip ################################
//##########################################################################
class CameraShip :
public Mover
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging support
//
protected:
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
public:
enum{
DirectionMessageID = Entity::NextMessageID,
NextMessageID
};
typedef CameraShip__DirectionMessage DirectionMessage;
void
DirectionMessageHandler(DirectionMessage *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
enum
{
MapRangeAttributeID = Mover::NextAttributeID,
MapLinearPositionAttributeID,
MapAngularPositionAttributeID,
NextAttributeID
};
private:
static const IndexEntry AttributePointers[];
protected:
static AttributeIndexSet AttributeIndex;
public:
Scalar
mapRange;
Point3D
*mapLinearPosition; // pointer to linear position of object or NULL
Quaternion
*mapAngularPosition; // pointer to angular position of object or NULL
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model support
//
public:
enum {
ControlsMapperSubsystem,
BasicSubsystemCount
};
void
SetMappingSubsystem(CameraControlsMapper *mapper);
//
// Various States of the CameraShip
//
enum {
ConfigureCamerasState = Mover::StateCount,
StateCount
};
typedef void
(CameraShip::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
FollowGoal(Scalar time_slice);
void
DriveCamera(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Flag Support
//
public:
enum{
DefaultFlags = Mover::DefaultFlags |
NoCollisionVolumeFlag |
NoCollisionTestFlag |
InitialStasisFlag
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
static CameraShip*
Make(MakeMessage *creation_message);
CameraShip(
MakeMessage *creation_message,
SharedData &virtual_data = DefaultData
);
~CameraShip();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public Data and Member Access Functions
//
public:
void
SetGoalEntity(Entity *goal_entity)
{Check(this); Check(goal_entity); goalEntity = goal_entity;}
Entity*
GetGoalEntity()
{Check(this); return goalEntity; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Member Data
//
public:
void
GoToClosestCamera(const Point3D &point_3D);
CameraInstance*
GetCurrentCamera()
{Check(this); return currentCamera;}
Time
lastSwitch;
Scalar
timeOnCamera;
protected:
CameraInstanceManager
cameraManager;
Entity
*goalEntity;
CameraInstance
*currentCamera;
Point3D
focusOffset;
void
MoveCameraShip(CameraInstance *camera_instance);
void
AimCameraAtPoint(const Point3D &point_3D);
void
RotateCameraToPoint(
Scalar time_slice,
const Point3D &point_3D
);
//
// Camera Motion Support
//
public:
void
ResetMotionVariables()
{
Check(this);
localVelocity = Motion::Identity;
localAcceleration = Motion::Identity;
worldLinearVelocity = Vector3D::Identity;
worldLinearAcceleration = Vector3D::Identity;
}
protected:
void
ApplyControlledPanAndTilt(
CameraControlsMapper *controls,
Scalar time_slice
);
void
ApplyControlledCameraHeight(CameraControlsMapper *controls);
void
ApplyControlledCameraMotion(
CameraControlsMapper *controls,
Scalar time_slice
);
//
// Camera Manager Support
//
public:
void
CreateCameraInstance();
void
DeleteCameraInstance();
void
IncrementCameraInstance();
void
DecrementCameraInstance();
public:
void
OutputCameraList()
{cameraManager.WriteNotationFile();}
};
#endif
+474
View File
@@ -0,0 +1,474 @@
//===========================================================================//
// File: chain.cc //
// Project: MUNGA Brick: Connection Engine //
// Contents: Implementation details of chains and their iterators //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 09/29/94 ECH Initial coding. //
// 10/20/94 JMA Fixed style stuff. Merged with CHNITR.HPP, and added //
// operator functions to iterator //
// 10/23/94 ECH Added greater deletion safety //
// 10/28/94 JMA Made compatible with SGI CC //
// 11/03/94 ECH Made compatible with BC4.0 //
// 12/12/94 ECH Changed release handling //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CHAIN_HPP)
#include <chain.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MemoryBlock
ChainLink::AllocatedMemory(
sizeof(ChainLink),
CHAINLINK_MEMORYBLOCK_ALLOCATION,
CHAINLINK_MEMORYBLOCK_ALLOCATION,
"ChainLink"
);
//
//#############################################################################
// ChainLink
//#############################################################################
//
ChainLink::ChainLink(
Chain *chain,
Plug *plug,
ChainLink *next_link,
ChainLink *prev_link
):
Link(chain, plug)
{
//
//-------------------------
// Link into existing chain
//-------------------------
//
if ((nextChainLink = next_link) != NULL)
{
Check(nextChainLink);
nextChainLink->prevChainLink = this;
}
if ((prevChainLink = prev_link) != NULL)
{
Check(prevChainLink);
prevChainLink->nextChainLink = this;
}
}
//
//#############################################################################
// ~ChainLink
//#############################################################################
//
ChainLink::~ChainLink()
{
Chain *chain = Cast_Object(Chain*, socket);
//
//--------------------------------------
// Remove this link from the linked list
//--------------------------------------
//
if (prevChainLink != NULL)
{
Check(prevChainLink);
prevChainLink->nextChainLink = nextChainLink;
}
else
{
Check(chain);
chain->head = nextChainLink;
}
if (nextChainLink != NULL)
{
Check(nextChainLink);
nextChainLink->prevChainLink = prevChainLink;
}
else
{
Check(chain);
chain->tail = prevChainLink;
}
prevChainLink = nextChainLink = NULL;
//
//------------------------------------------
// Remove this link from any plug references
//------------------------------------------
//
ReleaseFromPlug();
//
//-------------------------------------------------------------
// Tell the node to release this link. Note that this link
// is not referenced by the plug or the chain at this point in
// time.
//-------------------------------------------------------------
//
if (chain->GetReleaseNode() != NULL)
{
Check(chain->GetReleaseNode());
chain->GetReleaseNode()->ReleaseLinkHandler(chain, plug);
}
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
ChainLink::TestInstance() const
{
Link::TestInstance();
if (prevChainLink != NULL)
{
Check_Signature(prevChainLink);
}
if (nextChainLink != NULL)
{
Check_Signature(nextChainLink);
}
return( True );
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
// Chain
//#############################################################################
//
Chain::Chain(Node *node):
Socket(node)
{
head = NULL;
tail = NULL;
}
//
//#############################################################################
// ~Chain
//#############################################################################
//
Chain::~Chain()
{
SetReleaseNode(NULL);
while (head != NULL)
{
Unregister_Object(head);
delete head;
}
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
Chain::TestInstance() const
{
Socket::TestInstance();
if (head != NULL)
{
Check(head);
}
if (tail != NULL)
{
Check(tail);
}
return True;
}
//
//#############################################################################
// AddImplementation
//#############################################################################
//
void
Chain::AddImplementation(Plug *plug)
{
Check(this);
tail = new ChainLink(this, plug, NULL, tail);
Register_Object(tail);
if (head == NULL)
{
head = tail;
}
}
//
//#############################################################################
// InsertChainLink
//#############################################################################
//
ChainLink*
Chain::InsertChainLink(
Plug *plug,
ChainLink *current_link
)
{
Check(this);
Check(plug);
Check(current_link);
ChainLink *new_link =
new ChainLink(
this,
plug,
current_link,
current_link->prevChainLink
);
Register_Object(new_link);
Check(head);
if (head == current_link)
{
head = new_link;
}
return new_link;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//#############################################################################
// ChainIterator
//#############################################################################
//
ChainIterator::ChainIterator(Chain *chain):
SocketIterator(chain)
{
Check(chain);
currentLink = chain->head;
}
ChainIterator::ChainIterator(const ChainIterator &iterator):
SocketIterator(Cast_Object(Chain*, iterator.socket))
{
Check(&iterator);
currentLink = iterator.currentLink;
}
ChainIterator::~ChainIterator()
{
}
//
//###########################################################################
// TestInstance
//###########################################################################
//
Logical
ChainIterator::TestInstance() const
{
SocketIterator::TestInstance();
if (currentLink != NULL)
{
Check( currentLink );
}
return(True);
}
//
//###########################################################################
// First
//###########################################################################
//
void
ChainIterator::First()
{
currentLink = Cast_Object(Chain*, socket)->head;
}
//
//###########################################################################
// Last
//###########################################################################
//
void
ChainIterator::Last()
{
currentLink = Cast_Object(Chain*, socket)->tail;
}
//
//###########################################################################
// Next
//###########################################################################
//
void
ChainIterator::Next()
{
Check(currentLink);
currentLink = currentLink->nextChainLink;
}
//
//###########################################################################
// Previous
//###########################################################################
//
void
ChainIterator::Previous()
{
Check( currentLink );
currentLink = currentLink->prevChainLink;
}
//
//###########################################################################
// ReadAndNextImplementation
//###########################################################################
//
void*
ChainIterator::ReadAndNextImplementation()
{
if (currentLink != NULL)
{
Plug *plug;
Check(currentLink);
plug = currentLink->plug;
currentLink = currentLink->nextChainLink;
return plug;
}
return NULL;
}
//
//###########################################################################
// ReadAndPreviousImplementation
//###########################################################################
//
void*
ChainIterator::ReadAndPreviousImplementation()
{
if (currentLink != NULL)
{
Plug *plug;
Check(currentLink);
plug = currentLink->plug;
currentLink = currentLink->prevChainLink;
return plug;
}
return NULL;
}
//
//###########################################################################
// GetCurrentImplementation
//###########################################################################
//
void*
ChainIterator::GetCurrentImplementation()
{
if (currentLink != NULL)
{
Check(currentLink);
return currentLink->plug;
}
return NULL;
}
//
//###########################################################################
// GetSize
//###########################################################################
//
CollectionSize
ChainIterator::GetSize()
{
ChainLink *link;
CollectionSize count;
count = 0;
for (
link = Cast_Object(Chain*, socket)->head;
link != NULL;
link = link->nextChainLink
) {
Check(link);
count++;
}
return count;
}
//
//###########################################################################
// GetNthImplementation
//###########################################################################
//
void*
ChainIterator::GetNthImplementation(CollectionSize index)
{
ChainLink *link;
CollectionSize count;
count = 0;
for (
link = Cast_Object(Chain*, socket)->head;
link != NULL;
link = link->nextChainLink
) {
Check(link);
if (count == index) {
currentLink = link;
return currentLink->plug;
}
count++;
}
return NULL;
}
//
//###########################################################################
// Remove
//###########################################################################
//
void
ChainIterator::Remove()
{
ChainLink *oldLink = currentLink;
Check(currentLink);
currentLink = currentLink->nextChainLink;
Unregister_Object(oldLink);
delete oldLink ;
}
//
//###########################################################################
// InsertImplementation
//###########################################################################
//
void
ChainIterator::InsertImplementation(Plug *plug)
{
currentLink =
Cast_Object(Chain*, socket)->InsertChainLink(plug, currentLink);
Check(currentLink);
}
#ifdef TEST_CLASS
# include "chain.tcp"
#endif
+367
View File
@@ -0,0 +1,367 @@
//===========================================================================//
// File: chain.hh //
// Project: MUNGA Brick: Connection Engine //
// Contents: Interface specification of Chains and their iterators //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 09/29/94 ECH Initial coding. //
// 10/20/94 JMA Fixed style stuff. Merged with CHNITR.HPP, and added //
// operator functions to iterator //
// 10/23/94 ECH Added greater deletion safety //
// 10/28/94 JMA Made compatible with SGI CC //
// 11/03/94 ECH Made compatible with BC4.0 //
// 12/12/94 ECH Changed release handling //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#if !defined(CHAIN_HPP)
# define CHAIN_HPP
# if !defined(NODE_HPP)
# include <node.hpp>
# endif
# if !defined(MEMBLOCK_HPP)
# include <memblock.hpp>
# endif
class Chain;
class ChainIterator;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CHAINLINK_MEMORYBLOCK_ALLOCATION (100)
class ChainLink : public Link
{
friend class Chain;
friend class ChainIterator;
public:
~ChainLink();
Logical
TestInstance() const;
private:
ChainLink(
Chain *chain,
Plug *plug,
ChainLink *nextChainLink,
ChainLink *prevChainLink
);
ChainLink
*nextChainLink,
*prevChainLink;
private:
static MemoryBlock
AllocatedMemory;
void*
operator new(size_t)
{return AllocatedMemory.New();}
void
operator delete(void *where)
{AllocatedMemory.Delete(where);}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Chain:
public Socket
{
friend class ChainLink;
friend class ChainIterator;
public:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Public interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
//
//--------------------------------------------------------------------
// Constructor, Destructor and testing
//--------------------------------------------------------------------
//
Chain(Node *node);
~Chain();
Logical
TestInstance() const;
static Logical
TestClass();
static Logical
ProfileClass();
protected:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Protected interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
void
AddImplementation(Plug *plug);
private:
//
//--------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------
//
ChainLink*
InsertChainLink(
Plug *plug,
ChainLink *current_link
);
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
ChainLink
*head,
*tail;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> class ChainOf:
public Chain
{
public:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Public interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
ChainOf(Node *node);
~ChainOf();
//
//--------------------------------------------------------------------
// Socket methods (see Socket for full listing)
//--------------------------------------------------------------------
//
void
Add(T plug)
{AddImplementation(Cast_Object(Plug*,plug));}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
ChainOf<T>::ChainOf(Node *node):
Chain(node)
{
}
template <class T>
ChainOf<T>::~ChainOf()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ChainIterator:
public SocketIterator
{
public:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Public interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
//
//--------------------------------------------------------------------
// Constructors, Destructor and testing
//--------------------------------------------------------------------
//
ChainIterator(Chain *chain);
ChainIterator(const ChainIterator &iterator);
~ChainIterator();
Logical
TestInstance() const;
//
//--------------------------------------------------------------------
// Iterator methods (see Iterator for full listing)
//--------------------------------------------------------------------
//
void
First();
void
Last();
void
Next();
void
Previous();
CollectionSize
GetSize();
void
Remove();
protected:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Protected interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
void*
ReadAndNextImplementation();
void*
ReadAndPreviousImplementation();
void*
GetCurrentImplementation();
void*
GetNthImplementation(CollectionSize index);
void
InsertImplementation(Plug*);
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Protected data
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
ChainLink
*currentLink;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T> class ChainIteratorOf:
public ChainIterator
{
public:
//
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Public interface
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//
//
//--------------------------------------------------------------------
// Constructors and Destructor
//--------------------------------------------------------------------
//
ChainIteratorOf(ChainOf<T> *chain);
ChainIteratorOf(ChainOf<T> &chain);
ChainIteratorOf(const ChainIteratorOf<T> &iterator);
~ChainIteratorOf();
//
//--------------------------------------------------------------------
// Iterator methods (see Iterator for full listing)
//--------------------------------------------------------------------
//
T
ReadAndNext()
{return (T)ReadAndNextImplementation();}
T
ReadAndPrevious()
{return (T)ReadAndPreviousImplementation();}
T
GetCurrent()
{return (T)GetCurrentImplementation();}
T
GetNth(CollectionSize index)
{return (T)GetNthImplementation(index);}
void
Insert(T plug)
{InsertImplementation(Cast_Object(Plug*,plug));}
ChainIteratorOf<T>&
Begin()
{return (ChainIteratorOf<T>&)BeginImplementation();}
ChainIteratorOf<T>&
End()
{return (ChainIteratorOf<T>&)EndImplementation();}
ChainIteratorOf<T>&
Forward()
{return (ChainIteratorOf<T>&)ForwardImplementation();}
ChainIteratorOf<T>&
Backward()
{return (ChainIteratorOf<T>&)BackwardImplementation();}
//
//---------------------------------------------------
// Operators useful when it is know that the iterator
// is a ChainOf<> Iterator
//---------------------------------------------------
//
#if 0
Logical
operator!()
{return currentLink == NULL;}
operator T*()
{return GetCurrent();}
T*
operator->()
{return GetCurrent();}
T&
operator*()
{return *GetCurrent();}
ChainIteratorOf<T>&
operator++()
{Next(); return *this;}
ChainIteratorOf<T>&
operator--()
{Previous(); return *this;}
T*
operator++(int)
{return ReadAndNext();}
T*
operator--(int)
{return ReadAndPrevious();}
#endif
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template <class T>
ChainIteratorOf<T>::ChainIteratorOf(ChainOf<T> *chain):
ChainIterator(chain)
{
}
template <class T>
ChainIteratorOf<T>::ChainIteratorOf(ChainOf<T> &chain):
ChainIterator(&chain)
{
}
template <class T>
ChainIteratorOf<T>::ChainIteratorOf(const ChainIteratorOf<T> &iterator):
ChainIterator(iterator)
{
}
template <class T>
ChainIteratorOf<T>::~ChainIteratorOf()
{
}
#endif
+90
View File
@@ -0,0 +1,90 @@
//===========================================================================//
// File: cmpnnt.cc //
// Project: MUNGA Brick: Entity //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/14/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CMPNNT_HPP)
#include <cmpnnt.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Shared Data Support
//
Derivation
Component::ClassDerivations(
Receiver::ClassDerivations,
"Component"
);
Component::SharedData
Component::DefaultData(
Component::ClassDerivations,
Component::MessageHandlers
);
//
//#############################################################################
//#############################################################################
//
Component::Component(
ClassID class_id,
SharedData &shared_data
):
Receiver(class_id, shared_data)
{
}
//
//#############################################################################
//#############################################################################
//
Component::Component(
PlugStream *stream,
SharedData &shared_data
):
Receiver(stream, shared_data)
{
}
//
//#############################################################################
//#############################################################################
//
Component::~Component()
{
}
//
//#############################################################################
//#############################################################################
//
void
Component::Execute()
{
Fail("Component::Execute - Should never reach here");
}
//
//#############################################################################
//#############################################################################
//
Logical
Component::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
+73
View File
@@ -0,0 +1,73 @@
//===========================================================================//
// File: cmpnnt.hh //
// Project: MUNGA Brick: Watcher //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 12/14/94 ECH Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CMPNNT_HPP)
# define CMPNNT_HPP
# if !defined(RECEIVER_HPP)
# include <receiver.hpp>
# endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Component:
public Receiver
{
public:
//
//-----------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------
//
~Component();
//
//-----------------------------------------------------------------------
// Execute
//-----------------------------------------------------------------------
//
virtual void
Execute();
//
//-----------------------------------------------------------------------
// Shared Data Support
//-----------------------------------------------------------------------
//
static Derivation
ClassDerivations;
static SharedData
DefaultData;
Logical
TestInstance() const;
protected:
//
//-----------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------
//
Component(
ClassID class_id = TrivialComponentClassID,
SharedData &shared_data = DefaultData
);
Component(
PlugStream *stream,
SharedData &shared_data = DefaultData
);
};
#endif
+392
View File
@@ -0,0 +1,392 @@
//===========================================================================//
// File: collasst.cc //
// Project: MUNGA Brick: Collision //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 02/17/95 ECH Initial coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(COLLASST_HPP)
# include <collasst.hpp>
#endif
#if !defined(MOVER_HPP)
# include <mover.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(INTEREST_HPP)
#include <interest.hpp>
#endif
//
//#############################################################################
// Make
//#############################################################################
//
CollisionAssistant*
CollisionAssistant::Make(Mover *mover)
{
Check(mover);
//
// Create the collision assistant
//
CollisionAssistant *collision_assistant;
collision_assistant = new CollisionAssistant(mover->GetInterestZoneID());
Check(collision_assistant);
return collision_assistant;
}
//
//#############################################################################
// CollisionAssistant
//#############################################################################
//
CollisionAssistant::CollisionAssistant(InterestZoneID interest_zone_ID):
collisionOriginSocket(NULL)
{
Verify(interest_zone_ID != NullInterestZoneID);
currentInterestZoneID = interest_zone_ID;
LinkToInterestZone(interest_zone_ID);
}
//
//#############################################################################
// ~CollisionAssistant
//#############################################################################
//
CollisionAssistant::~CollisionAssistant()
{
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
CollisionAssistant::TestInstance() const
{
Node::TestInstance();
Verify(currentInterestZoneID != NullInterestZoneID);
Check(&collisionOriginSocket);
return True;
}
//
//#############################################################################
// Update
//#############################################################################
//
void
CollisionAssistant::Update(InterestZoneID interest_zone_ID)
{
Check(this);
Verify(interest_zone_ID != NullInterestZoneID);
if (interest_zone_ID == currentInterestZoneID)
return;
currentInterestZoneID = interest_zone_ID;
//
// Remove current collision origin and link to new one
//
if (collisionOriginSocket.GetCurrent() != NULL)
{
collisionOriginSocket.Remove();
}
LinkToInterestZone(interest_zone_ID);
}
//
//#############################################################################
// LinkToInterestZone
//#############################################################################
//
void
CollisionAssistant::LinkToInterestZone(InterestZoneID interest_zone_ID)
{
Check(this);
Verify(interest_zone_ID != NullInterestZoneID);
//
//--------------------------------------------------------------------------
// Does the interest zone have a collision origin?
//--------------------------------------------------------------------------
//
InterestZone *interest_zone;
CollisionOrigin *collision_origin;
Check(application);
Check(application->GetInterestManager());
interest_zone =
application->GetInterestManager()->GetInterestZone(interest_zone_ID);
Check(interest_zone);
collision_origin = interest_zone->GetCollisionOrigin();
if (collision_origin == NULL)
{
//
// It does not, so create one
//
collision_origin = new CollisionOrigin(interest_zone_ID);
Register_Object(collision_origin);
interest_zone->AdoptCollisionOrigin(collision_origin);
application->GetInterestManager()->AdoptInterestOrigin(collision_origin);
}
Check(collision_origin);
//
// link to the collision origin
//
collisionOriginSocket.Add(collision_origin);
}
//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~
CollisionAssistant__MovingEntityIterator::
CollisionAssistant__MovingEntityIterator(
CollisionAssistant *collision_assistant
):
CollisionOrigin__MovingEntityIterator(
collision_assistant->collisionOriginSocket.GetCurrent()
)
{
}
CollisionAssistant__MovingEntityIterator::
~CollisionAssistant__MovingEntityIterator()
{
}
#if 0
//
//#############################################################################
// Make
//#############################################################################
//
CollisionAssistant*
CollisionAssistant::Make(Mover *mover)
{
Check(mover);
//
//-----------------------------------------------------------------------
// Create the collision assistant
//-----------------------------------------------------------------------
//
CollisionAssistant *collision_assistant;
Check(application);
collision_assistant = new CollisionAssistant(
application->GetApplicationLoopFrameRate()
);
Check(collision_assistant);
//
//-----------------------------------------------------------------------
// Prime the collision assistant
//-----------------------------------------------------------------------
//
collision_assistant->LinkToMover(mover);
collision_assistant->LoadMission(NULL); // JM - This should work...
return collision_assistant;
}
//
//#############################################################################
// CollisionAssistant
//#############################################################################
//
CollisionAssistant::CollisionAssistant(RendererRate render_rate):
Renderer(
render_rate,
MaxRendererComplexity,
DefaultRendererPriority,
CollisionInterestType,
DefaultInterestDepth,
CollisionAssistantClassID
),
movingEntitySocket(NULL)
{
}
//
//#############################################################################
// ~CollisionAssistant
//#############################################################################
//
CollisionAssistant::~CollisionAssistant()
{
Suspend();
UnlinkFromEntity();
Shutdown();
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
CollisionAssistant::TestInstance() const
{
Renderer::TestInstance();
Check(&movingEntitySocket);
return True;
}
//
//#############################################################################
// LinkToEntity
//#############################################################################
//
void
CollisionAssistant::LinkToMover(Mover *mover)
{
Check(this);
Check(mover);
//
// Call inherited method
//
Renderer::LinkToEntity(mover);
//
//-----------------------------------------------------------------
// Tell the entity that is collisionable here ...
//-----------------------------------------------------------------
//
}
//
//#############################################################################
// NotifyOfNewInterestingEntity
//#############################################################################
//
void
CollisionAssistant::NotifyOfNewInterestingEntity(
Entity *interesting_entity
)
{
Check(this);
Check(interesting_entity);
//
//-------------------------------------------------------------------------
// Make sure that we don't check against ourself our against something that
// doesn't move
//-------------------------------------------------------------------------
//
if (
interesting_entity != GetLinkedEntity()
&& interesting_entity->IsDynamic()
)
{
//
//-------------------------------------------------------------
// If it is a mover and tangible, or a door, add it to our list
//-------------------------------------------------------------
//
if (interesting_entity->IsDerivedFrom(Mover::ClassDerivations))
{
Mover *mover = Cast_Object(Mover*, interesting_entity);
if (mover->IsTangible())
{
goto Add_Entity;
}
}
else if (interesting_entity->IsDerivedFrom(DoorFrame::ClassDerivations))
{
Add_Entity:
movingEntitySocket.Add(interesting_entity);
}
}
}
//
//#############################################################################
// NotifyOfBecomingUninterestingEntity
//#############################################################################
//
void
CollisionAssistant::NotifyOfBecomingUninterestingEntity(
Entity *uninteresting_entity
)
{
//
// HACK - ECH The following may not be a legitimate assertion
//
#if DEBUG_LEVEL>0 && 0
{
SChainIteratorOf<Mover*> iterator(&movingEntitySocket);
Verify(iterator.IsPlugMember(uninteresting_entity) == True);
}
#endif
//
// Remove from socket
//
PlugIterator iterator(uninteresting_entity);
iterator.RemoveSocket(&movingEntitySocket);
}
//
//#############################################################################
// GetCollisionRoot
//#############################################################################
//
BoxedSolidTree*
CollisionAssistant::GetCollisionRoot()
{
Check(GetInterestOrigin());
Check(GetInterestOrigin()->GetInterestArena());
return GetInterestOrigin()->GetInterestArena()->GetCollisionRoot();
}
//
//#############################################################################
// ExecuteImplementation
//#############################################################################
//
void
CollisionAssistant::ExecuteImplementation(
RendererComplexity,
InterestOrigin::InterestingEntityIterator*
)
{
}
//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CollisionAssistant__MovingEntityIterator::
CollisionAssistant__MovingEntityIterator(
CollisionAssistant *collision_assistant
):
SChainIteratorOf<Entity*>(collision_assistant->movingEntitySocket)
{
}
CollisionAssistant__MovingEntityIterator::
~CollisionAssistant__MovingEntityIterator()
{
}
#endif
+206
View File
@@ -0,0 +1,206 @@
//===========================================================================//
// File: collasst.hh //
// Project: MUNGA Brick: Collision //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 02/17/95 ECH Initial coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(COLLASST_HPP)
# define COLLASST_HPP
# if !defined(NODE_HPP)
# include <node.hpp>
# endif
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
# if !defined(COLLORGN_HPP)
# include <collorgn.hpp>
# endif
//##########################################################################
//####################### CollisionAssistant #########################
//##########################################################################
class Mover;
class CollisionAssistant:
public Node
{
friend class CollisionAssistant__MovingEntityIterator;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public Types
//
public:
typedef CollisionAssistant__MovingEntityIterator
MovingEntityIterator;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
CollisionAssistant(InterestZoneID interest_zone_ID);
~CollisionAssistant();
Logical
TestInstance() const;
static CollisionAssistant*
Make(Mover *mover);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Update
//
public:
void
Update(InterestZoneID interest_zone_ID);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private
//
private:
void
LinkToInterestZone(InterestZoneID interest_zone_ID);
InterestZoneID
currentInterestZoneID;
SlotOf<CollisionOrigin*>
collisionOriginSocket;
};
//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~
class CollisionAssistant__MovingEntityIterator:
public CollisionOrigin__MovingEntityIterator
{
public:
CollisionAssistant__MovingEntityIterator(
CollisionAssistant *collision_assistant
);
~CollisionAssistant__MovingEntityIterator();
};
#if 0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CollisionAssistant ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CollisionAssistant:
public Renderer
{
friend class CollisionAssistant__MovingEntityIterator;
public:
//
//--------------------------------------------------------------------
// Public Types
//--------------------------------------------------------------------
//
typedef CollisionAssistant__MovingEntityIterator
MovingEntityIterator;
//
//--------------------------------------------------------------------
// Construction, Destruction, Testing
//--------------------------------------------------------------------
//
CollisionAssistant(RendererRate render_rate);
~CollisionAssistant();
Logical
TestInstance() const;
static CollisionAssistant*
Make(Mover *mover);
//
//--------------------------------------------------------------------
// LinkToEntity
//--------------------------------------------------------------------
//
void
LinkToMover(Mover *mover);
//
//--------------------------------------------------------------------
// NotifyOfNewInterestingEntity
//--------------------------------------------------------------------
//
void
NotifyOfNewInterestingEntity(Entity *interesting_entity);
//
//--------------------------------------------------------------------
// NotifyOfBecomingUninterestingEntity
//--------------------------------------------------------------------
//
void
NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity);
//
//--------------------------------------------------------------------
// GetCollisionRoot
//--------------------------------------------------------------------
//
BoxedSolidTree*
GetCollisionRoot();
protected:
//
//--------------------------------------------------------------------
// ExecuteImplementation
//--------------------------------------------------------------------
//
void
ExecuteImplementation(
RendererComplexity complexity_update,
InterestOrigin::InterestingEntityIterator *iterator
);
private:
//
//--------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------
//
void
LoadMissionImplementation(Mission*) {}
void
ShutdownImplementation() {}
void
SuspendImplementation() {}
void
ResumeImplementation() {}
//
//--------------------------------------------------------------------
// Private data
//--------------------------------------------------------------------
//
SChainOf<Entity*>
movingEntitySocket;
};
//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class CollisionAssistant__MovingEntityIterator:
public SChainIteratorOf<Entity*>
{
public:
CollisionAssistant__MovingEntityIterator(
CollisionAssistant *collision_assistant
);
~CollisionAssistant__MovingEntityIterator();
};
#endif
#endif
+167
View File
@@ -0,0 +1,167 @@
//===========================================================================//
// File: collorgn.cc //
// Project: MUNGA Brick: Collision //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 06/01/95 ECH Initial coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(COLLORGN_HPP)
# include <collorgn.hpp>
#endif
#if !defined(MOVER_HPP)
# include <mover.hpp>
#endif
#if !defined(DOORFRAM_HPP)
# include <doorfram.hpp>
#endif
//
//#############################################################################
// CollisionOrigin
//#############################################################################
//
CollisionOrigin::CollisionOrigin(InterestZoneID interest_zone_ID):
InterestOrigin(
interest_zone_ID,
CollisionInterestType,
DefaultInterestDepth
),
movingEntitySocket(NULL)
{
}
//
//#############################################################################
// ~CollisionOrigin
//#############################################################################
//
CollisionOrigin::~CollisionOrigin()
{
}
//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
CollisionOrigin::TestInstance() const
{
InterestOrigin::TestInstance();
Check(&movingEntitySocket);
return True;
}
//
//#############################################################################
// AddInterestingEntity
//#############################################################################
//
void
CollisionOrigin::AddInterestingEntity(Entity *interesting_entity)
{
Check(this);
Check(interesting_entity);
//
//--------------------------------------------------------------------------
// Make sure that we don't check against something that doesn't move
//--------------------------------------------------------------------------
//
if (interesting_entity->IsDynamic())
{
//
//-----------------------------------------------------------------------
// If it is a mover and tangible, or a door, add it to our list
//-----------------------------------------------------------------------
//
if (interesting_entity->IsDerivedFrom(Mover::ClassDerivations))
{
Mover *mover = Cast_Object(Mover*, interesting_entity);
if (mover->IsCollisionTestable())
{
movingEntitySocket.Add(interesting_entity);
}
}
else if (interesting_entity->IsDerivedFrom(DoorFrame::ClassDerivations))
{
movingEntitySocket.Add(interesting_entity);
}
}
}
//
//#############################################################################
// RemoveUninterestingEntity
//#############################################################################
//
void
CollisionOrigin::RemoveUninterestingEntity(Entity *uninteresting_entity)
{
Check(this);
Check(uninteresting_entity);
//
// HACK - ECH The following may not be a legitimate assertion
//
#if DEBUG_LEVEL>0 && 0
{
SChainIteratorOf<Mover*> iterator(&movingEntitySocket);
Verify(iterator.IsPlugMember(uninteresting_entity) == True);
}
#endif
//
// Remove from socket
//
PlugIterator iterator(uninteresting_entity);
Check(&iterator);
iterator.RemoveSocket(&movingEntitySocket);
}
//
//#############################################################################
// RemoveUninterestingEntities
//#############################################################################
//
void
CollisionOrigin::RemoveUninterestingEntities()
{
Check(this);
SChainIteratorOf<Entity*> iterator(&movingEntitySocket);
Check(&iterator);
while (iterator.GetCurrent() != NULL)
{
Check(iterator.GetCurrent());
iterator.Remove();
}
}
//~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~
CollisionOrigin__MovingEntityIterator::CollisionOrigin__MovingEntityIterator(
CollisionOrigin *collision_origin
):
SChainIteratorOf<Entity*>(collision_origin->movingEntitySocket)
{
}
CollisionOrigin__MovingEntityIterator::~CollisionOrigin__MovingEntityIterator()
{
}
+80
View File
@@ -0,0 +1,80 @@
//===========================================================================//
// File: collorgn.hh //
// Project: MUNGA Brick: Collision //
// Contents: //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 06/01/95 ECH Initial coding //
//---------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(COLLORGN_HPP)
# define COLLORGN_HPP
# if !defined(INTEREST_HPP)
# include <interest.hpp>
# endif
//##########################################################################
//###################### CollisionOrigin #############################
//##########################################################################
class CollisionOrigin:
public InterestOrigin
{
friend class CollisionOrigin__MovingEntityIterator;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interest Manager support
//
public:
typedef CollisionOrigin__MovingEntityIterator
MovingEntityIterator;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction, Destruction, Testing
//
public:
CollisionOrigin(InterestZoneID interest_zone_ID);
~CollisionOrigin();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Interest Manager support
//
protected:
void
AddInterestingEntity(Entity *interesting_entity);
void
RemoveUninterestingEntity(Entity *uninteresting_entity);
void
RemoveUninterestingEntities();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
SChainOf<Entity*>
movingEntitySocket;
};
//~~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~
class CollisionOrigin__MovingEntityIterator:
public SChainIteratorOf<Entity*>
{
public:
CollisionOrigin__MovingEntityIterator(
CollisionOrigin *collision_origin
);
~CollisionOrigin__MovingEntityIterator();
};
#endif
+97
View File
@@ -0,0 +1,97 @@
//===========================================================================//
// File: Color.cpp //
// Project: MUNGA Brick: Utility Library //
// Contents: Implementation details for color classes //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 11/12/95 GDU Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(COLOR_HPP)
# include <color.hpp>
#endif
#if !defined(CSTR_HPP)
#include <cstr.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###########################################################################
//###########################################################################
//
void
Convert_From_Ascii(
const char *str,
RGBColor *color
)
{
Check_Pointer(str);
Check_Signature(color);
CString parse_string(str);
Check_Pointer(parse_string.GetNthToken(0));
color->Red = atof(parse_string.GetNthToken(0));
Check_Pointer(parse_string.GetNthToken(1));
color->Green = atof(parse_string.GetNthToken(1));
Check_Pointer(parse_string.GetNthToken(2));
color->Blue = atof(parse_string.GetNthToken(2));
Check(color);
}
//
//###########################################################################
//###########################################################################
//
Logical
RGBColor::TestInstance() const
{
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###########################################################################
//###########################################################################
//
void
Convert_From_Ascii(
const char *str,
RGBAColor *color
)
{
Check_Pointer(str);
Check_Signature(color);
CString parse_string(str);
Check_Pointer(parse_string.GetNthToken(0));
color->Red = atof(parse_string.GetNthToken(0));
Check_Pointer(parse_string.GetNthToken(1));
color->Green = atof(parse_string.GetNthToken(1));
Check_Pointer(parse_string.GetNthToken(2));
color->Blue = atof(parse_string.GetNthToken(2));
Check_Pointer(parse_string.GetNthToken(3));
color->Alpha = atof(parse_string.GetNthToken(3));
Check(color);
}
+194
View File
@@ -0,0 +1,194 @@
//===========================================================================//
// File: color.hh //
// Title: Declaration of Color classes. //
// Project: Tool Architecture II //
// Author: Jerry Edsall & Ken Olsen (based on work by J.M. Albertson) //
// Purpose: Stores color information. //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/15/94 KEO Added RGBAColor class. //
// 11/12/95 GDU Added MUNGA signatures and stream IO, moved to MUNGA //
//---------------------------------------------------------------------------//
// Copyright (c) 1994 Virtual World Entertainment, Inc. //
// All rights reserved worldwide. //
// This unpublished source code is PROPRIETARY and CONFIDENTIAL. //
//===========================================================================//
#if !defined(COLOR_HPP)
#define COLOR_HPP
#if !defined(MEMSTRM_HPP)
#include <memstrm.hpp>
#endif
#if !defined(SCALAR_HPP)
#include <scalar.hpp>
#endif
//##########################################################################
//############## RGBColor ############################################
//##########################################################################
class RGBColor
{
friend class RGBAColor;
public:
Scalar
Red,
Green,
Blue;
#if defined(USE_SIGNATURE)
friend int
Is_Signature_Bad(const volatile RGBColor *p)
{
return False;
}
#endif
RGBColor()
{
Red = Green = Blue = -1.0f;
}
RGBColor(
Scalar r,
Scalar g,
Scalar b
)
{
Red = r;
Green = g;
Blue = b;
}
Logical
operator==(const RGBColor &a_RGBColor) const
{ return !memcmp(this, &a_RGBColor, sizeof(RGBColor)); }
Logical
operator!=(const RGBColor &a_RGBColor) const
{ return memcmp(this, &a_RGBColor, sizeof(RGBColor)); }
Logical
TestInstance() const;
RGBColor
operator+(const RGBColor &a_RGBColor) const
{
return RGBColor (
min(this->Red + a_RGBColor.Red, 1.0),
min(this->Green + a_RGBColor.Green, 1.0),
min(this->Blue + a_RGBColor.Blue, 1.0));
}
Scalar
Infrared() const
{ return 0.3 * this->Red + 0.5 * this->Green + 0.2 * this->Blue; }
//
// Support functions
//
friend ostream&
operator<<(
ostream& stream,
const RGBColor& C
);
private:
Scalar
min(Scalar x, Scalar y) const
{ return x < y ? x : y; }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
Convert_From_Ascii(
const char *str,
RGBColor *color
);
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
RGBColor *output
)
{return stream->ReadBytes(output, sizeof(*output));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const RGBColor *input
)
{return stream->WriteBytes(input, sizeof(*input));}
//##########################################################################
//############## RGBAColor ###########################################
//##########################################################################
class RGBAColor:
public RGBColor
{
public:
Scalar
Alpha;
RGBAColor():
RGBColor()
{ Alpha = -1.0f; }
RGBAColor(
Scalar r,
Scalar g,
Scalar b,
Scalar a
):
RGBColor(r, g, b)
{ Alpha = a; }
Logical
operator==(const RGBAColor &a_RGBAColor) const
{ return !memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); }
Logical
operator!=(const RGBAColor &a_RGBAColor) const
{ return memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); }
//
// Support functions
//
friend ostream&
operator<<(
ostream& stream,
const RGBAColor& c
);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
Convert_From_Ascii(
const char *str,
RGBAColor *color
);
inline MemoryStream&
MemoryStream_Read(
MemoryStream* stream,
RGBAColor *output
)
{return stream->ReadBytes(output, sizeof(*output));}
inline MemoryStream&
MemoryStream_Write(
MemoryStream* stream,
const RGBAColor *input
)
{return stream->WriteBytes(input, sizeof(*input));}
#endif
//=============================================================================
+158
View File
@@ -0,0 +1,158 @@
#if !defined(CONFIG_HPP)
# define CONFIG_HPP
# if DEBUG_LEVEL>=3
# undef USE_ACTIVE_PROFILE // Disables trace activity
# define USE_TIME_ANALYSIS // Enables trace time statistics
# undef USE_TRACE_LOG // Disables logging functions
# define USE_FPU_ANALYSIS // Enables entity FPU checks
# define USE_MEMORY_ANALYSIS // Enables heap statistics
# undef USE_EVENT_STATISTICS // Disables event statistics
# elif DEBUG_LEVEL==2
# undef USE_ACTIVE_PROFILE // Disables trace activity
# define USE_TIME_ANALYSIS // Enables trace time statistics
# undef USE_TRACE_LOG // Disables logging functions
# define USE_FPU_ANALYSIS // Enables entity FPU checks
# define USE_MEMORY_ANALYSIS // Enables heap statistics
# undef USE_EVENT_STATISTICS // Disables event statistics
# elif DEBUG_LEVEL==1
# undef USE_ACTIVE_PROFILE // Disables trace activity
# define USE_TIME_ANALYSIS // Enables trace time statistics
# undef USE_TRACE_LOG // Disables logging functions
# define USE_FPU_ANALYSIS // Enables entity FPU checks
# define USE_MEMORY_ANALYSIS // Enables heap statistics
# undef USE_EVENT_STATISTICS // Disables event statistics
# elif DEBUG_LEVEL==0
# if defined(LAB_ONLY)
# undef USE_ACTIVE_PROFILE // Disables trace activity
# define USE_TIME_ANALYSIS // Enables trace time statistics
# define USE_TRACE_LOG // Enables logging functions
# undef USE_FPU_ANALYSIS // Disables entity FPU checks
# undef USE_MEMORY_ANALYSIS // Disables heap statistics
# define USE_EVENT_STATISTICS // Enables event statistics
# else
# undef USE_ACTIVE_PROFILE // Disables trace activity
# undef USE_TIME_ANALYSIS // Disables trace time statistics
# undef USE_TRACE_LOG // Disables logging functions
# undef USE_FPU_ANALYSIS // Disables entity FPU checks
# undef USE_MEMORY_ANALYSIS // Disables heap statistics
# undef USE_EVENT_STATISTICS // Disables event statistics
# endif
# endif
# if defined(USE_TIME_ANALYSIS) || defined(USE_ACTIVE_PROFILE)\
|| defined(USE_TRACE_LOG)
# define TRACE_ON
# endif
//
// Traces are expensive, release build should not have them
//
# if defined(TRACE_ON) && defined(LAB_ONLY)
# define TRACE_FOREGROUND_PROCESSING
//# define TRACE_RENDERER_MANAGER
//# define TRACE_PROCESS_EVENT
# define TRACE_EVENT_COUNT
//
// Update Manager Group
//
//# define TRACE_UPDATE_MANAGER
//# define TRACE_UPDATE_MASTER
//# define TRACE_UPDATE_REPLICANTS
//
// Networking Group
//
//# define TRACE_SEND_PACKET
//# define TRACE_ROUTE_PACKET
//# define TRACE_LOST_DATA
//# define TRACE_SEND_BUFFER
//
// Video Renderer group
// To see all the video renderer traces seperately, DO NOT define USE_ONE_VIDEO_TRACE
// To see all of the video renderer on the same trace, enable the following:
//
// USE_ONE_VIDEO_TRACE
// TRACE_VIDEO_RENDERER
// TRACE_VIDEO_BECOME_INTERESTING
// TRACE_VIDEO_BECOME_UNINTERESTING
// TRACE_VIDEO_RENDERER_FRAME_DONE
//
// The time used by the above four traces will all appear on the video renderer
// trace together. This configuration should not cause any buzzing of traces and
// should capture 100% of the video renderer's activity.
// Other video renderer traces may be enabled but will appear seperately
//
// CAUTION: Depending on the setup, TRACE_VIDEO_RENDERABLES can buzz, severly
// lengthening the video renderer profile times. Use carefully.
//
//# define USE_ONE_VIDEO_TRACE
//# define TRACE_VIDEO_RENDERER
//# define TRACE_VIDEO_BECOME_INTERESTING
//# define TRACE_VIDEO_BECOME_UNINTERESTING
//# define TRACE_VIDEO_RENDERER_FRAME_DONE
//# define TRACE_VIDEO_CULL_SETUP
//# define TRACE_VIDEO_VEHICLE_RENDERABLES
//# define TRACE_VIDEO_ALL_RENDERABLES
//# define TRACE_VIDEO_MECH_CULL_RENDERABLE
//# define TRACE_VIDEO_BATCH_FLUSH
//# define TRACE_VIDEO_LOAD_OBJECT
//# define TRACE_VIDEO_PICKPOINT
//# define TRACE_VIDEO_RENDERABLES
//# define TRACE_VIDEO_CONSTRUCT_ROOT // construct the root of
//# define TRACE_VIDEO_FIRST_FRAME_DONE // obsolete soon
//
// Audio renderer group
//
//# define TRACE_AUDIO_RENDERER
//# define TRACE_AUDIO_RENDERER_MIDI
//# define TRACE_AUDIO_RENDERER_CREATE_OBJECTS
//# define TRACE_AUDIO_RENDERER_DESTROY_OBJECTS
//# define TRACE_AUDIO_RENDERER_START_HANDLER
//# define TRACE_AUDIO_RENDERER_STOP_HANDLER
//# define TRACE_AUDIO_RENDERER_EXECUTE
//# define TRACE_AUDIO_RENDERER_RUNNING_SOURCES
//# define TRACE_AUDIO_RENDERER_RUNNING_SORT
//# define TRACE_AUDIO_RENDERER_CALCULATE_MIX
//# define TRACE_AUDIO_RENDERER_EXECUTE_SOURCES
//# define TRACE_AUDIO_RENDERER_DORMANT_SOURCES
//
// Gauge renderer group
//
//# define TRACE_GAUGE_RENDERER
//# define TRACE_SCREEN_COPY
//
// Other leftovers, these are probably obsolete, if you know ones that are, kill
// kill them off as appropriate.
//
# if 0
# define TRACE_COMPLETE_CYCLES
# define TRACE_DEATH_ROW
# define TRACE_EXECUTE_ENTITY
# define TRACE_PERFORM_ENTITY
# define TRACE_PERFORM_SUBSYSTEMS
# define TRACE_EXECUTE_WATCHERS
# define TRACE_RIO_RECEIVE_PACKET
# define TRACE_RIO_SEND_PACKET
# define TRACE_CHECK_BUFFERS
# define TRACE_CALL_NETNUB
# endif
# endif
#endif
+103
View File
@@ -0,0 +1,103 @@
//===========================================================================//
// File: cnslmsgs.cpp //
// Project: MUNGA Brick: //
// Contents: Console messages //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/02/95 ECH Initial coding. //
// 06/03/95 GAH Added corresponding Macintosh message defintions. //
// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CONSOLE_HPP)
# include <console.hpp>
#endif
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~~~~
ConsoleApplicationReadyToRunMessage::
ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID):
NetworkClient::Message(
ConsoleApplicationReadyToRunMessageID,
sizeof(ConsoleApplicationReadyToRunMessage)
)
{
readyToRunHostID = ready_to_run_host_ID;
}
//~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~~~~
ConsoleApplicationStateResponseMessage::ConsoleApplicationStateResponseMessage(
HostID responding_host_ID,
Enumeration application_state,
Enumeration application_type
):
NetworkClient::Message(
ConsoleApplicationStateResponseMessageID,
sizeof(ConsoleApplicationStateResponseMessage)
)
{
respondingHostID = responding_host_ID;
applicationState = application_state;
application = application_type;
}
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
ConsoleApplicationEndMissionMessage::
ConsoleApplicationEndMissionMessage(
HostID player_host_ID,
int final_score
):
NetworkClient::Message(
ConsoleApplicationEndMissionMessageID,
sizeof(ConsoleApplicationEndMissionMessage)
)
{
playerHostID = player_host_ID;
finalScore = final_score;
}
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~
ConsoleApplicationAbortMissionMessage::
ConsoleApplicationAbortMissionMessage(
HostID player_host_ID
):
NetworkClient::Message(
ConsoleApplicationAbortMissionMessageID,
sizeof(ConsoleApplicationAbortMissionMessage)
)
{
playerHostID = player_host_ID;
}
//~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~~~~
ConsoleApplicationTeamEndMissionMessage::
ConsoleApplicationTeamEndMissionMessage(
HostID player_host_ID,
int player_score,
int team_ID,
int team_score
):
NetworkClient::Message(
ConsoleApplicationTeamEndMissionMessageID,
sizeof(ConsoleApplicationTeamEndMissionMessage)
)
{
playerHostID = player_host_ID;
playerScore = player_score;
teamID = team_ID;
teamScore = team_score;
}
//==============================================================================
+306
View File
@@ -0,0 +1,306 @@
//===========================================================================//
// File: cnslmsgs.hpp //
// Project: MUNGA Brick: //
// Contents: Console messages //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 06/02/95 ECH Initial coding. //
// 06/03/95 GAH Added corresponding Macintosh message defintions. //
// 10/05/95 GAH Added ConsoleApplicationEndMissionMessage. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CONSOLE_HPP)
# define CONSOLE_HPP
#ifdef MAC
#pragma once
#endif
#ifdef MAC
#include "NetworkEndpoint.h"
#include "Participant.h"
#else
# if !defined(NETWORK_HPP)
# include <network.hpp>
# endif
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~ Console Message IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
enum ConsoleMessageID
{
ConsoleApplicationReadyToRunMessageID = 0,
ConsoleApplicationStateResponseMessageID = 1,
ConsoleApplicationEndMissionMessageID = 7,
ConsoleApplicationAbortMissionMessageID = 11,
ConsoleApplicationTeamEndMissionMessageID = 14
};
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class ConsoleApplicationReadyToRunMessage:
public NetworkEndpoint::Message
{
public:
ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID);
long
GetReadyToRunHostID()
{return readyToRunHostID.value();}
private:
HostID
readyToRunHostID;
};
#pragma options align=reset
#else
class ConsoleApplicationReadyToRunMessage:
public NetworkClient::Message
{
public:
ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID);
HostID
GetReadyToRunHostID()
{return readyToRunHostID;}
private:
HostID
readyToRunHostID;
};
#endif
//~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class ConsoleApplicationStateResponseMessage:
public NetworkEndpoint::Message
{
public:
ConsoleApplicationStateResponseMessage(
HostID responding_host_ID,
LEDWORD application_state,
LEDWORD application_type
);
long
GetRespondingHostID()
{return respondingHostID.value();}
long
GetApplicationState()
{return applicationState.value();}
ApplicationID
GetApplication()
{return((ApplicationID) application.value());}
private:
HostID
respondingHostID;
LEDWORD
applicationState;
LEDWORD
application;
};
#pragma options align=reset
#else
class ConsoleApplicationStateResponseMessage:
public NetworkClient::Message
{
public:
ConsoleApplicationStateResponseMessage(
HostID responding_host_ID,
Enumeration application_state,
Enumeration application
);
HostID
GetRespondingHostID()
{return respondingHostID;}
Enumeration
GetApplicationState()
{return applicationState;}
Enumeration
GetApplication()
{return application;}
private:
HostID
respondingHostID;
Enumeration
applicationState;
Enumeration
application;
};
#endif
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class ConsoleApplicationEndMissionMessage:
public NetworkEndpoint::Message
{
public:
ConsoleApplicationEndMissionMessage(
HostID player_ID,
LEDWORD final_score
);
long
GetPlayerHostID()
{return playerHostID.value();}
long
GetFinalScore()
{return finalScore.value();}
private:
HostID
playerHostID;
LEDWORD
finalScore;
};
#pragma options align=reset
#else
class ConsoleApplicationEndMissionMessage:
public NetworkClient::Message
{
public:
ConsoleApplicationEndMissionMessage(
HostID player_host_ID,
int final_score
);
HostID
GetPlayerHostID()
{return playerHostID;}
int
GetFinalScore()
{return finalScore;}
private:
HostID
playerHostID;
int
finalScore;
};
#endif
//~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class ConsoleApplicationAbortMissionMessage:
public NetworkEndpoint::Message
{
public:
ConsoleApplicationAbortMissionMessage(
HostID player_ID
);
long
GetPlayerHostID()
{return playerHostID.value();}
private:
HostID
playerHostID;
};
#pragma options align=reset
#else
class ConsoleApplicationAbortMissionMessage:
public NetworkClient::Message
{
public:
ConsoleApplicationAbortMissionMessage(
HostID player_host_ID
);
HostID
GetPlayerHostID()
{return playerHostID;}
private:
HostID
playerHostID;
};
#endif
//~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~
#ifdef MAC
#pragma options align=mac68k4byte
class ConsoleApplicationTeamEndMissionMessage:
public NetworkEndpoint::Message
{
public:
ConsoleApplicationTeamEndMissionMessage(
HostID player_ID,
LEDWORD player_score,
LEDWORD team_id,
LEDWORD team_score
);
long
GetPlayerHostID()
{return playerHostID.value();}
long
GetPlayerScore()
{return playerScore.value();}
long
GetTeamID()
{return teamID.value();}
long
GetTeamScore()
{return teamScore.value();}
private:
HostID
playerHostID;
LEDWORD
playerScore;
LEDWORD
teamID;
LEDWORD
teamScore;
};
#pragma options align=reset
#else
class ConsoleApplicationTeamEndMissionMessage:
public NetworkClient::Message
{
public:
ConsoleApplicationTeamEndMissionMessage(
HostID player_host_ID,
int player_score,
int team_id,
int team_score
);
HostID
GetPlayerHostID()
{return playerHostID;}
int
GetFinalScore()
{return playerScore;}
int
GetTeamID()
{return teamID;}
int
GetTeamScore()
{return teamScore;}
private:
HostID
playerHostID;
int
playerScore;
int
teamID;
int
teamScore;
};
#endif
#endif
+682
View File
@@ -0,0 +1,682 @@
//==========================================================================//
// File: controls.cc //
// Project: MUNGA Brick: Controls Manager //
// Contents: Interface specification for Controls //
//--------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ----------------------------------------------------------//
// 11/21/94 CPB Initial coding. //
// 01/25/95 CPB Major surgery! Removed Entities, added Subsystems. //
//--------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//==========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(CONTROLS_HPP)
# include <controls.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if defined(DEBUG)
# define Test_Tell(n) DEBUG_STREAM << n
#else
# define Test_Tell(n)
#endif
//############################################################################
//####################### ControlsInstance #############################
//############################################################################
ControlsInstance::ControlsInstance(
ClassID class_ID,
ModeMask mode_mask,
Plug *dependant
):
Node(class_ID),
dependantPlug(this)
{
Check_Pointer(this);
modeMask = mode_mask;
dependantPlug.Add(dependant);
Check_Fpu();
}
ControlsInstance::~ControlsInstance()
{
Check(this);
Check_Fpu();
}
void
ControlsInstance::Update(void *)
{
Fail("ControlsInstance::Update not overridden!");
}
//
//#############################################################################
//#############################################################################
//
void
ControlsInstance::ReleaseLinkHandler(
Socket*,
Plug*
)
{
Unregister_Object(this);
delete this;
Check_Fpu();
}
//############################################################################
//######################### ControlsMappingGroup #############################
//############################################################################
//
// The ControlsMappingGroup object maintains a group of ControlInstances.
//
// ControlsMappingGroup.Update() will call ControlsInstance.Update()
// for each instance in the group.
//
ControlsMappingGroup::ControlsMappingGroup():
Node(ControlsMappingGroup::ControlsMappingGroupClassID),
instanceList(this)
{
Check_Pointer(this);
Check_Fpu();
}
ControlsMappingGroup::~ControlsMappingGroup()
{
Check(this);
Remove(0); // remove all mappings
Check_Fpu();
}
void ControlsMappingGroup::Remove(ModeMask mode_mask)
{
Check(this);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
//---------------------------------------------
// Remove mapping bit(s)
//---------------------------------------------
controls_instance->modeMask &= ~mode_mask;
//---------------------------------------------
// If no bits left, delete mapping
//---------------------------------------------
if (controls_instance->modeMask == (ModeMask)0)
{
Unregister_Object(controls_instance);
delete controls_instance;
}
}
Check_Fpu();
}
void
ControlsMappingGroup::Update(void *data_source, ModeMask mode_mask)
{
Check(this);
Check_Pointer(data_source);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
//------------------------------------------------
// Process only if at least one mode bit matches
//------------------------------------------------
Check(controls_instance);
if (controls_instance->modeMask & mode_mask)
{
controls_instance->Update(data_source);
}
}
Check_Fpu();
}
Logical
ControlsMappingGroup::CurrentFilterStatus(ModeMask mode_mask)
{
Check(this);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
if (controls_instance->modeMask & mode_mask)
{
Check_Fpu();
return True;
}
}
Check_Fpu();
return False;
}
//############################################################################
//########################### ControlsManager ################################
//############################################################################
//---------------------------------------------------------------------------
// Class derivation
//---------------------------------------------------------------------------
Derivation
ControlsManager::ClassDerivations(
Receiver::ClassDerivations,"ControlsManager"
);
unsigned int
ControlsManager::nextOwnerID=0;
ControlsManager
*ControlsManager::headControlsManager = NULL;
//
//############################################################################
// ControlsManager
//
// Creator method
//----------------------------------------------------------------------------
// Enter: virtualDataPtr
//############################################################################
//
ControlsManager::ControlsManager(
ClassID class_ID,
SharedData &shared_data
):
Receiver(
class_ID,
shared_data
)
{
activeDestination = NULL;
activeReceiver = NULL;
activeMessageID = (Receiver::MessageID) 0;
activeDependant = NULL;
//----------------------------------------------------
// Add this object to the chain
//----------------------------------------------------
nextControlsManager = headControlsManager;
headControlsManager = this;
Check_Fpu();
}
//
//############################################################################
// ~ControlsManager
//
// Destructor method
//############################################################################
//
ControlsManager::~ControlsManager()
{
//----------------------------------------------------
// Unlink this object from the chain
//----------------------------------------------------
ControlsManager
*controls_manager,
*previous_controls_manager(NULL);
//
// Search for 'this' in the chain
//
for(
controls_manager = headControlsManager;
controls_manager != NULL;
controls_manager = controls_manager->nextControlsManager
)
{
if (controls_manager == this)
{
//
// Found! head of list?
//
if (previous_controls_manager == NULL)
{
headControlsManager = nextControlsManager;
}
//
// Not head, remove from chain
//
else
{
previous_controls_manager->nextControlsManager =
nextControlsManager;
}
break;
}
//
// Keep track of 'previous' object
//
previous_controls_manager = controls_manager;
}
Check_Fpu();
}
void
ControlsManager::Remove(ModeMask /*mode_mask*/)
{
Fail("ControlsManager::Remove should not be called!\n");
}
void
ControlsManager::Execute()
{
Fail("ControlsManager::Execute should not be called!\n");
}
void
ControlsManager::StartMappableButtonsConfigure(
void *active_direct_target,
Receiver *target,
Plug *dependant,
Receiver::MessageID active_message_id,
ModeMask remove_mode_mask,
ModeMask add_mode_mask
)
{
Check(this);
activeReceiver = target;
activeMessageID = active_message_id;
activeDestination = active_direct_target;
activeDependant = dependant;
Check(application);
ModeManager
*mode_manager = application->GetModeManager();
Check(mode_manager);
mode_manager->RemoveModeMask(remove_mode_mask);
mode_manager->AddModeMask(add_mode_mask);
Check_Fpu();
}
void
ControlsManager::StopMappableButtonsConfigure(
ModeMask remove_mode_mask,
ModeMask add_mode_mask
)
{
Check(this);
Check(application);
ModeManager
*mode_manager = application->GetModeManager();
Check(mode_manager);
mode_manager->RemoveModeMask(remove_mode_mask);
mode_manager->AddModeMask(add_mode_mask);
activeDestination = NULL;
activeReceiver = NULL;
activeMessageID = (Receiver::MessageID) 0;
activeDependant = NULL;
Check_Fpu();
}
void
ControlsManager::AddOrEraseMappableButton(
int /*button_number*/,
ModeMask /*mode_mask*/
)
{
Check(this);
Check_Fpu();
}
//
//############################################################################
// TestInstance
//
//############################################################################
//
Logical
ControlsManager::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
//
//############################################################################
// Shutdown
//
//############################################################################
//
void
ControlsManager::Shutdown()
{
ControlsManager
*controls_manager;
for(
controls_manager = headControlsManager;
controls_manager != NULL;
controls_manager = controls_manager->nextControlsManager
)
{
controls_manager->LocalShutdown();
}
Check_Fpu();
}
void
ControlsManager::LocalShutdown()
{
Check(this);
Check_Fpu();
}
//#########################################################################
//############################# ControlsString ############################
//#########################################################################
int
ControlsString::nextID = 1;
ControlsString::ControlsString(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
int user_code
):
Node(RegisteredClass::ControlsStringClassID)
{
Test_Tell(
"ControlsString creator('" new_string <<
"'," << keypad_unit_number <<
"," << receiver_pointer <<
"," << message_id <<
")\n"
);
Check_Pointer(this);
Check_Pointer(new_string);
Check(receiver_pointer);
//----------------------------------------------
// Assign unique ID
//----------------------------------------------
id = nextID++;
matchStringPointer = new_string;
keypadUnitNumber = keypad_unit_number;
//----------------------------------------------
// Save message data
//----------------------------------------------
receiverPointer = receiver_pointer;
messageID = message_id;
userCode = user_code;
//----------------------------------------------
// Clear the buffer
//----------------------------------------------
string[0] = '\0';
stringLength = 0;
Check_Fpu();
}
ControlsString::~ControlsString()
{
Test_Tell("ControlsString destructor\n");
Check(this);
Check_Fpu();
}
Logical
ControlsString::TestInstance() const
{
return True;
}
void
ControlsString::Update(int keypad_unit_number, ControlsKey new_key)
{
Test_Tell(
"ControlsString::Update(" << keypad_unit_number <<
"," << new_key <<
"\n"
);
Check(this);
//----------------------------------------------
// Update only if proper keyboard unit
//----------------------------------------------
if (keypad_unit_number == keypadUnitNumber)
{
//--------------------------------------
// Get string length
//--------------------------------------
Check_Pointer(matchStringPointer);
int
length = strlen(matchStringPointer);
if (length > maxStringLength)
{
length = maxStringLength;
}
if (stringLength > length) // in case matchString changes
{
stringLength = length;
string[stringLength] = '\0';
}
//--------------------------------------
// Update string buffer
//--------------------------------------
if (stringLength < length)
{
string[stringLength++] = (char) new_key;
string[stringLength] = '\0';
}
else
{
if (length > 1)
{
memmove(&string[0],&string[1], length-1);
}
string[length-1] = (char) new_key;
}
Test_Tell("string=" << string << "\n");
//--------------------------------------
// Check for match
//--------------------------------------
if (strnicmp(string, matchStringPointer, length) == 0)
{
Test_Tell(
"ControlsString::Update, '" << matchStringPointer <<
"' matched!\n"
);
//--------------------------------------
// Match found, send message
//--------------------------------------
Check(receiverPointer);
Check(application);
ControlsStringMessage
message(messageID, this->userCode);
receiverPointer->Dispatch(&message);
//--------------------------------------
// Clear the string
//--------------------------------------
string[0] = '\0';
stringLength = 0;
}
}
Check_Fpu();
}
//#########################################################################
//######################## ControlsStringManager ##########################
//#########################################################################
ControlsStringManager::ControlsStringManager() :
Node(RegisteredClass::ControlsStringManagerClassID),
instanceList(this)
{
Test_Tell("ControlsStringManager creator\n");
Check_Pointer(this);
}
ControlsStringManager::~ControlsStringManager()
{
Test_Tell("ControlsStringManager destructor\n");
Check(this);
//----------------------------------------------
// Remove all ControlStrings
//----------------------------------------------
Remove(0);
Check_Fpu();
}
Logical
ControlsStringManager::TestInstance() const
{
return True;
}
ControlsStringID
ControlsStringManager::Add(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
int user_code
)
{
Test_Tell("ControlsStringManager::Add(" << new_string <<
"," << keypad_unit_number <<
"," << receiver_pointer <<
"," << message_id <<
"\n"
);
Check(this);
Check_Pointer(new_string);
Check(receiver_pointer);
//----------------------------------------------
// Create the ControlsString
//----------------------------------------------
ControlsString
*string_item = new ControlsString(
new_string,
keypad_unit_number,
receiver_pointer,
message_id,
user_code
);
Check(string_item);
Register_Object(string_item);
//----------------------------------------------
// Add to the instance list
//----------------------------------------------
instanceList.Add(string_item);
//----------------------------------------------
// return the new string's (unique) ID
//----------------------------------------------
Check_Fpu();
return string_item->id;
}
void
ControlsStringManager::Remove(ControlsStringID string_id)
{
Test_Tell("ControlsStringManager::Remove(" << string_id << ")\n");
Check(this);
ChainIteratorOf<ControlsString*>
i(instanceList);
ControlsString
*controls_string;
//----------------------------------------------
// Search for the given ID (or universal match)
//----------------------------------------------
while ((controls_string=i.ReadAndNext()) != NULL)
{
Check(controls_string);
if (
(string_id == 0) ||
(controls_string->id == string_id)
)
{
Unregister_Object(controls_string);
delete controls_string;
//------------------------------------------
// If this is not a 'universal' remove,
// we're done (ID's are unique)
//------------------------------------------
if (string_id != 0)
{
break;
}
}
}
Check_Fpu();
}
void
ControlsStringManager::Update(
int keypad_unit_number,
ControlsKey new_key
)
{
Test_Tell("ControlsStringManager::Update(" << keypad_unit_number <<
"," << new_key <<
")\n"
);
Check(this);
//--------------------------------------
// Update all matching string items
//--------------------------------------
ChainIteratorOf<ControlsString*>
i(instanceList);
ControlsString
*controls_string;
while ((controls_string=i.ReadAndNext()) != NULL)
{
Check(controls_string);
controls_string->Update(keypad_unit_number, new_key);
}
Check_Fpu();
}
#if defined(TEST_CLASS)
# include "controls.tcp"
#endif
+947
View File
@@ -0,0 +1,947 @@
//===========================================================================//
// File: controls.hpp //
// Project: MUNGA Brick: Controls Module //
// Contents: Interface specification for Controls module //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 12/12/94 CPB Initial coding. //
// 01/25/95 CPB Major surgery! Removed Entities, added Receivers. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CONTROLS_HPP)
# define CONTROLS_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
class Controls;
class ControlsInstance;
class ControlsMappingGroup;
struct ControlsMapping;
class ControlsOwner;
class ControlsManager;
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
# if !defined(CHAIN_HPP)
# include <chain.hpp>
# endif
# if !defined(VECTOR2D_HPP)
# include <vector2d.hpp>
# endif
# if !defined(RECEIVER_HPP)
# include <receiver.hpp>
# endif
# if !defined(SIMULATE_HPP)
# include <simulate.hpp>
# endif
# if !defined(MODE_HPP)
# include <mode.hpp>
# endif
//########################################################################
//######################## Basic control typedefs ########################
//########################################################################
typedef Scalar ControlsScalar;
typedef Vector2DOf<Scalar> ControlsJoystick;
typedef int ControlsKey;
typedef int ControlsButton; // negative for release
typedef Vector2DOf<int> ControlsMouse;
//#########################################################################
//######################### ControlsInstance ##############################
//#########################################################################
// The ControlsInstance object exists to serve the ControlsMappingGroup
// object. It maintains one instance of a mapping from a physical
// input device to either an entity event message or a value.
class ControlsInstance :
public Node
{
friend class ControlsMappingGroup;
friend class ControlsManager; // required for testing
friend class L4MappableButtonManager;
public:
ControlsInstance(
ClassID class_id,
ModeMask mode_mask,
Plug *dependant
);
~ControlsInstance();
ModeMask
modeMask; // lots of objects (and templates) need access to this
protected:
virtual void Update(void *data_source);
SlotOf<Plug*>
dependantPlug;
void
ReleaseLinkHandler(
Socket *socket,
Plug *plug
);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceDirectOf ~~~~~~~~~~~~~~~~~~
template <class T> class ControlsInstanceDirectOf:
public ControlsInstance
{
friend class ControlsMappingGroup;
friend class ControlsManager; // required for testing
public:
ControlsInstanceDirectOf(
ModeMask mode_mask,
T* data_pointer,
Plug *dependant
);
ControlsInstanceDirectOf(
ControlsInstanceDirectOf<T> *original
);
~ControlsInstanceDirectOf();
Logical
TestInstance() const;
// protected:
void Update(void *data_source);
T *dataPointer;
};
template <class T> ControlsInstanceDirectOf<T>::ControlsInstanceDirectOf(
ModeMask mode_mask,
T* data,
Plug *dependant
):
ControlsInstance(
DirectControlsInstanceClassID,
mode_mask,
dependant
),
dataPointer(data)
{}
template <class T> ControlsInstanceDirectOf<T>::ControlsInstanceDirectOf(
ControlsInstanceDirectOf<T> *original
):
ControlsInstance(
DirectControlsInstanceClassID,
original->modeMask,
original->dependantPlug.GetCurrent()
),
dataPointer(original->dataPointer)
{}
template <class T> ControlsInstanceDirectOf<T>::~ControlsInstanceDirectOf()
{}
template <class T> void
ControlsInstanceDirectOf<T>::Update(void *data_source)
{
Check(this);
Check_Pointer(data_source);
Check_Pointer(dataPointer);
*dataPointer = *(T*)data_source;
Verify(*dataPointer == *(T*)data_source);
Check_Fpu();
}
template <class T> Logical
ControlsInstanceDirectOf<T>::TestInstance() const
{
Check_Pointer(this);
Check_Pointer(dataPointer);
Check_Fpu();
return Plug::TestInstance();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceEventOf ~~~~~~~~~~~~~~~~~~
template <class T> class ControlsInstanceEventOf:
public ControlsInstance
{
friend class ControlsMappingGroup;
friend class ControlsManager; // required for testing
public:
ControlsInstanceEventOf(
ModeMask mode_mask,
Receiver *receiver,
Receiver::MessageID message_id,
Plug *dependant
);
ControlsInstanceEventOf(
ControlsInstanceEventOf<T> *original
);
~ControlsInstanceEventOf();
Logical
TestInstance() const;
// protected:
void Update(void *data_source);
Receiver *receiverPointer;
Receiver::MessageID messageID;
};
template <class T> ControlsInstanceEventOf<T>::ControlsInstanceEventOf(
ModeMask mode_mask,
Receiver *receiver,
Receiver::MessageID message_id,
Plug *dependant
):
ControlsInstance(
EventControlsInstanceClassID,
mode_mask,
dependant
),
receiverPointer(receiver),
messageID(message_id)
{}
template <class T> ControlsInstanceEventOf<T>::ControlsInstanceEventOf(
ControlsInstanceEventOf<T> *original
):
ControlsInstance(
EventControlsInstanceClassID,
original->modeMask,
original->dependantPlug.GetCurrent()
),
receiverPointer(original->receiverPointer),
messageID(original->messageID)
{}
template <class T> ControlsInstanceEventOf<T>::~ControlsInstanceEventOf()
{}
template <class T> void
ControlsInstanceEventOf<T>::Update(void *data_source)
{
Check(this);
Check_Pointer(data_source);
Check(application);
ReceiverDataMessageOf<T>
update_message(
messageID,
sizeof(ReceiverDataMessageOf<T>),
*(T*)data_source
);
application->Post(
ControlsEventPriority,
receiverPointer,
&update_message
);
}
template <class T> Logical
ControlsInstanceEventOf<T>::TestInstance() const
{
Check_Pointer(this);
Check(receiverPointer);
Check_Fpu();
return Plug::TestInstance();
}
//#########################################################################
//######################### ControlsMappingGroup ##########################
//#########################################################################
// The ControlsMappingGroup object maintains a group of ControlInstances.
//
// ControlsMappingGroup.Update() will call ControlsInstance.Update()
// for each instance in the group.
class ControlsMappingGroup :
public Node
{
friend class ControlsManager; // required for testing
public:
ControlsMappingGroup();
~ControlsMappingGroup();
void
Add(ControlsInstance *mapping)
{
Check(this);
Check(mapping);
instanceList.Add(mapping);
}
virtual void
Remove(ModeMask mode_mask);
virtual void
Update(void *value, ModeMask mode_mask);
Logical // returns true if at least one button active
CurrentFilterStatus(ModeMask mode_mask);
protected:
ChainOf<ControlsInstance*>
instanceList;
};
//#########################################################################
//########################## ControlsUpdateManager ########################
//#########################################################################
template <class T> class ControlsUpdateManager :
public ControlsMappingGroup
{
public:
ControlsUpdateManager();
~ControlsUpdateManager();
Logical
TestInstance() const;
virtual ControlsInstance*
Add(
ModeMask mode_mask,
Receiver *receiver_pointer,
Receiver::MessageID id,
Plug *dependant
);
virtual ControlsInstance*
Add(
ModeMask mode_mask,
T *destination,
Plug *dependant
);
virtual ControlsInstance*
AddOrErase(
ModeMask mode_mask,
Receiver *target,
Receiver::MessageID message_ID,
Plug *dependant
);
virtual ControlsInstance*
AddOrErase(
ModeMask mode_mask,
T *destination,
Plug *dependant
);
enum
{
unmapped = 0,
mappedByOthers = 1,
mappedByMe = 2
};
virtual int
GetMapState(
void *direct_destination,
Receiver *event_receiver,
Receiver::MessageID message_id,
ModeMask mode_mask
);
virtual void
Update(void *sourcePointer, ModeMask mode_mask);
void
ForceUpdate(T *sourcePointer, ModeMask mode_mask);
T
previousValue;
};
template <class T> Logical
ControlsUpdateManager<T>::TestInstance() const
{
return True;
}
template <class T>
ControlsUpdateManager<T>::ControlsUpdateManager()
: ControlsMappingGroup()
{
}
template <class T> ControlsUpdateManager<T>::~ControlsUpdateManager()
{
}
template <class T> void
ControlsUpdateManager<T>::Update(
void * source_pointer,
ModeMask mode_mask
)
{
Check(this);
Check_Pointer(source_pointer);
if (previousValue != *(T*) source_pointer)
{
ForceUpdate((T*)source_pointer, mode_mask);
}
Check_Fpu();
}
template <class T> void
ControlsUpdateManager<T>::ForceUpdate(
T* source_pointer,
ModeMask mode_mask
)
{
Check(this);
Check_Pointer(source_pointer);
previousValue = *source_pointer;
ControlsMappingGroup::Update(source_pointer, mode_mask);
Check_Fpu();
}
template <class T> ControlsInstance*
ControlsUpdateManager<T>::Add(
ModeMask mode_mask,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
Plug *dependant
)
{
Check(this);
Check(receiver_pointer);
ControlsInstanceEventOf<T> *instance =
new ControlsInstanceEventOf<T>(
mode_mask,
receiver_pointer,
message_id,
dependant
);
Register_Object(instance);
ControlsMappingGroup::Add(instance);
Check_Fpu();
return instance;
}
template <class T> ControlsInstance*
ControlsUpdateManager<T>::Add(
ModeMask mode_mask,
T *destination,
Plug *dependant
)
{
Check(this);
Check_Pointer(destination);
ControlsInstanceDirectOf<T> *instance =
new ControlsInstanceDirectOf<T>(
mode_mask,
destination,
dependant
);
Register_Object(instance);
ControlsMappingGroup::Add(instance);
Check_Fpu();
return instance;
}
template <class T> ControlsInstance*
ControlsUpdateManager<T>::AddOrErase(
ModeMask mode_mask,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
Plug *dependant
)
{
Check(this);
Check(receiver_pointer);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
ControlsInstanceEventOf<T>
*event_mapping;
//-----------------------------------------------
// Search through all mappings
//-----------------------------------------------
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
//-----------------------------------------------
// Process only the event mappings
//-----------------------------------------------
if (controls_instance->GetClassID() == EventControlsInstanceClassID)
{
event_mapping = (ControlsInstanceEventOf<T> *)controls_instance;
Check(event_mapping);
//-----------------------------------------------
// Process only if the target is correct, AND
// if the mapping is allowed under the given
// mode mask
//-----------------------------------------------
if (
(event_mapping->receiverPointer == receiver_pointer) &&
(event_mapping->messageID == message_id) &&
(event_mapping->modeMask & mode_mask)
)
{
//-----------------------------------------------
// Found! Remove mode enable bit(s)
//-----------------------------------------------
event_mapping->modeMask &= ~mode_mask;
//-----------------------------------------------
// If this mapping no longer matches ANY mode
// (i.e., all bits cleared), delete it, 'cuz
// it doesn't do anything anymore.
//-----------------------------------------------
if (event_mapping->modeMask == (ModeMask)0)
{
Unregister_Object(event_mapping);
delete event_mapping;
}
//-----------------------------------------------
// We found the match, break out of the loop
//-----------------------------------------------
break;
}
}
}
//----------------------------------------------------------
// If the mapping wasn't found (controls_instance == NULL),
// then create one.
//----------------------------------------------------------
if (controls_instance == NULL)
{
event_mapping =
new ControlsInstanceEventOf<T>(
mode_mask,
receiver_pointer,
message_id,
dependant
);
Register_Object(event_mapping);
ControlsMappingGroup::Add(event_mapping);
Check_Fpu();
return event_mapping;
}
Check_Fpu();
return NULL;
}
template <class T> ControlsInstance*
ControlsUpdateManager<T>::AddOrErase(
ModeMask mode_mask,
T *destination,
Plug *dependant
)
{
Check(this);
Check_Pointer(destination);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
ControlsInstanceDirectOf<T>
*direct_mapping;
//-----------------------------------------------
// Search through all mappings
//-----------------------------------------------
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
//-----------------------------------------------
// Process only the direct mappings
//-----------------------------------------------
if (controls_instance->GetClassID() == DirectControlsInstanceClassID)
{
direct_mapping = (ControlsInstanceDirectOf<T> *)controls_instance;
Check(direct_mapping);
//-----------------------------------------------
// Process only if the target is correct, AND
// if the mapping is allowed under the given
// mode mask
//-----------------------------------------------
if (
(direct_mapping->dataPointer == destination) &&
(direct_mapping->modeMask & mode_mask)
)
{
//-----------------------------------------------
// Found! Remove mode enable bit(s)
//-----------------------------------------------
direct_mapping->modeMask &= ~mode_mask;
//-----------------------------------------------
// If this mapping no longer matches ANY mode
// (i.e., all bits cleared), delete it, 'cuz
// it doesn't do anything anymore.
//-----------------------------------------------
if (direct_mapping->modeMask == (ModeMask)0)
{
Unregister_Object(direct_mapping);
delete direct_mapping;
}
//-----------------------------------------------
// We found the match, break out of the loop
//-----------------------------------------------
break;
}
}
}
//----------------------------------------------------------
// If the mapping wasn't found (controls_instance == NULL),
// then create one.
//----------------------------------------------------------
if (controls_instance == NULL)
{
direct_mapping =
new ControlsInstanceDirectOf<T>(
mode_mask,
destination,
dependant
);
Register_Object(direct_mapping);
ControlsMappingGroup::Add(direct_mapping);
Check_Fpu();
return direct_mapping;
}
Check_Fpu();
return NULL;
}
template <class T> int
ControlsUpdateManager<T>::GetMapState(
void *direct_destination,
Receiver *event_receiver,
Receiver::MessageID message_id,
ModeMask mode_mask
)
{
Check(this);
ChainIteratorOf<ControlsInstance*>
i(instanceList);
ControlsInstance
*controls_instance;
int
map_state = 0;
//-----------------------------------------------
// Search through all mappings
//-----------------------------------------------
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
//------------------------------------
// Process if allowed mode
//------------------------------------
if (controls_instance->modeMask & mode_mask)
{
//------------------------------------
// Process direct mappings
//------------------------------------
if (controls_instance->GetClassID() ==
DirectControlsInstanceClassID
)
{
ControlsInstanceDirectOf<T>
*direct_mapping = (ControlsInstanceDirectOf<T> *)
controls_instance;
Check(direct_mapping);
if (direct_mapping->dataPointer == direct_destination)
{
map_state |= mappedByMe;
}
else
{
map_state |= mappedByOthers;
}
}
//------------------------------------
// Process event mappings
//------------------------------------
else
{
Verify(controls_instance->GetClassID() ==
EventControlsInstanceClassID
);
ControlsInstanceEventOf<T>
*event_mapping = (ControlsInstanceEventOf<T> *)
controls_instance;
Check(event_mapping);
if (
(event_mapping->receiverPointer == event_receiver) &&
(event_mapping->messageID == message_id)
)
{
map_state |= mappedByMe;
}
else
{
map_state |= mappedByOthers;
}
}
}
}
Check_Fpu();
return map_state;
}
//#########################################################################
//############################ ControlsManager ############################
//#########################################################################
class ControlsManager:
public Receiver
{
friend class ControlsMappingGroup; // for access to groupEnable
//-------------------------------------------------------------------
// Shared data support
//-------------------------------------------------------------------
public:
static Derivation ClassDerivations;
// static SharedData DefaultData;
//-------------------------------------------------------------------
// Construction/destruction/verification
//-------------------------------------------------------------------
protected:
ControlsManager(
ClassID class_ID = ControlsManagerClassID,
SharedData &shared_data = ControlsManager::DefaultData
);
public:
~ControlsManager();
unsigned int
UniqueOwnerID()
{
if ((nextOwnerID+1)==0) { ++nextOwnerID; }
Check_Fpu();
return (++nextOwnerID);
}
virtual void
Remove(ModeMask mode_mask);
virtual void
Execute();
static Logical
TestClass();
Logical
TestInstance() const;
static void
Shutdown();
virtual void
LocalShutdown();
//-------------------------------------------------------------------
// Mode control
//-------------------------------------------------------------------
virtual void
StartMappableButtonsConfigure(
void *active_direct_target,
Receiver *target,
Plug *dependant,
Receiver::MessageID active_message_id,
ModeMask remove_mode_mask,
ModeMask add_mode_mask
);
virtual void
StopMappableButtonsConfigure(
ModeMask remove_mode_mask,
ModeMask add_mode_mask
);
virtual void
AddOrEraseMappableButton(
int button_number,
ModeMask mode_mask
);
//-------------------------------------------------------------------
// Gauge support
//-------------------------------------------------------------------
void
*activeDestination;
Receiver
*activeReceiver;
Receiver::MessageID
activeMessageID;
Plug
*activeDependant;
private:
static ControlsManager
*headControlsManager;
ControlsManager
*nextControlsManager;
static unsigned int
nextOwnerID;
};
//#########################################################################
//############################ ControlsMapping ############################
//#########################################################################
// Used by tools for building/reading control map streams
struct ControlsMapping
{
public:
enum {
DirectMapping=0,
EventMapping=1
};
Enumeration
controlsGroup,
controlsElement,
mappingType,
subsystemID;
ModeMask
modeMask;
union
{
Simulation::AttributeID attributeID;
Receiver::MessageID messageID;
};
};
//#########################################################################
//############################ ControlsString #############################
//#########################################################################
typedef int ControlsStringID;
class ControlsString :
public Node
{
friend class ControlsStringManager;
protected:
enum
{
maxStringLength=16
};
ControlsString(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID message_id,
int user_code
);
~ControlsString();
Logical
TestInstance() const;
void
Update(int keypad_unit_number, ControlsKey new_key);
ControlsStringID
id;
const char
*matchStringPointer;
char
string[maxStringLength+1];
int
stringLength,
keypadUnitNumber,
userCode;
Receiver
*receiverPointer;
Receiver::MessageID
messageID;
static ControlsStringID
nextID;
};
//#########################################################################
//######################## ControlsStringMessage ##########################
//#########################################################################
// This is sent by the controlsString object when a match is detected
class ControlsStringMessage:
public Receiver::Message
{
public:
ControlsStringMessage(
Receiver::MessageID message_ID,
int user_code
):
Receiver::Message(message_ID, sizeof(ControlsStringMessage)),
userCode(user_code)
{}
int
userCode;
};
//#########################################################################
//######################## ControlsStringManager ##########################
//#########################################################################
// This class matches strings from a keypad. When the given string
// is matched, it sends an event to the given receiver.
class ControlsStringManager :
public Node
{
public:
ControlsStringManager();
~ControlsStringManager();
Logical
TestInstance() const;
ControlsStringID
Add(
const char *new_string,
int keypad_unit_number,
Receiver *receiver_pointer,
Receiver::MessageID id,
int user_code = 0
);
void
Remove(ControlsStringID string_id);
void
Update(int keypad_unit_number, ControlsKey new_key);
ChainOf<ControlsString*>
instanceList;
};
#endif
+303
View File
@@ -0,0 +1,303 @@
//==========================================================================//
// File: controls.tst //
// Project: MUNGA Brick: COntrols module //
// Contents: Test code for vector classes //
//--------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ----------------------------------------------------------//
// 12/12/94 CPB Initial coding. //
//--------------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//==========================================================================//
#include <controls.thp>
#pragma initialize 34
//
//###########################################################################
//###########################################################################
//
TestControlsManager::TestControlsManager()
: ControlsManager()
{
}
//
//###########################################################################
//###########################################################################
//
TestControlsManager::~TestControlsManager()
{
}
//
//###########################################################################
//###########################################################################
//
void
TestControlsManager::Execute()
{
}
//###########################################################################
//############################# TestReceiver ################################
//###########################################################################
Derivation
TestControlsReceiver::ClassDerivations(
Receiver::ClassDerivations,"TestControlsReceiver1"
);
TestControlsReceiver::SharedData
TestControlsReceiver::DefaultData(
TestControlsReceiver::ClassDerivations,
TestControlsReceiver::MessageHandlers
);
TestControlsReceiver::TestControlsReceiver(
TestControlsReceiver::ClassID class_ID,
TestControlsReceiver::SharedData &shared_data
):
Receiver(class_ID, shared_data)
{
keyStroke = 0;
joystickValue.x = 0.0f;
joystickValue.y = 0.0f;
}
TestControlsReceiver::~TestControlsReceiver()
{
}
void
TestControlsReceiver::KeyboardMessageHandler(
ReceiverDataMessageOf<int> *message
)
{
keyStroke = message->dataContents;
}
void
TestControlsReceiver::JoystickMessageHandler(
ReceiverDataMessageOf<Vector2DOf<Scalar> > *message
)
{
joystickValue = message->dataContents;
}
const Receiver::HandlerEntry
TestControlsReceiver::MessageHandlerEntries[]=
{
{
TestControlsReceiver::KeyboardMessageID,
"Keyboard",
(Receiver::Handler)&TestControlsReceiver::KeyboardMessageHandler
},
{
TestControlsReceiver::JoystickMessageID,
"Joystick",
(Receiver::Handler)&TestControlsReceiver::JoystickMessageHandler
}
};
Receiver::MessageHandlerSet
TestControlsReceiver::MessageHandlers(
ELEMENTS(TestControlsReceiver::MessageHandlerEntries),
TestControlsReceiver::MessageHandlerEntries,
Receiver::MessageHandlers
);
//
//###########################################################################
//###########################################################################
//
Logical
ControlsManager::TestClass()
{
#if 0
Test_Message("Starting ControlsManager test...\n");
unsigned int fakeOwnerID(1);
Vector2DOf<Scalar> vector1(0.0f, 0.0f);
Vector2DOf<Scalar> vector2(1.0f, 2.0f);
Vector2DOf<Scalar> vector3(3.0f, 4.0f);
//
//--------------------------------------------------------
// Test ControlsInstanceDirectOf...
//--------------------------------------------------------
//
{
ControlsInstanceDirectOf< Vector2DOf<Scalar> > *instance1;
instance1 = new ControlsInstanceDirectOf< Vector2DOf<Scalar> >(
fakeOwnerID,&vector1
);
Check(instance1);
Register_Object(instance1);
instance1->Update(&vector2);
Test(vector1 == vector2);
Unregister_Object(instance1);
delete instance1;
}
//
//--------------------------------------------------------
// Test ControlsMappingGroup
//--------------------------------------------------------
//
{
ControlsMappingGroup testGroup;
Check(&testGroup);
ControlsInstanceDirectOf< Vector2DOf<Scalar> > *instance1;
instance1 = new ControlsInstanceDirectOf< Vector2DOf<Scalar> >(
fakeOwnerID,
&vector1
);
Check(instance1);
Register_Object(instance1);
ControlsInstanceDirectOf< Vector2DOf<Scalar> > *instance2;
instance2 = new ControlsInstanceDirectOf< Vector2DOf<Scalar> > (
fakeOwnerID,
&vector2
);
Check(instance2);
Register_Object(instance2);
testGroup.Add(instance1);
testGroup.Add(instance2);
ChainIteratorOf<ControlsInstance>
i(testGroup.instanceList);
ControlsInstance
*controls_instance;
while ((controls_instance=i.ReadAndNext()) != NULL)
{
Check(controls_instance);
}
testGroup.Update(&vector3);
Test(vector1 == vector3);
Test(vector2 == vector3);
Unregister_Object(instance2);
delete instance2;
Unregister_Object(instance1);
delete instance1;
}
//
//--------------------------------------------------------
// Create Receiver
//--------------------------------------------------------
//
TestControlsReceiver *my_receiver;
my_receiver = new TestControlsReceiver();
Check(my_receiver);
Register_Object(my_receiver);
//
//--------------------------------------------------------
// Test ControlsInstanceEventOf...
//--------------------------------------------------------
//
{
int q0, q1;
int testKey = 0;
ControlsInstanceEventOf< int > *instance1;
instance1 = new ControlsInstanceEventOf< int > (
fakeOwnerID,
my_receiver,
TestControlsReceiver::KeyboardMessageID
);
Check(instance1);
Register_Object(instance1);
ControlsInstanceDirectOf< int > *instance2;
instance2 = new ControlsInstanceDirectOf< int > (
fakeOwnerID,
&testKey
);
Check(instance2);
Register_Object(instance2);
Test(my_receiver->keyStroke == 0);
q0 = 1;
instance1->Update(&q0);
application->ProcessAllEvents(); // process posted events
Test(my_receiver->keyStroke == q0);
//
//--------------------------------------------------------
// Test ControlsMappingGroup, again
//--------------------------------------------------------
//
ControlsMappingGroup testGroup;
Check(&testGroup);
testGroup.Add(instance1);
testGroup.Add(instance2);
q1=2;
testGroup.Update(&q1);
application->ProcessAllEvents(); // process posted events
Test(my_receiver->keyStroke == q1);
Test(testKey == q1);
Unregister_Object(instance2);
delete instance2;
Unregister_Object(instance1);
delete instance1;
}
//
//--------------------------------------------------------
// Test ControlsUpdateManager
//--------------------------------------------------------
//
{
ControlsUpdateManager<int> intGroup;
int source = 1;
int dest1 = 0;
int dest2 = 0;
intGroup.Add(0,&dest1);
intGroup.Add(0,&dest2);
intGroup.ForceUpdate(&source);
Test(dest1 == source);
Test(dest2 == source);
intGroup.Remove(0);
dest1 = 0;
dest2 = 0;
intGroup.ForceUpdate(&source);
Test(dest1 == 0);
Test(dest2 == 0);
}
//
//--------------------------------------------------------
// Destroy Receiver
//--------------------------------------------------------
//
Unregister_Object(my_receiver);
delete my_receiver;
//
//--------------------------------------------------------
// Return test result
//--------------------------------------------------------
//
#endif
return True;
}
+88
View File
@@ -0,0 +1,88 @@
//===========================================================================//
// File: controls.thh //
// Project: MUNGA Brick: Controls Module //
// Contents: Interface specification for Controls module //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- -----------------------------------------------------------//
// 12/12/94 CPB Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved //
// PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(CONTROLS_THH)
# define CONTROLS_THH
//#########################################################################
//########################## TestControlsManager ##########################
//#########################################################################
class TestControlsManager:
public ControlsManager
{
public:
TestControlsManager();
~TestControlsManager();
void
Execute();
};
//#########################################################################
//############################# TestReceiver ##############################
//#########################################################################
class TestControlsReceiver:
public Receiver
{
//#########################################################################
// Shared Data Support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//#########################################################################
// Construction and Destruction Support
//
public:
TestControlsReceiver(
ClassID class_ID=TrivialReceiverClassID,
SharedData &shared_data=DefaultData
);
~TestControlsReceiver();
//##########################################################################
// Messaging Support
//
public:
enum {
KeyboardMessageID=Receiver::NextMessageID,
JoystickMessageID,
NextMessageID
};
protected:
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
void KeyboardMessageHandler(ReceiverDataMessageOf<int> *);
void JoystickMessageHandler(ReceiverDataMessageOf<Vector2DOf<Scalar> > *);
//##########################################################################
// Test Support
//
public:
int
keyStroke;
Vector2DOf<Scalar>
joystickValue;
};
#endif
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
#define TEST_STRING "Test String"
#define TEST_STRING_2 "Test StringTest String"
#define TEST_STRING_3 "Test StringZ"
Logical
CString::TestClass()
{
#if 1
CString string_a;
//Verify(string_a.stringSize == 0);
//Verify(string_a.stringLength == 0);
//Verify(string_a.stringText == NULL);
CString string_b(TEST_STRING);
CString string_c(string_b);
Verify(string_b.Length() == strlen(TEST_STRING));
Verify(string_b.Length() == strlen(string_c));
Verify(string_b == string_c);
CString string_d(TEST_STRING_2);
CString string_e;
string_e = string_b + string_c;
Verify(string_e == string_d);
CString string_f(TEST_STRING_3);
CString string_g;
string_g = string_b + 'Z';
Verify(string_g == string_f);
CString string_h(TEST_STRING);
string_h += string_b;
Verify(string_h == string_d);
CString string_i(TEST_STRING);
string_i += 'Z';
Verify(string_i == string_f);
CString string_j("aaa");
CString string_k("aab");
CString string_l("abb");
CString string_m("bbb");
CString string_n("aaa");
Verify(string_j < string_k);
Verify(string_l > string_k);
Verify(string_l <= string_m);
Verify(string_m >= string_j);
Verify(string_j == string_n);
Verify(string_j != string_k);
Verify(string_k[0] == 'a');
Verify(string_k[1] == 'a');
Verify(string_k[2] == 'b');
CString string_o("0.1,0.2,0.3");
CString string_p("0.1 0.2 0.3");
CString string_q("0.1");
CString string_r("0.2");
CString string_s("0.3");
Verify(string_o.GetNthToken(0) == string_q);
Verify(string_o.GetNthToken(1) == string_r);
Verify(string_o.GetNthToken(2) == string_s);
Verify(string_p.GetNthToken(0) == string_q);
Verify(string_p.GetNthToken(1) == string_r);
Verify(string_p.GetNthToken(2) == string_s);
#endif
return True;
}
+388
View File
@@ -0,0 +1,388 @@
//===========================================================================//
// File: cultural.hh //
// Project: MUNGA Brick: Model Manager //
// Contents: Interface specification for Cultural Icon Class //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 12/11/95 JM Initial coding. //
// 01/10/96 JM Added Landmark Terrain //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined (CULTURAL_HPP)
# define CULTURAL_HPP
#if !defined(TERRAIN_HPP)
# include<terrain.hpp>
#endif
#if !defined(MEMSTRM_HPP)
# include<memstrm.hpp>
#endif
#if !defined(RESOURCE_HPP)
# include<resource.hpp>
#endif
#if !defined(NOTATION_HPP)
# include<notation.hpp>
#endif
#if !defined(TEAM_HPP)
# include<team.hpp>
#endif
class ScenarioRole;
//##########################################################################
//################## CulturalIcon::ModelResource #######################
//##########################################################################
struct CulturalIcon__ModelResource
{
Scalar
destroyedYTranslation;
Scalar
timeDelay;
ResourceDescription::ResourceID
explosionResourceID;
ResourceDescription::ResourceID
crunchExplosionResourceID;
Logical
sinkCollisionVolume, stoppingCollisionVolume;
};
//##########################################################################
//##################### Class CulturalIcon ##########################
//##########################################################################
class CulturalIcon :
public UnscalableTerrain
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
private:
static const HandlerEntry MessageHandlerEntries[];
protected:
static MessageHandlerSet MessageHandlers;
public:
enum {
SetBurningStateMessageID = UnscalableTerrain::NextMessageID,
NextMessageID
};
void
TakeDamageMessageHandler(TakeDamageMessage *damage_message);
void
SetBurningStateMessageHandler(Message *burning_message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Collision Volume Support
//
protected:
void
UpdateCollisionVolumes();
enum {
RemoveCollisionVolumeOnDeathBit = UnscalableTerrain::NextBit,
StoppingCollisionVolumeBit,
NextBit
};
enum {
RemoveCollisionVolumeOnDeathFlag = 1 << RemoveCollisionVolumeOnDeathBit,
StoppingCollisionVolumeFlag = 1 << StoppingCollisionVolumeBit
};
void
SetRemoveCollisionVolumeFlag()
{Check(this); simulationFlags |= RemoveCollisionVolumeOnDeathFlag;}
Logical
RemoveCollisionVolumeOnDeath() const
{Check(this); return (simulationFlags&RemoveCollisionVolumeOnDeathFlag);}
void
SetStoppingCollisionVolumeFlag()
{Check(this); simulationFlags |= StoppingCollisionVolumeFlag; }
ResourceDescription::ResourceID
explosionResourceID;
ResourceDescription::ResourceID
crunchExplosionResourceID;
Scalar
destroyedYTranslation;
Scalar
timeDelay;
public:
Logical
IsStoppingCollisionVolume() const
{Check(this); return (simulationFlags&StoppingCollisionVolumeFlag);}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
enum {
TeamNameAttributeID = UnscalableTerrain::NextAttributeID,
NextAttributeID
};
enum {
BurningState = UnscalableTerrain::StateCount,
WaitingToBurn,
StateCount
};
char
teamName[64];
private:
static const IndexEntry AttributePointers[];
protected:
static AttributeIndexSet AttributeIndex;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
typedef CulturalIcon__ModelResource ModelResource;
CulturalIcon(
MakeMessage *creation_message,
SharedData &shared_data = DefaultData
);
~CulturalIcon();
void
ReadUpdateRecord(Simulation::UpdateRecord *message);
Logical
TestInstance() const;
static Logical
CreateMakeMessage (
MakeMessage *creation_message,
NotationFile *model_file,
const ResourceDirectories *directories
);
static CulturalIcon*
Make(MakeMessage *creation_message);
static int
CreateModelResource (
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories *directories,
ModelResource* model = NULL
);
static int
CreateDamageZoneStream (
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories *directories
);
};
//##########################################################################
//################## Landmark::MakeMessage #############################
//##########################################################################
class Landmark__MakeMessage :
public CulturalIcon::MakeMessage
{
public:
int
landmarkID;
char
roleName[64];
char
landmarkName[64];
char
teamName[64];
Landmark__MakeMessage();
Landmark__MakeMessage(
Receiver::MessageID message_ID,
size_t length,
const EntityID &entity_ID,
Entity::ClassID class_ID,
ResourceDescription::ResourceID resource_ID,
LWord instance_flags,
const Origin &origin,
char *team_name,
int landmark_ID,
CString role_name
) :
CulturalIcon::MakeMessage(
message_ID,
length,
entity_ID,
class_ID,
EntityID::Null,
resource_ID,
instance_flags,
origin
),
landmarkID(landmark_ID)
{
Str_Copy(teamName, team_name, sizeof(teamName));
Str_Copy(roleName, (const char*)role_name, sizeof(roleName));
}
};
//##########################################################################
//################## Landmark::ModelResource #######################
//##########################################################################
struct Landmark__ModelResource :
public CulturalIcon::ModelResource
{
#if 0
ResourceDescription::ResourceID
roleResourceID;
#endif
};
//##########################################################################
//##################### Class Landmark ##########################
//##########################################################################
class Landmark :
public CulturalIcon
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
private:
static const HandlerEntry MessageHandlerEntries[];
protected:
static MessageHandlerSet MessageHandlers;
public:
void
TakeDamageMessageHandler(TakeDamageMessage *damage_message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Data support
//
protected:
ScenarioRole
*scenarioRole;
int
landmarkID;
Team
*owningTeam;
char
teamName[64];
public:
const ScenarioRole*
GetScenarioRole() const
{Check(this); return scenarioRole; }
void
SetScenarioRole(ScenarioRole *scenario_role)
{ Check(this); scenarioRole = scenario_role; }
int
GetLandmarkID() const
{Check(this); return landmarkID; }
Team*
GetOwningTeam()
{Check(this); return owningTeam; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor / Destructor support
//
public:
typedef Landmark__MakeMessage MakeMessage;
typedef Landmark__ModelResource ModelResource;
Landmark(
MakeMessage *creation_message,
SharedData &shared_data = DefaultData
);
~Landmark();
Logical
TestInstance() const;
static Logical
CreateMakeMessage (
MakeMessage *creation_message,
NotationFile *model_file,
const ResourceDirectories *directories
);
static Landmark*
Make(MakeMessage *creation_message);
static int
CreateModelResource (
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories *directories,
ModelResource* model = NULL
);
};
#endif
+834
View File
@@ -0,0 +1,834 @@
//===========================================================================//
// File: damage.cpp //
// Project: MUNGA Brick: Entity Manager //
// Contents: Damage Details //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/01/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(SEGMENT_HPP)
# include <segment.hpp>
#endif
#if !defined(EXPTBL_HPP)
# include <exptbl.hpp>
#endif
#if !defined(FILEUTIL_HPP)
# include <fileutil.hpp>
#endif
#if !defined(JMOVER_HPP)
# include <jmover.hpp>
#endif
#if !defined(SCHAIN_HPP)
# include <schain.hpp>
#endif
#if !defined(NOTATION_HPP)
# include <notation.hpp>
#endif
#if !defined(NAMELIST_HPP)
# include <namelist.hpp>
#endif
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MaterialList::MaterialList() :
materialList(NULL)
{
listIterator = new CStringSocketIterator(materialList);
Register_Object(listIterator);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MaterialList::~MaterialList()
{
DeletePlugs();
Unregister_Object(listIterator);
delete listIterator;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Damage::Damage()
{
damageAmount = 0.0f;
damageForce = Vector3D::Identity;
surfaceNormal.x = 0.0f;
surfaceNormal.y = 1.0f;
surfaceNormal.z = 0.0f;
impactPoint = Point3D::Identity;
burstCount = 1.0f;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
EntitySegment*
DamageZone::GetCurrentEffectSite(Enumeration effect_site_type)
{
Check(this);
EntitySegment *return_segment;
switch(effect_site_type)
{
Return_Default_Effect:
case DefaultEffectSite:
default:
{
SChainIteratorOf<EntitySegment*> iterator(defaultEffectSiteChain);
Check(iterator.GetCurrent());
return iterator.GetCurrent();
}
case InternalVideoEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(internalVideoEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case ExternalVideoEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(externalVideoEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case InternalAudioEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(internalAudioEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
case ExternalAudioEffectSite:
{
SChainIteratorOf<EntitySegment*> iterator(externalAudioEffectSiteChain);
return_segment = iterator.GetCurrent();
if (return_segment)
{
Check(return_segment);
return return_segment;
}
else
{
goto Return_Default_Effect;
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::Reset(Logical )
{
SetDamageZoneState(DefaultState);
damageZoneGraphicState.SetState(ExistsGraphicState);
damageLevel = 0.0f;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::WriteUpdateRecord(UpdateRecord *update_record)
{
Check(this);
Check_Pointer(update_record);
update_record->damageLevel = damageLevel;
update_record->damageZoneState = damageZoneState.GetState();
update_record->damageZoneGraphicState = damageZoneGraphicState.GetState();
update_record->damageZoneIndex = damageZoneIndex;
update_record->changedFlags = changedFlags;
update_record->recordLength = sizeof(*update_record);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Clear Flags here for MasterInstance DamageZones!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResetChangedFlags();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::ReadUpdateRecord(UpdateRecord *update_record)
{
Check(this);
Check_Pointer(update_record);
Verify(damageZoneIndex == update_record->damageZoneIndex);
damageLevel = update_record->damageLevel;
damageZoneState.SetState(update_record->damageZoneState);
damageZoneGraphicState.SetState(update_record->damageZoneGraphicState);
changedFlags = update_record->changedFlags;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::DamageZone(Simulation *owner, int damage_zone_index) :
Node(DamageZoneClassID),
materialTable(NULL, False),
damageZoneState(DamageStateCount),
damageZoneGraphicState(GraphicStateCount),
defaultEffectSiteChain(NULL),
internalVideoEffectSiteChain(NULL),
externalVideoEffectSiteChain(NULL),
internalAudioEffectSiteChain(NULL),
externalAudioEffectSiteChain(NULL)
{
Check(owner);
damageZoneIndex = damage_zone_index;
owningSimulation = owner;
damageLevel = 0.0f;
explosionTable = NULL;
for(int ii=0;ii<Damage::DamageTypeCount;ii++)
{
damageScale[ii] = 0.0f;
}
damageZoneName = "TrivialDamageZone_Name";
changedFlags = 0;
Reset();
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::DamageZone(
Simulation *owning_simulation,
int damage_zone_index,
MemoryStream *stream
) :
Node(DamageZoneClassID),
materialTable(NULL, False),
damageZoneState(DamageStateCount),
damageZoneGraphicState(GraphicStateCount),
defaultEffectSiteChain(NULL),
internalVideoEffectSiteChain(NULL),
externalVideoEffectSiteChain(NULL),
internalAudioEffectSiteChain(NULL),
externalAudioEffectSiteChain(NULL)
{
Check(owning_simulation);
Check(stream);
owningSimulation = owning_simulation;
damageZoneIndex = damage_zone_index;
damageLevel = 0.0f;
explosionTable = NULL;
Reset();
*stream >> damageZoneName;
if (owningSimulation->IsDerivedFrom(JointedMover::ClassDerivations))
{
JointedMover *jointed_mover = Cast_Object(
JointedMover*,
owningSimulation
);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~
// Read in all Effect Sites
//~~~~~~~~~~~~~~~~~~~~~~~~~
//
int effect_site_count;
int effect_site_index;
EntitySegment *effect_site_segment;
//
//~~~~~~~~~~~~~~~~~~~~~~~
// Read in External Video
//~~~~~~~~~~~~~~~~~~~~~~~
//
for (int jj=0;jj<EffectSiteCount;++jj)
{
*stream >> effect_site_count;
for(int ii=0;ii<effect_site_count;++ii)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the Site Segment From the Index
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*stream >> effect_site_index;
effect_site_segment = jointed_mover->GetSegment(effect_site_index);
Check(effect_site_segment);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Add the Segment to the Appropriate Chain
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
switch (jj)
{
case DefaultEffectSite:
defaultEffectSiteChain.Add(effect_site_segment);
break;
case ExternalVideoEffectSite :
externalVideoEffectSiteChain.Add(effect_site_segment);
break;
case InternalVideoEffectSite :
internalVideoEffectSiteChain.Add(effect_site_segment);
break;
case ExternalAudioEffectSite :
externalAudioEffectSiteChain.Add(effect_site_segment);
break;
case InternalAudioEffectSite :
internalAudioEffectSiteChain.Add(effect_site_segment);
break;
}
}
}
}
else
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read in these for consistancy
// and for later improvements for
// not Jointed Mover Objects!
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int filler_int;
for (int jj=0;jj<EffectSiteCount;++jj)
{
*stream >> filler_int;
}
}
*stream >> defaultArmorPoints;
int ii;
for (ii=0; ii<Damage::DamageTypeCount; ii++)
{
*stream >> damageScale[ii];
}
int skeleton_count;
EntitySegment::SkeletonType skl_type;
*stream >> skeleton_count;
for(ii=0;ii<skeleton_count;++ii)
{
*stream >> skl_type;
int material_count;
*stream >> material_count;
if(!material_count)
{
continue;
}
MaterialList *material_list = new MaterialList;
Register_Object(material_list);
for(int jj=0;jj<material_count;++jj)
{
CString new_material;
*stream >> new_material;
MaterialList::CStringPlug *new_plug =
new MaterialList::CStringPlug(new_material);
Register_Object(new_plug);
material_list->Add(new_plug);
}
material_list->First();
materialTable.AddValue(material_list, skl_type);
}
changedFlags = 0;
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DamageZone::~DamageZone()
{
MaterialTableIterator iterator(materialTable);
iterator.DeletePlugs();
if (explosionTable)
{
Unregister_Object(explosionTable);
delete explosionTable;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ExplosionTable*
DamageZone::CreateExplosionTable(MemoryStream *explosion_stream)
{
Check(this);
explosionTable = new ExplosionTable(explosion_stream);
Register_Object(explosionTable);
Check_Fpu();
return explosionTable;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
DamageZone::TakeDamage(Damage &damage)
{
Check(this);
Check_Pointer(&damage);
damageLevel += damage.damageAmount * damageScale[damage.damageType];
Clamp(damageLevel, 0.0f, 1.0f);
SetDamageLevelChangedFlag();
if (damageLevel >= 1.0f)
{
SetDamageZoneState(BurningState);
SetGraphicState(DestroyedGraphicState);
SetGraphicStateChangedFlag();
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
DamageZone::TestInstance() const
{
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
DamageZone::CreateStreamedDamageZone(
NotationFile *model_file,
const char *,
NotationFile *skl_file,
CString damage_zone_name,
MemoryStream *damage_zone_stream,
NotationFile *dmg_file,
const ResourceDirectories *directories
)
{
Check_Pointer(damage_zone_name);
Check_Pointer(&damage_zone_stream);
Check_Pointer(directories);
Check(dmg_file);
*damage_zone_stream << damage_zone_name;
//
// Find dzone name in .dmg file
//
if(!dmg_file->PageExists(damage_zone_name))
{
cerr << damage_zone_name <<" listed in .skl, does not exist in .dmg file"<<endl;
Check_Fpu();
return -1;
}
if (skl_file)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Read and Write All The Effect Sites
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"DefaultEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"ExternalVideoEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"InternalVideoEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"ExternalAudioEffectSiteName"
);
WriteEffectSegmentIndicies(
damage_zone_stream,
damage_zone_name,
dmg_file,
skl_file,
"InternalAudioEffectSiteName"
);
}
else
{
int zero_int(0);
for(int ii=0;ii<EffectSiteCount;++ii)
{
*damage_zone_stream << zero_int;
}
}
Scalar default_points;
if(!dmg_file->GetEntry(
damage_zone_name,
"WeaponDamagePoints",
&default_points
)
)
{
cerr<<damage_zone_name<<" Must have a WeaponDamagePoints"<<endl;
return False;
}
if (!default_points)
{
cerr<<"DefaultDamagePoints must have a non-zero value !"<<endl;
Check_Fpu();
return False;
}
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write default armor values
//~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << default_points;
//
// Read the damage Points values
//
float point_data;
Scalar modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"CollisionDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
if (point_data == 0.0f)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
Check_Fpu();
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"BallisticDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"ExplosiveDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"LaserDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
if(!dmg_file->GetEntry(
damage_zone_name,
"EnergyDamagePoints",
&point_data
)
)
{
modified_armor = 1.0f/default_points;
}
else
{
modified_armor = 1.0f/point_data;
}
*damage_zone_stream << modified_armor;
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get dzm filename
//~~~~~~~~~~~~~~~~~~~~~~~~~~
//
NameList *dzm_namelist = model_file->MakeEntryList("video","dzm");
if(!dzm_namelist)
{
int zero_scalar(0.0f);
*damage_zone_stream << zero_scalar;
return True;
}
Register_Object(dzm_namelist);
int dzm_filecount;
dzm_filecount = dzm_namelist->EntryCount();
*damage_zone_stream << dzm_filecount;
if(dzm_filecount)
{
NameList::Entry *dzm_fileentry = dzm_namelist->GetFirstEntry();
while(dzm_fileentry)
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// write out the skeleton type of the material
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//
CString dzm_entry_name;
dzm_entry_name = dzm_fileentry->GetName();
EntitySegment::SkeletonType skeleton_type;
if (! dzm_entry_name.Compare("dzm") )
{
skeleton_type = EntitySegment::SkeletonType_N;
}
else if (! dzm_entry_name.Compare("dzms") )
{
skeleton_type = EntitySegment::SkeletonType_S;
}
else if (! dzm_entry_name.Compare("dzmt") )
{
skeleton_type = EntitySegment::SkeletonType_T;
}
else if (! dzm_entry_name.Compare("dzmo") )
{
skeleton_type = EntitySegment::SkeletonType_O;
}
else if (! dzm_entry_name.Compare("dzma") )
{
skeleton_type = EntitySegment::SkeletonType_A;
}
else if (! dzm_entry_name.Compare("dzmb") )
{
skeleton_type = EntitySegment::SkeletonType_B;
}
else if (! dzm_entry_name.Compare("dzmc") )
{
skeleton_type = EntitySegment::SkeletonType_C;
}
else if (! dzm_entry_name.Compare("dzmd") )
{
skeleton_type = EntitySegment::SkeletonType_D;
}
*damage_zone_stream << skeleton_type;
//
// Get the name of the dzm File
//
char *filename = MakePathedFilename(
directories->videoDirectory,
dzm_fileentry->GetChar()
);
Register_Pointer(filename);
//
// Create a Notation file from the dzm ASCII File
//
NotationFile *dzm_file = new NotationFile(filename);
Register_Object(dzm_file);
NameList *material_list;
material_list = dzm_file->MakeEntryList(damage_zone_name, "material");
int entry_count(0);
if(material_list)
{
Register_Object(material_list);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write out how many materials
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
entry_count = material_list->EntryCount();
*damage_zone_stream << entry_count;
if(entry_count)
{
NameList::Entry *dzm_entry;
dzm_entry = material_list->GetFirstEntry();
Check(dzm_entry);
CString material_name;
while(dzm_entry)
{
material_name = dzm_entry->GetChar();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write out the material name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << material_name;
dzm_entry = dzm_entry->GetNextEntry();
}
}
Unregister_Object(material_list);
delete material_list;
}
else
{
*damage_zone_stream << entry_count;
}
dzm_fileentry = dzm_fileentry->GetNextEntry();
Unregister_Pointer(filename);
delete filename;
Unregister_Object(dzm_file);
delete dzm_file;
}
}
Unregister_Object(dzm_namelist);
delete dzm_namelist;
Check_Fpu();
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
DamageZone::WriteEffectSegmentIndicies(
MemoryStream *damage_zone_stream,
const char *damage_zone_name,
NotationFile *dmg_file,
NotationFile *skl_file,
const char *effect_type
)
{
Check(dmg_file);
Check(skl_file);
Check_Pointer(damage_zone_name);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Make an Entry list for this type of effect Site
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int effect_count(0);
NameList::Entry *effect_entry;
NameList *effect_namelist = dmg_file->MakeEntryList(damage_zone_name, effect_type);
if (!effect_namelist)
{
//
//~~~~~~~~~~~
// No Entries
//~~~~~~~~~~~
//
*damage_zone_stream << effect_count;
Check_Fpu();
return 1;
}
else
{
Register_Object(effect_namelist);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~
// Write Out number of sites
//~~~~~~~~~~~~~~~~~~~~~~~~~~
//
effect_count = effect_namelist->EntryCount();
*damage_zone_stream << effect_count;
effect_entry = effect_namelist->GetFirstEntry();
CString site_page_name;
int effect_site_index;
while(effect_entry)
{
site_page_name = effect_entry->GetChar();
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get SegmentIndex for this effect site Name
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
effect_site_index =
JointedMover::GetSegmentIndex(site_page_name, skl_file);
if (effect_site_index == -1)
{
cerr<<site_page_name<<" not found in skl file !"<<endl;
Unregister_Object(effect_namelist);
delete effect_namelist;
return -1;
}
//
//~~~~~~~~~~~~~~~~~~~~
// Write Out the Index
//~~~~~~~~~~~~~~~~~~~~
//
*damage_zone_stream << effect_site_index;
effect_entry = effect_entry->GetNextEntry();
}
Unregister_Object(effect_namelist);
delete effect_namelist;
}
Check_Fpu();
return 1;
}
+428
View File
@@ -0,0 +1,428 @@
//===========================================================================//
// File: damage.hpp //
// Project: MUNGA Brick: Entity Manager //
// Contents: Damage Definitions //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 05/01/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(DAMAGE_HPP)
# define DAMAGE_HPP
# if !defined(POINT3D_HPP)
# include <point3d.hpp>
# endif
# if !defined(NODE_HPP)
# include <node.hpp>
# endif
# if !defined(NORMAL_HPP)
# include <normal.hpp>
# endif
# if !defined(CSTR_HPP)
# include <cstr.hpp>
# endif
# if !defined(TABLE_HPP)
# include <table.hpp>
# endif
# if !defined(SCHAIN_HPP)
# include <schain.hpp>
# endif
# if !defined(SIMULATE_HPP)
# include <simulate.hpp>
# endif
class MaterialList;
class EntitySegment;
class ExplosionTable;
class Simulation;
class MemoryStream;
class NotationFile;
class ResourceDirectories;
class Entity;
//##########################################################################
//########################### Damage #################################
//##########################################################################
class Damage
{
public:
enum {
CollisionDamageType,
BallisticDamageType,
ExplosiveDamageType,
LaserDamageType,
EnergyDamageType,
DamageTypeCount
};
Enumeration
damageType;
Scalar
damageAmount;
Vector3D
damageForce;
Normal
surfaceNormal;
// impact point should be in the global coordinate space.
Point3D
impactPoint;
//
// burst count should be thought of as number of times
// to apply the damage.
//
int
burstCount;
Damage();
};
//##########################################################################
//######################### MaterialList #############################
//##########################################################################
class MaterialList :
public Plug
{
public:
typedef PlugOf<CString> CStringPlug;
typedef SChainOf<CStringPlug*>
CStringSocket;
typedef SChainIteratorOf<CStringPlug*>
CStringSocketIterator;
protected:
CStringSocketIterator*
listIterator;
CStringSocket
materialList;
public:
MaterialList();
~MaterialList();
void
DeletePlugs()
{Check(this); listIterator->DeletePlugs();}
void
Add(CStringPlug *new_plug)
{Check(this); materialList.Add(new_plug);}
void
First()
{ Check(this);listIterator->First();}
void
Last()
{Check(this); listIterator->Last(); }
CString*
ReadAndNext()
{
Check(this);
if (!listIterator->GetCurrent())
return NULL;
else
return listIterator->ReadAndNext()->GetPointer();
}
CString*
GetCurrent()
{
Check(this);
if (!listIterator->GetCurrent())
return NULL;
else
return listIterator->GetCurrent()->GetPointer();
}
void
Next()
{Check(this); if(listIterator->GetCurrent()) listIterator->Next();}
};
//##########################################################################
//################# DamageZone::UpdateRecord #########################
//##########################################################################
struct DamageZone__UpdateRecord
{
public:
size_t recordLength;
int damageZoneIndex;
Scalar damageLevel;
Enumeration damageZoneState;
Enumeration damageZoneGraphicState;
LWord changedFlags;
};
//##########################################################################
//######################### DamageZone ###############################
//##########################################################################
class DamageZone:
public Node
{
protected:
Simulation*
owningSimulation;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// State Support
//
private:
StateIndicator
damageZoneState;
StateIndicator
damageZoneGraphicState;
public:
enum{
ExistsGraphicState = 0,
DestroyedGraphicState,
GoneGraphicState,
GraphicStateCount
};
enum{
DefaultState = 0,
BurningState,
DamageStateCount
};
StateIndicator*
GetGraphicStatePointer()
{Check(this); return &damageZoneGraphicState;}
Enumeration
GetDamageZoneState()
{Check(this); return damageZoneState.GetState();}
void
SetDamageZoneState(Enumeration new_state)
{Check(this); damageZoneState.SetState(new_state); }
Enumeration
GetGraphicState()
{Check(this); return damageZoneGraphicState.GetState();}
virtual void
SetGraphicState(Enumeration new_state)
{
Check(this);
damageZoneGraphicState.SetState(new_state);
SetGraphicStateChangedFlag();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Flag Support
//
public:
enum {
DamageLevelChangedBit = 2,
GraphicStateChangedBit,
NextBit
};
enum {
DamageLevelChangedFlag = 1 << DamageLevelChangedBit,
GraphicStateChangedFlag = 1 << GraphicStateChangedBit
};
Logical
DamageLevelChanged() const
{Check(this); return (changedFlags & DamageLevelChangedFlag); }
Logical
GraphicStateChanged() const
{Check(this); return (changedFlags & GraphicStateChangedFlag); }
void
SetDamageLevelChangedFlag()
{Check(this); changedFlags |= DamageLevelChangedFlag; }
void
SetGraphicStateChangedFlag()
{Check(this); changedFlags |= GraphicStateChangedFlag; }
void
ResetChangedFlags()
{Check(this); changedFlags = 0; }
LWord
changedFlags;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Update Support
//
public:
typedef DamageZone__UpdateRecord UpdateRecord;
virtual void
ReadUpdateRecord(UpdateRecord *message);
virtual void
WriteUpdateRecord(UpdateRecord *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Material Support
//
public:
typedef TableOf<MaterialList*, Enumeration>
MaterialTable;
typedef TableIteratorOf<MaterialList*, Enumeration>
MaterialTableIterator;
MaterialList*
GetMaterialList(Enumeration skl_type)
{
Check(this);
return materialTable.Find(skl_type);
}
protected:
MaterialTable
materialTable;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Explosion Support
//
protected:
ExplosionTable
*explosionTable;
public:
ExplosionTable*
CreateExplosionTable(MemoryStream *explosion_stream);
ExplosionTable*
GetExplosionTable()
{Check(this); return explosionTable; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Effect Support
//
public:
SChainOf<EntitySegment*>
defaultEffectSiteChain,
internalVideoEffectSiteChain,
externalVideoEffectSiteChain,
internalAudioEffectSiteChain,
externalAudioEffectSiteChain;
enum {
DefaultEffectSite,
ExternalVideoEffectSite,
InternalVideoEffectSite,
ExternalAudioEffectSite,
InternalAudioEffectSite,
EffectSiteCount
};
EntitySegment*
GetCurrentEffectSite(Enumeration effect_site_type = DefaultEffectSite);
static
WriteEffectSegmentIndicies(
MemoryStream *damage_zone_stream,
const char *damage_zone_name,
NotationFile *dmg_file,
NotationFile *skl_file,
const char *effect_type
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Support
//
public:
Simulation*
GetOwningSimulation()
{return owningSimulation;}
int
damageZoneIndex;
Scalar
defaultArmorPoints;
Scalar
damageScale[Damage::DamageTypeCount];
Scalar
damageLevel;
CString damageZoneName;
virtual void
TakeDamage(Damage &damage);
void
Reset(Logical full_reset=True);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction / Destruction Support
//
DamageZone(
Simulation *owner,
int damage_zone_index,
MemoryStream *dzone_res
);
DamageZone(Simulation *owner, int damage_zone_index);
virtual ~DamageZone();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Resource Support
//
static Logical
CreateStreamedDamageZone(
NotationFile *model_file,
const char *model_name,
NotationFile *skl_file,
CString damage_zone_name,
MemoryStream *damage_zone_stream,
NotationFile *dmg_file,
const ResourceDirectories *directories
);
};
#endif
+141
View File
@@ -0,0 +1,141 @@
//=======================================================================//
// File: debug1on.hpp //
// Project: Architecture //
// Author: J.M. Albertson //
// 4-12-95 CPB added Str_Cat macro //
//-----------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//=======================================================================//
#if !defined(OLD_DEBUG_LEVEL)
# define OLD_DEBUG_LEVEL 1
#else
# undef OLD_DEBUG_LEVEL
# if DEBUG_LEVEL>=3
# define OLD_DEBUG_LEVEL 3
# elif DEBUG_LEVEL==1
# define OLD_DEBUG_LEVEL 1
# elif DEBUG_LEVEL==0
# define OLD_DEBUG_LEVEL 0
# endif
#endif
#undef DEBUG_LEVEL
#undef Verify
#undef Verify_And_Dump
#undef Dump
#undef Tell
#undef Warn
#undef Warn_And_Dump
#undef Check_Signature
#undef Check_Pointer
#undef Check
#undef Check_Fpu
#undef Fail
#undef Cast_Object
#undef DEBUG_CODE
#undef Mem_Copy
#undef Str_Copy
#undef Str_Cat
#undef Sqrt
#undef Arctan
#undef Arccos
#undef Arcsin
#define DEBUG_LEVEL 1
#define DEBUG_CODE(x) { x }
#define Dump(v)\
(DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << flush)
#define Verify(c)\
if (!(c)) {\
Verify_Failed(#c,__FILE__,__LINE__);\
}
#define Verify_And_Dump(c,v)\
if (!(c)) {\
DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\
Verify_Failed(#c,__FILE__,__LINE__);\
}
#define Warn(c)\
if (c) {\
DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\
}
#define Warn_And_Dump(c,v)\
if (c) {\
DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\
DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\
}
#define Tell(m)\
(DEBUG_STREAM << m << flush)
#define Check_Pointer(p) Verify(p)
#define Check_Fpu() Verify(Fpu_Ok())
#define Mem_Copy(destination, source, length, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
memcpy(destination, source, length);\
}
#define Str_Copy(destination, source, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
strcpy(destination, source);\
}
#define Str_Cat(destination, source, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
strcat(destination, source);\
}
#define Sqrt(value)\
((value>=0.0f) ? sqrt(value) : (Fail("Bad parameter to sqrt"),0.0f))
#define Arctan(y,x)\
(\
(!Small_Enough(y) || !Small_Enough(x))\
? atan2((y),(x)) :\
(Fail("Zero Arctan!"),0.0f)\
)
#define Arccos(x)\
(\
((x)>=-1.0f && (x)<=1.0f)\
? acos(x) :\
(Fail("Out of range Arccos!"),0.0f)\
)
#define Arcsin(x)\
(\
((x)>=-1.0f && (x)<=1.0f)\
? asin(x) :\
(Fail("Out of range Arcsin!"),0.0f)\
)
#define Power(x,y)\
(\
((x)<0.0f)\
? (Fail("Out of range Power!"),0.0f) :\
pow(x,y)\
)
#define Check_Signature(p) Check_Pointer(p)
#define Check(p) Check_Pointer(p)
#define Fail(m)\
Fail_To_Debugger(m,__FILE__,__LINE__)
#define Cast_Object(type, ptr) ((type)(ptr))
+185
View File
@@ -0,0 +1,185 @@
//=======================================================================//
// File: debug2on.hpp //
// Project: Architecture //
// Author: J.M. Albertson //
// 4-12-95 CPB added Str_Cat macro //
//-----------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//=======================================================================//
#if !defined(OLD_DEBUG_LEVEL)
# define OLD_DEBUG_LEVEL 2
#else
# undef OLD_DEBUG_LEVEL
# if DEBUG_LEVEL>=3
# define OLD_DEBUG_LEVEL 3
# elif DEBUG_LEVEL==1
# define OLD_DEBUG_LEVEL 1
# elif DEBUG_LEVEL==0
# define OLD_DEBUG_LEVEL 0
# endif
#endif
#undef DEBUG_LEVEL
#undef Verify
#undef Verify_And_Dump
#undef Dump
#undef Tell
#undef Warn
#undef Warn_And_Dump
#undef Check_Signature
#undef Check_Pointer
#undef Check
#undef Check_Fpu
#undef Fail
#undef Cast_Object
#undef DEBUG_CODE
#undef Mem_Copy
#undef Str_Copy
#undef Str_Cat
#undef Sqrt
#undef Arctan
#undef Arccos
#undef Arcsin
#undef Power
#define DEBUG_LEVEL 2
#define DEBUG_CODE(x) { x }
#define Dump(v)\
(DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << flush)
#define Verify(c)\
if (!(c)) {\
Verify_Failed(#c,__FILE__,__LINE__);\
}
#define Verify_And_Dump(c,v)\
if (!(c)) {\
DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\
Verify_Failed(#c,__FILE__,__LINE__);\
}
#define Warn(c)\
if (c) {\
DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\
}
#define Warn_And_Dump(c,v)\
if (c) {\
DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl;\
DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\
}
#define Tell(m)\
(DEBUG_STREAM << m << flush)
#define Check_Pointer(p) Verify(p)
#define Check_Fpu() Verify(Fpu_Ok())
#define Mem_Copy(destination, source, length, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
Verify((length) <= (available));\
Verify(abs((char*)destination - (char*)source) >= length);\
memcpy(destination, source, length);\
}
#define Str_Copy(destination, source, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
Verify((strlen(source) + 1) <= (available));\
Verify(abs(destination - source) >= (strlen(source) + 1));\
strcpy(destination, source);\
}
#define Str_Cat(destination, source, available)\
{\
Check_Pointer(destination);\
Check_Pointer(source);\
Verify((strlen(destination) + strlen(source) + 1) <= (available));\
strcat(destination, source);\
}
#define Sqrt(value)\
((value>=0.0f) ? sqrt(value) : (Fail("Bad parameter to sqrt"),0.0f))
#define Arctan(y,x)\
(\
(!Small_Enough(y) || !Small_Enough(x))\
? atan2((y),(x)) :\
(Fail("Zero Arctan!"),0.0f)\
)
#define Arccos(x)\
(\
((x)>=-1.0f && (x)<=1.0f)\
? acos(x) :\
(Fail("Out of range Arccos!"),0.0f)\
)
#define Arcsin(x)\
(\
((x)>=-1.0f && (x)<=1.0f)\
? asin(x) :\
(Fail("Out of range Arcsin!"),0.0f)\
)
#define Power(x,y)\
(\
((x)<0.0f)\
? (Fail("Out of range Power!"),0.0f) :\
pow(x,y)\
)
#if defined(USE_SIGNATURE)
# define Check_Signature(p) {\
Check_Pointer(p);\
Verify_And_Dump(!Is_Signature_Bad(p),Is_Signature_Bad(p));\
}
#else
# define Check_Signature(p) Check_Pointer(p)
#endif
#if defined(USE_SIGNATURE)
# define Check(p) {Check_Signature(p);Verify(!((LWord)p & 3));Check_Fpu();}
#else
# define Check(p) {Check_Pointer(p);Verify(!((LWord)p & 3));Check_Fpu();}
#endif
#define Fail(m)\
Fail_To_Debugger(m,__FILE__,__LINE__)
#if defined(USE_SIGNATURE)
# define Cast_Object(type, ptr) (\
(!ptr)\
? (\
Verify_Failed(#ptr,__FILE__,__LINE__),(type)NULL\
)\
: (\
(Is_Signature_Bad((type)ptr))\
? (\
Verify_Failed(\
"Is_Signature_Bad(("#type")"#ptr")",\
__FILE__,\
__LINE__\
),(type)NULL\
)\
: ((type)(ptr))\
)\
)
#else
# define Cast_Object(type, ptr) (\
(!ptr)\
? (\
Verify_Failed(#ptr,__FILE__,__LINE__),(type)NULL\
)\
: ((type)(ptr))\
)
#endif
+72
View File
@@ -0,0 +1,72 @@
//=======================================================================//
// File: debugoff.hpp //
// Project: Architecture //
// Author: J.M. Albertson //
// 4-12-95 CPB added Str_Cat macro //
//-----------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//=======================================================================//
#if !defined(OLD_DEBUG_LEVEL)
# define OLD_DEBUG_LEVEL 0
#else
# undef OLD_DEBUG_LEVEL
# if DEBUG_LEVEL>=3
# define OLD_DEBUG_LEVEL 3
# elif DEBUG_LEVEL==2
# define OLD_DEBUG_LEVEL 2
# elif DEBUG_LEVEL==1
# define OLD_DEBUG_LEVEL 1
# endif
#endif
#undef DEBUG_LEVEL
#undef Verify
#undef Verify_And_Dump
#undef Warn
#undef Warn_And_Dump
#undef Dump
#undef Tell
#undef Check_Signature
#undef Check_Pointer
#undef Mem_Copy
#undef Str_Copy
#undef Str_Cat
#undef Check
#undef Check_Fpu
#undef Fail
#undef Cast_Object
#undef DEBUG_CODE
#undef Sqrt
#undef Arctan
#undef Arccos
#undef Arcsin
#define DEBUG_LEVEL 0
#define DEBUG_CODE(x)
#define Verify(c)
#define Verify_And_Dump(c,v)
#define Warn(c)
#define Warn_And_Dump(c,v)
#define Dump(v)
#define Tell(m)
#define Check_Pointer(p)
#define Check_Fpu()
#define Mem_Copy(destination, source, length, available)\
memcpy(destination, source, length)
#define Str_Copy(destination, source, available)\
strcpy(destination, source);
#define Str_Cat(destination, source, available)\
strcat(destination, source);
#define Sqrt(value) sqrt(value)
#define Arctan(y,x) atan2(y,x)
#define Arccos(x) acos(x)
#define Arcsin(x) asin(x)
#define Power(x,y) pow(x,y)
#define Check(p)
#define Check_Signature(p)
#define Fail(m) Fail_To_Debugger(m,__FILE__,__LINE__)
#define Cast_Object(type, ptr) ((type)(ptr))
+24
View File
@@ -0,0 +1,24 @@
//=======================================================================//
// File: debug2on.hpp //
// Project: Architecture //
// Author: J.M. Albertson //
// 4-12-95 CPB added Str_Cat macro //
//-----------------------------------------------------------------------//
// Copyright (C) 1994, Virtual World Entertainments, All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//=======================================================================//
#if !defined(OLD_DEBUG_LEVEL)
# error Cannot revert to old debug level!
#else
# if OLD_DEBUG_LEVEL>=3
# include "debug3on.hpp"
# elif OLD_DEBUG_LEVEL==2
# include "debug2on.hpp"
# elif OLD_DEBUG_LEVEL==1
# include "debug1on.hpp"
# else
# include "debugoff.hpp"
# endif
#endif
+346
View File
@@ -0,0 +1,346 @@
//===========================================================================//
// File: director.cc //
// Project: Munga //
// Contents: Chooses from a Selection of Camerea's and provides information //
// to any number of cameraship's as to which player to follow //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/09/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
//
// Munga Includes
//
#include <munga.hpp>
#pragma hdrstop
#if !defined(DIRECTOR_HPP)
# include <director.hpp>
#endif
#if !defined(MISSION_HPP)
# include <mission.hpp>
#endif
#if !defined(PLAYER_HPP)
# include <player.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(HOSTMGR_HPP)
#include <hostmgr.hpp>
#endif
#if !defined(NTTMGR_HPP)
#include <nttmgr.hpp>
#endif
//#############################################################################
// Shared Data support
//
Derivation
CameraDirector::ClassDerivations(
Player::ClassDerivations,
"CameraDirector"
);
CameraDirector::SharedData
CameraDirector::DefaultData(
CameraDirector::ClassDerivations,
CameraDirector::MessageHandlers,
CameraDirector::AttributeIndex,
CameraDirector::StateCount,
(Entity::MakeHandler) CameraDirector::Make
);
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
CameraDirector::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(CameraDirector, AttachCameraShip)
};
CameraDirector::MessageHandlerSet
CameraDirector::MessageHandlers(
ELEMENTS(CameraDirector::MessageHandlerEntries),
CameraDirector::MessageHandlerEntries,
Player::MessageHandlers
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraDirector::AttachCameraShipMessageHandler(
AttachCameraShipMessage *in_message
)
{
Check(in_message);
Check(application);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the cameraship ID to attach to
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
HostManager *host = application->GetHostManager();
Check(host);
Entity *entity_ptr = host->GetEntityPointer(in_message->cameraShipID);
Check(entity_ptr);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Get the cameraShip Pointer Object
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraShip *camera_ship;
camera_ship = Cast_Object(CameraShip*, entity_ptr);
Check(this);
Check(camera_ship);
cameraShip = camera_ship;
}
//#############################################################################
// Model Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraDirector::UpdateHUD(
Scalar time_slice
)
{
Check(this);
Check(application);
//
//~~~~~~~~~~~~
// HUD Support
//~~~~~~~~~~~~
//
if (GetGoalEntity())
{
Check(GetGoalEntity());
Player *goal_player = GetGoalEntity()->GetPlayerLink();
if (goal_player)
{
Check(goal_player);
goalPlayerIndex = goal_player->playerBitmapIndex;
}
}
if (
application->GetApplicationState() == Application::StoppingMission ||
application->GetApplicationState() == Application::EndingMission
)
{
displayRankingWindow = False;
return;
}
else if (application->GetSecondsRemainingInGame() <= 30.0f)
{
displayRankingWindow = True;
}
else
{
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Check times for Ranking Window Display
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (displayRankingWindow)
{
timeDisplayed += time_slice;
if(timeDisplayed >= displayIntervalOn)
{
timeTillDisplayed = displayIntervalOff;
displayRankingWindow = False;
}
}
else
{
timeTillDisplayed -= time_slice;
if (timeTillDisplayed <= 0.0f)
{
timeDisplayed = 0.0f;
displayRankingWindow = True;
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraDirector::BeADirector(Scalar time_slice)
{
Check(this);
Player::PlayerSimulation(time_slice);
UpdateHUD(time_slice);
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Time To Cut To a new Player?
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
if (
timeLeftOnPlayer > 0.0f
&& application->GetApplicationState() == Application::RunningMission)
{
timeLeftOnPlayer -= time_slice;
return;
}
Player *top_dog = FindPlayerByRank(0);
if (top_dog)
{
Check(top_dog);
Entity *vehicle = top_dog->GetPlayerVehicle();
if (vehicle)
{
Check(vehicle);
if ((GetGoalEntity() != vehicle))
{
SetGoalEntity(vehicle);
timeLeftOnPlayer = 10.0f;
Check(cameraShip);
CameraShip::DirectionMessage direction_message(
CameraShip::DirectionMessageID,
sizeof(CameraShip::DirectionMessage),
GetGoalEntity()->GetEntityID(),
0.0f,
Point3D::Identity
);
Check(cameraShip);
cameraShip->Dispatch(&direction_message);
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
CameraDirector::CreateCameraShip(Scalar)
{
CreatePlayerVehicle(localOrigin);
PlayerLinkMessage player_link_message (
PlayerLinkMessageID,
sizeof(PlayerLinkMessage),
this->GetEntityID()
);
Check(playerVehicle);
playerVehicle->Dispatch(&player_link_message);
playerVehicle->DispatchToReplicants(&player_link_message);
SetPerformance(&CameraDirector::BeADirector);
deathCount = 0;
CameraDirector::AttachCameraShipMessage
message(
CameraDirector::AttachCameraShipMessageID,
sizeof(CameraDirector::AttachCameraShipMessage),
playerVehicle->GetEntityID()
);
Dispatch(&message);
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraDirector::CameraDirector(
CameraDirector::MakeMessage *creation_message,
CameraDirector::SharedData &virtual_data
) :
Player(creation_message, virtual_data),
goalEntity(this)
{
cameraShip = NULL;
SetValidFlag();
timeLeftOnPlayer = -1.0f;
if (GetInstance() != ReplicantInstance)
{
SetPerformance(&CameraDirector::CreateCameraShip);
}
//
//~~~~~~~~~~~~
// HUD Support
//~~~~~~~~~~~~
//
goalPlayerIndex = -1;
displayRankingWindow = False;
displayIntervalOn = 10.0f;
displayIntervalOff = 15.0f;
timeDisplayed = 0.0f;
timeTillDisplayed = displayIntervalOff;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraDirector*
CameraDirector::Make(MakeMessage *creation_message)
{
return new CameraDirector(creation_message);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CameraDirector::~CameraDirector()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Player*
CameraDirector::FindPlayerByRank(int rank_to_find)
{
Check(application);
//
//---------------------------------------
// Get all players from the entity group
//---------------------------------------
//
EntityGroup *player_group =
application->GetEntityManager()->FindGroup("Players");
if(player_group)
{
Player *leading_player;
//
//-----------------------------------------------------
// Iterate through the players find the leading player
//-----------------------------------------------------
//
ChainIteratorOf<Node*> iterator(player_group->groupMembers);
while ((leading_player = (Player*) iterator.ReadAndNext()) != NULL)
{
Check(leading_player);
if (leading_player->playerRanking == rank_to_find)
{
return leading_player;
}
}
}
return NULL;
}
Logical
CameraDirector::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
+192
View File
@@ -0,0 +1,192 @@
//===========================================================================//
// File: director.hh //
// Project: Munga //
// Contents: Chooses from a Selection of Camerea's and provides information //
// to any number of cameraship's as to which player to follow //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 08/09/95 JM Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(DIRECTOR_HPP)
# define DIRECTOR_HPP
# if !defined(STYLE_HPP)
# include <style.hpp>
# endif
# if !defined(PLAYER_HPP)
# include <player.hpp>
# endif
# if !defined(SCHAIN_HPP)
# include <schain.hpp>
# endif
# if !defined(CAMSHIP_HPP)
# include <camship.hpp>
# endif
# if !defined(GRAPH2D_HPP)
# include <graph2d.hpp>
# endif
# if !defined(SLOT_HPP)
# include <slot.hpp>
# endif
//##########################################################################
//################# CameraDirector::AttachCameraShip #################
//##########################################################################
class CameraDirector__AttachCameraShipMessage:
public Player::Message
{
public:
EntityID
cameraShipID;
CameraDirector__AttachCameraShipMessage(
Receiver::MessageID message_ID,
size_t length,
EntityID camera_ship_ID
):
Entity::Message(message_ID, length),
cameraShipID(camera_ship_ID)
{}
};
//##########################################################################
//############################# CameraDirector #############################
//##########################################################################
class CameraDirector:
public Player
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging support
//
public:
friend class CameraDirector__AttachCameraShipMessage;
enum{
AttachCameraShipMessageID = Entity::NextMessageID,
NextMessageID
};
typedef CameraDirector__AttachCameraShipMessage AttachCameraShipMessage;
void
AttachCameraShipMessageHandler(AttachCameraShipMessage *message);
protected:
static const HandlerEntry
MessageHandlerEntries[];
static MessageHandlerSet
MessageHandlers;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Simulation Support
//
public:
typedef void
(CameraDirector::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
CreateCameraShip(Scalar time_slice);
void
BeADirector(Scalar time_slice);
void
UpdateHUD(Scalar time_slice);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction Support
//
public:
CameraDirector(
MakeMessage *creation_message,
SharedData &virtual_data = DefaultData
);
static CameraDirector*
CameraDirector::Make(CameraDirector::MakeMessage *creation_message);
~CameraDirector();
Logical
TestInstance() const;
enum {
DefaultFlags = Entity::DefaultFlags | PreRunFlag | CameraShipPlayerFlag
};
static Player*
FindPlayerByRank(int rank_to_find);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Simulation Support Data & Functions
//
protected:
SlotOf<Entity*>
goalEntity;
void
SetGoalEntity(Entity *goal_entity)
{
Check(this);
goalEntity.Remove();
Check(goal_entity);
goalEntity.Add(goal_entity);
}
Entity*
GetGoalEntity()
{Check(this); return goalEntity.GetCurrent(); }
Scalar
timeLeftOnPlayer;
CameraShip
*cameraShip;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// HUD Support
//
public:
int
goalPlayerIndex;
Logical
displayRankingWindow;
Scalar
timeDisplayed,
timeTillDisplayed,
displayIntervalOn,
displayIntervalOff;
};
#endif
+566
View File
@@ -0,0 +1,566 @@
//===========================================================================//
// File: door.cc //
// Project: Red Planet //
// Contents: Door subsystem for managing door operation //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(DOOR_HPP)
# include <door.hpp>
#endif
#if !defined(FILEUTIL_HPP)
# include <fileutil.hpp>
#endif
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(DOORFRAM_HPP)
# include <doorfram.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(NOTATION_HPP)
#include <notation.hpp>
#endif
//#############################################################################
// Shared Data Support
//
Door::SharedData
Door::DefaultData(
Door::ClassDerivations,
Door::MessageHandlers,
Door::AttributeIndex,
Door::StateCount
);
Derivation
Door::ClassDerivations(
Subsystem::ClassDerivations,
"Door"
);
//#############################################################################
// Messaging Support
//
//#############################################################################
// Attribute Support
//
const Door::IndexEntry
Door::AttributePointers[]=
{
{
Door::CurrentPositionAttributeID,
"CurrentPosition",
(Simulation::AttributePointer)&Door::currentPosition
},
{
Door::VideoResourceAttributeID,
"VideoResource",
(Simulation::AttributePointer)&Door::videoResource
},
{
Door::PercentOpenAttributeID,
"PercentOpen",
(Simulation::AttributePointer)&Door::percentOpen
},
{
Door::CurrentVelocityAttributeID,
"CurrentVelocity",
(Simulation::AttributePointer)&Door::currentVelocity
}
};
Door::AttributeIndexSet
Door::AttributeIndex(
ELEMENTS(Door::AttributePointers),
Door::AttributePointers,
Subsystem::AttributeIndex
);
//#############################################################################
// Model Support
//
void
Door::ReadUpdateRecord(Simulation::UpdateRecord *message)
{
Check(this);
Check_Pointer(message);
Subsystem::ReadUpdateRecord(message);
UpdateRecord* record = (UpdateRecord*) message;
percentOpen = record->percentOpen;
switch (GetSimulationState())
{
case Opening:
case Closing:
phaseTimeRemaining = travelTime;
break;
case Opened:
case Closed:
phaseTimeRemaining = deadTime;
break;
}
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door updated to state "
// << GetSimulationState() << " @ "
// << application->GetSecondsRemainingInGame() << endl;
MoveCollisionVolume(percentOpen);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Door::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model)
{
Check(this);
Check_Pointer(record);
Subsystem::WriteUpdateRecord(record, update_model);
UpdateRecord *update = (UpdateRecord*)record;
update->percentOpen = percentOpen;
update->recordLength = sizeof(*update);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Door::SlideDoor(Scalar time_slice)
{
Check(this);
//
//------------------------------------------------------------
// Advance the clock, then branch based upon our current state
//------------------------------------------------------------
//
int new_state;
if (time_slice > 1.0f)
{
Check_Fpu();
return;
}
phaseTimeRemaining -= time_slice;
Scalar percent_open;
switch (GetSimulationState())
{
//
//------------------------------------------------------------------------
// If the door is not done opening, set its new position, otherwise branch
// to the opened state
//------------------------------------------------------------------------
//
case Opening:
Door_Opening:
new_state = Opening;
if (phaseTimeRemaining > 0.0f)
{
percent_open = 1.0f - phaseTimeRemaining/travelTime;
}
else
{
phaseTimeRemaining += deadTime;
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opened @ "
// << application->GetSecondsRemainingInGame() << endl;
goto Door_Opened;
}
currentVelocity.Subtract(
worldExtent,
GetEntity()->localOrigin.linearPosition
);
currentVelocity /= travelTime;
Check_Fpu();
break;
//
//-------------------------------------------------------------
// If the door is ready to start closing, jump to closing state
//-------------------------------------------------------------
//
case Opened:
Door_Opened:
new_state = Opened;
if (phaseTimeRemaining <= 0.0f)
{
phaseTimeRemaining += travelTime;
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closing @ "
// << application->GetSecondsRemainingInGame() << endl;
goto Door_Closing;
}
percent_open = 1.0f;
currentVelocity = Vector3D::Identity;
Check_Fpu();
break;
//
//------------------------------------------------------------------------
// If the door is not done closing, set its new position, otherwise branch
// to the closed state
//------------------------------------------------------------------------
//
case DefaultState:
phaseTimeRemaining = travelTime;
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door default @ "
// << application->GetSecondsRemainingInGame() << endl;
case Closing:
Door_Closing:
new_state = Closing;
if (phaseTimeRemaining > 0.0f)
{
percent_open = phaseTimeRemaining/travelTime;
}
else
{
phaseTimeRemaining += deadTime;
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closed @ "
// << application->GetSecondsRemainingInGame() << endl;
goto Door_Closed;
}
currentVelocity.Subtract(
GetEntity()->localOrigin.linearPosition,
worldExtent
);
currentVelocity /= travelTime;
Check_Fpu();
break;
//
//-------------------------------------------------------------
// If the door is ready to start opening, jump to opening state
//-------------------------------------------------------------
//
case Closed:
Door_Closed:
new_state = Closed;
if (phaseTimeRemaining <= 0.0f)
{
phaseTimeRemaining += travelTime;
// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opening @ "
// << application->GetSecondsRemainingInGame() << endl;
goto Door_Opening;
}
percent_open = 0.0f;
currentVelocity = Vector3D::Identity;
Check_Fpu();
break;
}
//
//-------------------------------------------------
// Move the collision volumes and set the new state
//-------------------------------------------------
//
MoveCollisionVolume(percent_open);
SetSimulationState(new_state);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
Door::MoveCollisionVolume(Scalar percent_open)
{
Check(this);
//
//---------------------------------------------------------
// If the door hasn't moved, don't bother updating anything
//---------------------------------------------------------
//
Entity *entity = GetEntity();
Check(entity);
if (
GetSimulationState() != simulationState.GetOldState()
&& entity->GetInstance() == Entity::MasterInstance
&& entity->IsDynamic()
)
{
ForceUpdate();
}
if (percent_open == percentOpen)
{
return;
}
//
//-----------------------------------
// Otherwise, lerp the local position
//-----------------------------------
//
percentOpen = percent_open;
currentPosition.Lerp(Point3D::Identity, localExtent, percentOpen);
//
//-----------------------------------------------------------
// Now, lerp the world position and set the collision volumes
//-----------------------------------------------------------
//
Point3D world;
world.Lerp(
GetEntity()->localOrigin.linearPosition,
worldExtent,
percentOpen
);
BoxedSolid* temp = collisionTemplates;
BoxedSolid* vol = collisionVolumes;
while (temp)
{
Check(temp);
Check(vol);
vol->minX = temp->minX + world.x;
vol->maxX = temp->maxX + world.x;
vol->minY = temp->minY + world.y;
vol->maxY = temp->maxY + world.y;
vol->minZ = temp->minZ + world.z;
vol->maxZ = temp->maxZ + world.z;
vol = vol->GetNextSolid();
temp = temp->GetNextSolid();
}
Verify(!vol);
Check_Fpu();
}
//#############################################################################
// Constructer/Destructor Support
//
Door::Door(
DoorFrame *entity,
int subsystem_ID,
SubsystemResource *subsystem_resource
):
Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData)
{
Check_Pointer(this);
Check(entity);
Check_Pointer(subsystem_resource);
//
// GetStream data NOTE::This must be in the same order as below!!!
//
localExtent = subsystem_resource->motionExtent;
travelTime = subsystem_resource->travelTime;
deadTime = subsystem_resource->deadTime;
//
// Initialize variables
//
phaseTimeRemaining = 0.0f;
currentPosition = Point3D::Identity;
SetPerformance(&Door::SlideDoor);
SetSimulationState(DefaultState);
collisionVolumeCount = 0;
collisionTemplates = NULL;
collisionVolumes = NULL;
percentOpen = -1.0f;
//
//-------------------------------------
// Establish the worldspace coordinates
//-------------------------------------
//
worldExtent.Multiply(localExtent, entity->localToWorld);
Origin local_origin = entity->localOrigin;
local_origin.linearPosition = Point3D::Identity;
//
//------------------------------
// Read in the collision volumes
//------------------------------
//
Check(application);
ResourceFile *res_file = application->GetResourceFile();
Check(res_file);
ResourceDescription *res =
res_file->FindResourceDescription(subsystem_resource->collisionID);
Check(res);
res->Lock();
BoxedSolidResource* box =
(BoxedSolidResource*)res->resourceAddress;
Check_Pointer(box);
collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource);
for (int i=0; i<collisionVolumeCount; ++i)
{
BoxedSolidResource world_box,local_box;
world_box.Instance(*box,entity->localOrigin);
local_box.Instance(*box,local_origin);
collisionTemplates =
BoxedSolid::MakeBoxedSolid(&local_box, this, collisionTemplates);
Register_Object(collisionTemplates);
collisionVolumes =
BoxedSolid::MakeBoxedSolid(&world_box, this, collisionVolumes);
Register_Object(collisionVolumes);
++box;
}
res->Unlock();
MoveCollisionVolume(0.0f);
Check(this);
}
Door::~Door()
{
BoxedSolid *box = collisionTemplates;
while (box)
{
BoxedSolid *next_box = box->GetNextSolid();
Unregister_Object(box);
delete box;
box = next_box;
}
box = collisionVolumes;
while (box)
{
BoxedSolid *next_box = box->GetNextSolid();
Unregister_Object(box);
delete box;
box = next_box;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CreateStreamedSubsystem
//
Logical
Door::CreateStreamedSubsystem(
NotationFile *model_file,
const char *model_name,
const char* subsystem_name,
SubsystemResource *subsystem_resource,
NotationFile *subsystem_file,
const ResourceDirectories *directories,
ResourceFile *res_file
)
{
if (
!Subsystem::CreateStreamedSubsystem(
model_file,
model_name,
subsystem_name,
subsystem_resource,
subsystem_file,
directories
)
)
{
return False;
}
subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource);
subsystem_resource->classID = RegisteredClass::DoorClassID;
//
// Get the motion Extent
//
const char *extent_data;
if(
!subsystem_file->GetEntry(
subsystem_name,
"MotionExtent",
&extent_data
)
)
{
cerr << subsystem_name << " missing MotionExtent!!\n";
return -1;
}
sscanf(
extent_data,
"%f %f %f",
&subsystem_resource->motionExtent.x,
&subsystem_resource->motionExtent.y,
&subsystem_resource->motionExtent.z
);
//
// Get the travelTime
//
if(
!subsystem_file->GetEntry(
subsystem_name,
"TravelTime",
&subsystem_resource->travelTime
)
)
{
cerr << subsystem_name << " missing TravelTime!\n";
return -1;
}
//
// Read in the Deadtime
//
if(
!subsystem_file->GetEntry(
subsystem_name,
"DeadTime",
&subsystem_resource->deadTime
)
)
{
cerr << subsystem_name << " missing DeadTime!\n";
return False;
}
const char* collision_file;
if (
!subsystem_file->GetEntry(
subsystem_name,
"Collision",
&collision_file
)
)
{
cerr << subsystem_name << " missing Collision!\n";
return False;
}
subsystem_resource->collisionID =
BoxedSolidResource::CreateBoxedSolidStream(
collision_file,
res_file,
directories
);
return True;
}
Logical
Door::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
+185
View File
@@ -0,0 +1,185 @@
//===========================================================================//
// File: door.hh //
// Project: RP //
// Contents: A terrain subsystem for management of door operation //
// //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#if !defined (DOOR_HPP)
# define DOOR_HPP
# if !defined(SUBSYSTM_HPP)
# include <subsystm.hpp>
# endif
# if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
# endif
class DoorFrame;
//##########################################################################
//##################### Door::SubsystemResource ###################
//##########################################################################
struct Door__SubsystemResource:
public Subsystem::SubsystemResource
{
Vector3D motionExtent;
Scalar
travelTime,
deadTime;
ResourceDescription::ResourceID
collisionID;
};
//##########################################################################
//##################### Chute::UpdateRecord #####################
//##########################################################################
struct Door__UpdateRecord :
public Subsystem::UpdateRecord
{
Scalar
percentOpen;
};
//##########################################################################
//######################### CLASS Door ########################
//##########################################################################
class Door :
public Subsystem
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Messaging Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data Support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support
//
public:
enum {
PercentOpenAttributeID = Subsystem::NextAttributeID,
CurrentPositionAttributeID,
VideoResourceAttributeID,
CurrentVelocityAttributeID,
NextAttributeID
};
private:
static const IndexEntry AttributePointers[];
protected:
static AttributeIndexSet AttributeIndex;
public:
Scalar percentOpen;
ResourceDescription::ResourceID videoResource;
Point3D currentPosition;
Vector3D currentVelocity;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model Support
//
public:
enum {
Opening = Subsystem::StateCount,
Opened,
Closing,
Closed,
StateCount
};
typedef void
(Door::*Performance)(Scalar time_slice);
typedef Door__UpdateRecord UpdateRecord;
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
void
SlideDoor(Scalar time_slice);
void
MoveCollisionVolume(Scalar open_percent);
BoxedSolid*
GetFirstBoxedSolid()
{Check(this); return collisionVolumes;}
protected:
void
WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model);
void
ReadUpdateRecord(Simulation::UpdateRecord *message);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
typedef Door__SubsystemResource SubsystemResource;
Door(
DoorFrame *entity,
int subsystem_ID,
SubsystemResource *subsystem_resource
);
~Door();
Logical
TestInstance() const;
static Logical
CreateStreamedSubsystem(
NotationFile *model_file,
const char *model_name,
const char *subsystem_name,
SubsystemResource *subsystem_resource,
NotationFile *subsystem_file,
const ResourceDirectories *directories,
ResourceFile *res_file
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Local Support
//
private:
Point3D
localExtent,
worldExtent;
Scalar
phaseTimeRemaining,
travelTime,
deadTime;
int collisionVolumeCount;
BoxedSolid
*collisionTemplates,
*collisionVolumes;
};
#endif
+309
View File
@@ -0,0 +1,309 @@
//===========================================================================//
// File: Doorfram.cc //
// Project: Red Planet //
// Contents: Implementation details of well head doors //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#include <munga.hpp>
#pragma hdrstop
#if !defined(BOXSOLID_HPP)
# include <boxsolid.hpp>
#endif
#if !defined(FILEUTIL_HPP)
# include <fileutil.hpp>
#endif
#if !defined(DOORFRAM_HPP)
# include <doorfram.hpp>
#endif
#if !defined(DOOR_HPP)
# include <door.hpp>
#endif
#if !defined(APP_HPP)
#include <app.hpp>
#endif
#if !defined(NOTATION_HPP)
#include <notation.hpp>
#endif
#if !defined(NAMELIST_HPP)
#include <namelist.hpp>
#endif
//#############################################################################
// Shared Data Support
//
Derivation
DoorFrame::ClassDerivations(UnscalableTerrain::ClassDerivations,"DoorFrame");
DoorFrame::SharedData
DoorFrame::DefaultData(
DoorFrame::ClassDerivations,
DoorFrame::MessageHandlers,
DoorFrame::AttributeIndex,
DoorFrame::StateCount,
(Entity::MakeHandler)DoorFrame::Make
);
//#############################################################################
// Test Support
//
Logical
DoorFrame::TestInstance() const
{
return IsDerivedFrom(ClassDerivations);
}
//#############################################################################
// Construction and Destruction
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DoorFrame::DoorFrame(
DoorFrame::MakeMessage *creation_message,
DoorFrame::SharedData &virtual_data
):
UnscalableTerrain(creation_message, virtual_data)
{
Check_Pointer(this);
Check(creation_message);
Check(&virtual_data);
SetValidFlag();
SetPerformance(&DoorFrame::DoNothing);
//
// Get the subsystem_resource from the resource file
//
Check(application);
ResourceDescription *subsystem_resource =
application->GetResourceFile()->SearchList(
resourceID,
ResourceDescription::SubsystemModelStreamResourceType
);
Check(subsystem_resource);
subsystem_resource->Lock();
Check_Pointer(subsystem_resource->resourceAddress);
MemoryStream subsystem_stream(
subsystem_resource->resourceAddress,
subsystem_resource->resourceSize);
subsystemCount = *(int*)subsystem_stream.GetPointer();
subsystem_stream.AdvancePointer(sizeof(int));
Verify(subsystemCount);
//
// Set up Subsystems
//
subsystemArray = new (Subsystem(*[subsystemCount]));
Register_Pointer(subsystemArray);
//
// Attach the doors as defined in the mod file
//
for (int ii=BasicSubsystemCount; ii<subsystemCount; ++ii)
{
Door::SubsystemResource *subsystem_resource =
(Door::SubsystemResource *)subsystem_stream.GetPointer();
subsystemArray[ii] = new Door(this, ii, subsystem_resource);
Register_Object(subsystemArray[ii]);
subsystem_stream.AdvancePointer(subsystem_resource->subsystemModelSize);
}
subsystem_resource->Unlock();
Check(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DoorFrame*
DoorFrame::Make(DoorFrame::MakeMessage *creation_message)
{
return new DoorFrame(creation_message);
}
int
DoorFrame::CreateMakeMessage(
MakeMessage *creation_message,
NotationFile *model_file,
const ResourceDirectories *directories
)
{
Check(creation_message);
Check(model_file);
if (
!UnscalableTerrain::CreateMakeMessage(
creation_message,
model_file,
directories
)
)
{
return False;
}
creation_message->classToCreate = RegisteredClass::DoorFrameClassID;
creation_message->instanceFlags =
MasterInstance|DynamicFlag|MapFlag|TrappedFlag;
return True;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
DoorFrame::~DoorFrame()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ResourceDescription::ResourceID
DoorFrame::CreateSubsystemStream(
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories *directories
)
{
Check(resource_file);
Check_Pointer(model_name);
Check(model_file);
Check_Pointer(directories);
//
//-------------------
// Find the .sub file
//-------------------
//
const char* entry_data;
if (
!model_file->GetEntry(
"gamedata",
"Subsystems",
&entry_data
)
)
{
cerr << model_name << " is missing .sub file specification!\n";
return -1;
}
char *sub_filename = MakePathedFilename(directories->modelDirectory, entry_data);
Register_Pointer(sub_filename);
NotationFile *sub_file = new NotationFile(sub_filename);
Register_Object(sub_file);
NameList *sub_namelist = sub_file->MakePageList();
Register_Object(sub_namelist);
int subsystem_count = sub_file->PageCount();
if (!subsystem_count)
{
cerr << sub_filename << " empty of missing!\n";
Dump_And_Die:
Unregister_Pointer(sub_filename);
delete sub_filename;
Unregister_Object(sub_file);
delete sub_file;
Unregister_Object(sub_namelist);
delete sub_namelist;
return -1;
}
int buf_size =
subsystem_count * sizeof(Door::SubsystemResource) + sizeof(int);
char *buffer = new char[buf_size];
Register_Pointer(buffer);
MemoryStream subsystem_stream(buffer, buf_size);
*(int*)subsystem_stream.GetPointer() = subsystem_count;
subsystem_stream.AdvancePointer(sizeof(int));
NameList::Entry *sub_entry = sub_namelist->GetFirstEntry();
while(sub_entry)
{
char subsystem_name[32];
Str_Copy(subsystem_name, sub_entry->GetName(), sizeof(subsystem_name));
const char *sub_type;
if(!sub_file->GetEntry(
subsystem_name,
"Type",
&sub_type
)
)
{
cerr << model_name << ':' << subsystem_name << " missing Type!\n";
Dump_And_Die_2:
Unregister_Pointer(buffer);
delete[] buffer;
goto Dump_And_Die;
}
Subsystem::SubsystemResource *sub_res =
(Subsystem::SubsystemResource*)subsystem_stream.GetPointer();
if (!strcmp(sub_type, "DoorClassID"))
{
if (
Door::CreateStreamedSubsystem(
model_file,
model_name,
subsystem_name,
(Door::SubsystemResource*)sub_res,
sub_file,
directories,
resource_file
) == -1
)
{
goto Dump_And_Die_2;
}
}
else
{
cerr << model_name << ':' << subsystem_name
<< " has an unknown component type of " << sub_type << endl;
goto Dump_And_Die_2;
}
subsystem_stream.AdvancePointer(sub_res->subsystemModelSize);
sub_entry = sub_entry->GetNextEntry();
}
ResourceDescription *res_desc = resource_file->
ResourceFile::AddResourceMemoryStream(
model_name,
ResourceDescription::SubsystemModelStreamResourceType,
1,
ResourceDescription::Preload,
&subsystem_stream
);
ResourceDescription::ResourceID res_id;
if(!res_desc)
{
res_id = ResourceDescription::NullResourceID;
}
else
{
res_id = res_desc->resourceID;
}
Unregister_Pointer(sub_filename);
delete sub_filename;
Unregister_Object(sub_file);
delete sub_file;
Unregister_Object(sub_namelist);
delete sub_namelist;
Unregister_Pointer(buffer);
delete[] buffer;
return res_id;
}
+90
View File
@@ -0,0 +1,90 @@
//===========================================================================//
// File: Doorfram.hh //
// Project: Red Planet //
// Contents: Interface specification for doors //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. //
// All Rights reserved worldwide //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
//===========================================================================//
#if !defined(DOORFRAM_HPP)
# define DOORFRAM_HPP
# if !defined(TERRAIN_HPP)
# include <terrain.hpp>
# endif
//##########################################################################
//############################# DoorFrame ################################
//##########################################################################
class DoorFrame:
public UnscalableTerrain
{
public:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test Instance support
//
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Model support
//
enum{
BasicSubsystemCount
};
public:
typedef void
(DoorFrame::*Performance)(Scalar time_slice);
void
SetPerformance(Performance performance)
{
Check(this);
activePerformance = (Simulation::Performance)performance;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construction and Destruction
//
public:
static Logical
CreateMakeMessage(
MakeMessage *creation_message,
NotationFile *model_file,
const ResourceDirectories *directories
);
static ResourceDescription::ResourceID
CreateSubsystemStream(
ResourceFile *resource_file,
const char *model_name,
NotationFile *model_file,
const ResourceDirectories *directories
);
static DoorFrame*
Make(MakeMessage *creation_message);
DoorFrame(
MakeMessage *creation_message,
SharedData &virtual_data = DefaultData
);
~DoorFrame();
};
#endif

Some files were not shown because too many files have changed in this diff Show More