📄 sceneobject.cc
字号:
// Polylist bounding box & sphere
Point3F min(1e10, 1e10, 1e10);
Point3F max(-1e10, -1e10, -1e10);
for (U32 i = 0; i < polyhedron.pointList.size(); i++)
{
min.setMin(polyhedron.pointList[i]);
max.setMax(polyhedron.pointList[i]);
}
info.boundingBox.min = info.boundingBox.max = Point3F(0, 0, 0);
info.boundingBox.min.setMin(vector);
info.boundingBox.max.setMax(vector);
info.boundingBox.min += min;
info.boundingBox.max += max;
info.boundingSphere.center = (info.boundingBox.min + info.boundingBox.max) * 0.5;
VectorF bv = info.boundingBox.max - info.boundingSphere.center;
info.boundingSphere.radius = bv.len();
// Extruded
sExtrudedPolyList.extrude(polyhedron, vector);
sExtrudedPolyList.setVelocity(velocity);
if (velocity.isZero())
{
sExtrudedPolyList.clearInterestNormal();
}
else
{
Point3F normVec = velocity;
normVec.normalize();
sExtrudedPolyList.setInterestNormal(normVec);
}
sExtrudedPolyList.setCollisionList(collisionList);
info.polyList = &sExtrudedPolyList;
Box3F queryBox = info.boundingBox;
// Query main database
findObjects(queryBox, mask, callback ? callback : buildCallback, &info);
sExtrudedPolyList.adjustCollisionTime();
return collisionList->count != 0;
}
void Container::cleanupSearchVectors()
{
for (U32 i = 0; i < mSearchList.size(); i++)
delete mSearchList[i];
mSearchList.clear();
mCurrSearchPos = -1;
}
static Point3F sgSortReferencePoint;
int QSORT_CALLBACK cmpSearchPointers(const void* inP1, const void* inP2)
{
SimObjectPtr<SceneObject>** p1 = (SimObjectPtr<SceneObject>**)inP1;
SimObjectPtr<SceneObject>** p2 = (SimObjectPtr<SceneObject>**)inP2;
Point3F temp;
F32 d1, d2;
if (bool(**p1))
{
(**p1)->getWorldBox().getCenter(&temp);
d1 = (temp - sgSortReferencePoint).len();
}
else
{
d1 = 0;
}
if (bool(**p2))
{
(**p2)->getWorldBox().getCenter(&temp);
d2 = (temp - sgSortReferencePoint).len();
}
else
{
d2 = 0;
}
if (d1 > d2)
return 1;
else if (d1 < d2)
return -1;
else
return 0;
}
void Container::initRadiusSearch(const Point3F& searchPoint,
const F32 searchRadius,
const U32 searchMask)
{
AssertFatal(this == &gServerContainer, "Abort. Searches only allowed on server container");
cleanupSearchVectors();
mSearchReferencePoint = searchPoint;
Box3F queryBox(searchPoint, searchPoint);
queryBox.min -= Point3F(searchRadius, searchRadius, searchRadius);
queryBox.max += Point3F(searchRadius, searchRadius, searchRadius);
SimpleQueryList queryList;
findObjects(queryBox, searchMask, SimpleQueryList::insertionCallback, &queryList);
F32 radiusSquared = searchRadius * searchRadius;
const F32* pPoint = &searchPoint.x;
for (U32 i = 0; i < queryList.mList.size(); i++)
{
const F32* bMins;
const F32* bMaxs;
bMins = &queryList.mList[i]->getWorldBox().min.x;
bMaxs = &queryList.mList[i]->getWorldBox().max.x;
F32 sum = 0;
for (U32 j = 0; j < 3; j++)
{
if (pPoint[j] < bMins[j])
sum += (pPoint[j] - bMins[j])*(pPoint[j] - bMins[j]);
else if (pPoint[j] > bMaxs[j])
sum += (pPoint[j] - bMaxs[j])*(pPoint[j] - bMaxs[j]);
}
if (sum < radiusSquared || queryList.mList[i]->isGlobalBounds())
{
mSearchList.push_back(new SimObjectPtr<SceneObject>);
*(mSearchList.last()) = queryList.mList[i];
}
}
if (mSearchList.size() != 0)
{
sgSortReferencePoint = mSearchReferencePoint;
dQsort(mSearchList.address(), mSearchList.size(),
sizeof(SimObjectPtr<SceneObject>*), cmpSearchPointers);
}
}
U32 Container::containerSearchNext()
{
AssertFatal(this == &gServerContainer, "Abort. Searches only allowed on server container");
if (mCurrSearchPos >= mSearchList.size())
return 0;
mCurrSearchPos++;
while (mCurrSearchPos < mSearchList.size() && bool(*mSearchList[mCurrSearchPos]) == false)
mCurrSearchPos++;
if (mCurrSearchPos == mSearchList.size())
return 0;
return (*mSearchList[mCurrSearchPos])->getId();
}
F32 Container::containerSearchCurrDist()
{
AssertFatal(this == &gServerContainer, "Abort. Searches only allowed on server container");
AssertFatal(mCurrSearchPos != -1, "Error, must call containerSearchNext before containerSearchCurrDist");
if (mCurrSearchPos == -1 || mCurrSearchPos >= mSearchList.size() ||
bool(*mSearchList[mCurrSearchPos]) == false)
return 0.0;
Point3F pos;
(*mSearchList[mCurrSearchPos])->getWorldBox().getCenter(&pos);
return (pos - mSearchReferencePoint).len();
}
F32 Container::containerSearchCurrRadiusDist()
{
AssertFatal(this == &gServerContainer, "Abort. Searches only allowed on server container");
AssertFatal(mCurrSearchPos != -1, "Error, must call containerSearchNext before containerSearchCurrDist");
if (mCurrSearchPos == -1 || mCurrSearchPos >= mSearchList.size() ||
bool(*mSearchList[mCurrSearchPos]) == false)
return 0.0;
Point3F pos;
(*mSearchList[mCurrSearchPos])->getWorldBox().getCenter(&pos);
F32 dist = (pos - mSearchReferencePoint).len();
F32 min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_x();
if ((*mSearchList[mCurrSearchPos])->getWorldBox().len_y() < min)
min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_y();
if ((*mSearchList[mCurrSearchPos])->getWorldBox().len_z() < min)
min = (*mSearchList[mCurrSearchPos])->getWorldBox().len_z();
dist -= min;
if (dist < 0)
dist = 0;
return dist;
}
//----------------------------------------------------------------------------
void SimpleQueryList::insertionCallback(SceneObject* obj, void *key)
{
SimpleQueryList* pList = (SimpleQueryList*)key;
pList->insertObject(obj);
}
Point3F SceneObject::getPosition() const
{
Point3F pos;
mObjToWorld.getColumn(3, &pos);
return pos;
}
Point3F SceneObject::getRenderPosition() const
{
Point3F pos;
mRenderObjToWorld.getColumn(3, &pos);
return pos;
}
void SceneObject::setPosition(const Point3F &pos)
{
MatrixF xform = mObjToWorld;
xform.setColumn(3, pos);
setTransform(xform);
}
//--------------------------------------------------------------------------
SceneObject::LightingInfo::LightingInfo()
{
mUseInfo = false;
mDirty = false;
mHasLastColor = false;
// set the colors to half white for invalid surfaces and all...
mDefaultColor.set(0.5f, 0.5f, 0.5f);
mAlarmColor.set(0.5f, 0.5f, 0.5f);
mLastColor.set(0.5f, 0.5f, 0.5f);
mLastTime = 0;
}
//--------------------------------------------------------------------------
void SceneObject::installLights()
{
// install the lights:
LightManager * lightManager = gClientSceneGraph->getLightManager();
AssertFatal(lightManager!=NULL, "SceneObject::installLights: LightManager not found");
ColorF ambientColor;
if(getLightingAmbientColor(&ambientColor))
{
switch(mLightingInfo.mLightSource)
{
case LightingInfo::Interior:
{
// ambient/directional contributions
const F32 directionalFactor = 0.3f;
const F32 ambientFactor = 0.7f;
LightInfo & light = mLightingInfo.smAmbientLight;
light.mType = LightInfo::Ambient;
light.mDirection = VectorF(0.57735f, 0.57735f, -0.57735f);
light.mColor = ambientColor * directionalFactor;
light.mAmbient = ambientColor * ambientFactor;
lightManager->addLight(&mLightingInfo.smAmbientLight);
lightManager->setVectorLightsEnabled(false);
break;
}
case LightingInfo::Terrain:
{
F32 factor = mClampF((ambientColor.red + ambientColor.green + ambientColor.blue) / 3.f, 0.f, 1.f);
lightManager->setVectorLightsAttenuation(factor);
break;
}
}
}
lightManager->installGLLights(getRenderWorldBox());
}
void SceneObject::uninstallLights()
{
LightManager * lightManager = gClientSceneGraph->getLightManager();
AssertFatal(lightManager!=NULL, "SceneObject::uninstallLights: LightManager not found");
lightManager->removeLight(&mLightingInfo.smAmbientLight);
// resets all ambient/vector settings
lightManager->uninstallGLLights();
}
//--------------------------------------------------------------------------
// Lighting update: not used directly by sceneobject...
// - if an interior, which contains this object, moves then this value will be incorrect
bool SceneObject::getLightingAmbientColor(ColorF * col)
{
AssertFatal(col!=NULL, "SceneObject::getLightingAmbientColor: invalid color ptr");
const F32 cRayLength = 100.f; // down/up
const F32 cTerrainRayLength = 10.f; // height above terrain for no ambient
const F32 cColorStep = 0.2f; // amount to add per 100ms
PROFILE_START(GetLightingAmbientColor);
// query a new value?
if(mLightingInfo.mDirty)
{
mLightingInfo.mDirty = false;
Point3F pos;
getRenderWorldBox().getCenter(&pos);
// check if shadowed:
disableCollision();
mLightingInfo.mUseInfo = false;
mLightingInfo.mInterior = 0;
// Ambient light is determined by the surface we are standing on.
RayInfo collision;
if (gClientContainer.castRay(pos, Point3F(pos.x, pos.y, pos.z - cRayLength),
InteriorObjectType | TerrainObjectType, &collision))
{
// Standing on an interior object
if (InteriorInstance * instance = dynamic_cast<InteriorInstance*>(collision.object))
{
if (collision.face != -1)
{
// determine the color of this point...
Interior * interior = instance->getDetailLevel(0);
AssertFatal(interior!=NULL, "SceneObject::getLightingAmbientColor: invalid interior");
AssertFatal(collision.face < interior->getSurfaceCount(), "SceneObject::getLightingAmbientColor: invalid surface");
const Interior::Surface & surface = interior->getSurface(collision.face);
// get the render order
U32 currIndex = 0;
U32 last = 2;
static U32 renderIndices[512];
while(last < surface.windingCount)
{
// first
renderIndices[currIndex++] = last - 2;
renderIndices[currIndex++] = last - 1;
renderIndices[currIndex++] = last - 0;
last++;
if(last == surface.windingCount)
break;
// second
renderIndices[currIndex++] = last - 1;
renderIndices[currIndex++] = last - 2;
renderIndices[currIndex++] = last - 0;
last++;
}
// get the winding indices, the src indices and the points
static Point3F points[512];
static U32 srcIndices[512];
for(U32 i = 0; i < currIndex; i++)
{
srcIndices[i] = surface.windingStart + renderIndices[i];
renderIndices[i] = interior->getWinding(srcIndices[i]);
points[i] = interior->getPoint(renderIndices[i]);
}
// project the collision point into object space
instance->getWorldTransform().mulP(collision.point);
PlaneF plane = interior->getFlippedPlane(surface.planeIndex);
// walk the tri's to find the one under collision point
S32 insideOffset = -1;
for(U32 offset = 0; offset < currIndex; offset += 3)
{
bool inside = true;
for(U32 j = 0; (j < 3) && inside; j++)
{
U32 k = (j+1) % 3;
VectorF vec1 = points[offset + k] - points[offset + j];
VectorF vec2 = collision.point - points[offset + j];
Point3F cross;
mCross(vec2, vec1, &cross);
if(mDot(plane, cross) < 0.f)
inside = false;
}
if(inside)
{
insideOffset = offset;
break;
}
}
if(insideOffset != -1)
{
// box map the surface:
F32 max = 0.f;
S32 index = -1;
F32
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -