📄 chcollision.cpp
字号:
}
#if 1
#define WIDTH 4
#define HEIGHT 4
//unsigned char buffer1[WIDTH * HEIGHT * 4];
#if (defined(CH_USE_RLAB))
static RLImage stockImage = {
WIDTH, HEIGHT, /* width, height */
2, 1, /* aspectx, aspecty */
24, /* depth */
TRUE, /* rgb */
WIDTH*4, /* bytes_per_line */
0, /* buffer1 */
NULL, /* buffer2 */
0xff0000, /* red mask */
0xff00, /* green mask */
0xff, /* blue mask */
0, /* alpha mask */
0, /* palette size */
NULL, /* palette */
};
#define ZBUFFERDEPTH 16
#endif
ChCollisionView::ChCollisionView(ChRenderContext *pRC, ChNrViewport sceneView, ChNrFrame scene, ChNrFrame sceneCamera ) :
m_buffer(0), m_zBuffer(0)
#if (defined(CH_USE_D3D))
, m_pDevice(0)
#endif
{
m_camera = pRC->CreateFrame(sceneCamera);
ChNrFrameSetPosition(m_camera, sceneCamera, 0, 0, 0);
ChNrFrameSetOrientation(m_camera, sceneCamera,
0, 0, -1,
0, 1, 0); // point backwards to start
#if (defined(CH_USE_RLAB))
// Set up the image buffer
m_image = stockImage;
m_buffer = new unsigned char [WIDTH * HEIGHT * 4];
::memset(m_buffer, 0, WIDTH * HEIGHT * 4);
m_image.buffer1 = m_buffer;
// Now set up the z buffer
m_zBufferImage = stockImage;
m_zBufferImage.depth = ZBUFFERDEPTH;
m_zBufferImage.bytes_per_line = ZBUFFERDEPTH / 8 * m_zBufferImage.width;
m_zBuffer = new unsigned char [WIDTH * HEIGHT * ZBUFFERDEPTH / 8];
::memset(m_zBuffer, 0, WIDTH * HEIGHT * ZBUFFERDEPTH / 8);
m_zBufferImage.buffer1 = m_zBuffer;
m_dev = RLCreateMemoryDevice(&m_image, /*0*/ &m_zBufferImage , NULL, NULL, NULL, NULL);
#elif (defined(CH_USE_D3D))
m_pDevice = new ChDevice3D(pRC, WIDTH, HEIGHT);
m_dev = m_pDevice->GetDevice();
#endif
ChNrDeviceSetQuality(m_dev, RenderFlat);
m_view = pRC->CreateViewport(m_dev, m_camera, 0, 0,
ChNrDeviceGetWidth(m_dev),
ChNrDeviceGetHeight(m_dev));
m_scene = scene;
m_sceneCamera = sceneCamera;
ChNrViewportSetProjection(m_view, ChNrViewportGetProjection(sceneView) );
ChNrViewportSetFront(m_view, ChNrViewportGetFront(sceneView) / NEAR_PLANE_SCALE); // as close as possible
ChNrViewportSetBack(m_view, ChNrViewportGetBack(sceneView));
#ifdef _DEBUG
float front = ChNrViewportGetFront(sceneView);
float back = ChNrViewportGetBack(sceneView);
//int field = int(ChNrViewportGetField(sceneView) * 4. / ChNrViewportGetHeight(sceneView));
#endif
float field = (ChNrViewportGetField(sceneView) * 4. / ChNrViewportGetHeight(sceneView));
ChNrViewportSetField(m_view, field / NEAR_PLANE_SCALE);
//RLTick(); /* render a scene */
}
ChCollisionView::~ChCollisionView()
{
if(m_view) ChNrObjectDestroy(m_view);
m_view = 0;
#if (defined(CH_USE_RLAB))
if(m_dev) ChNrObjectDestroy(m_dev);
m_dev = 0;
#elif (defined(CH_USE_D3D))
// delete the rcdevice
delete m_pDevice;
#endif
delete [] m_buffer;
m_buffer = 0;
delete [] m_zBuffer;
m_zBuffer = 0;
}
void ChCollisionView::SetDir(GxVec3f dir)
{
dir.normalize();
//dir .z() = -dir.z();
dir .x() = -dir.x();
dir .y() = -dir.y();
GxVec3f xAxis(1, 0, 0), yAxis(0, 1, 0), sideways, up;
if(dir.dot(yAxis) > .9)
{
sideways = dir.cross(xAxis);
}
else
{
sideways = dir.cross(yAxis);
}
up = sideways.cross(dir);
ChNrFrameSetOrientation(m_camera, m_scene,
dir.x(), dir.y(), dir.z(),
up.x(), up.y(), up.z());
SetBack();
};
void ChCollisionView::SetRelativeDir(GxVec3f dir)
{
dir.normalize();
GxVec3f xAxis(1, 0, 0), yAxis(0, 1, 0), sideways, up;
if(dir.dot(yAxis) > .9)
{
sideways = dir.cross(xAxis);
}
else
{
sideways = dir.cross(yAxis);
}
up = sideways.cross(dir);
ChNrFrameSetOrientation(m_camera, m_sceneCamera,
dir.x(), dir.y(), dir.z(),
up.x(), up.y(), up.z());
SetBack();
}
void ChCollisionView::SetBack()
{
// Step back a bit for the collision view from the current camera loc
// to account for the near clipping plane
GxVec3f dir, up;
ChNrFrameGetOrientation(m_camera, m_sceneCamera,
(ChNrVector*)&dir,
(ChNrVector*)&up);
dir.normalize();
dir *= -ChNrViewportGetFront(m_view);
ChNrFrameSetPosition(m_camera, m_sceneCamera,
dir.x(), dir.y(), dir.z());
}
void ChCollisionView::Render()
{
#if (defined(CH_USE_RLAB))
::memset(m_zBuffer, 0xff, WIDTH * HEIGHT * ZBUFFERDEPTH / 8);
#endif
ChNrViewportClear(m_view);
ChNrViewportRender(m_view, m_scene);
ChNrDeviceUpdate(m_dev);
}
float ChCollisionView::GetZ()
{
#if (defined(CH_USE_RLAB))
GxVec3f pt;
ChNrVector4d screenCoord;
unsigned short zMin = 0xffff;
int width = ChNrViewportGetWidth(m_view);
int height = ChNrViewportGetHeight(m_view);
for(int x = 0; x < width; x++)
{
for(int y = 0; y < height; y++)
{
int index = y * m_zBufferImage.bytes_per_line / 2 + x ;
unsigned short z = ((unsigned short*)m_zBufferImage.buffer1)[index];
zMin = min(z, zMin);
}
}
if(zMin == 0xffff) return CH_INFINITE_RANGE; // free to move if nothing drawn
screenCoord.x = 0;
screenCoord.y = 0;
#if 1
screenCoord.x = width / 2;
screenCoord.y = height / 2;
#endif
screenCoord.z = float(zMin) / 65535.;
screenCoord.w = 1;
ChNrViewportInverseTransform(m_view, (ChNrVector*)&pt, &screenCoord);
// Convert to camera coords
GxVec3f ptInCameraSpace;
ChNrFrameInverseTransform(m_camera, (ChNrVector*)&ptInCameraSpace, (ChNrVector*)&pt);
return ptInCameraSpace.z();
#else
return 0;
#endif
}
#endif // 0 or 1
#if (defined(CH_USE_D3D))
// Just stubs to get us going on d3d
#pragma message("D3D Collision Testing Not done!")
#if 0
float ChRenderContext::GetCollisionRange(GxVec3f &look, bool boolRelative /* = false*/)
{
// Return the range the current camera can be moved without colliding with something
// value is in -camera- coords
float range = CH_INFINITE_RANGE; // free to move if no scene
return range;
};
#endif
#elif (defined(CH_USE_RLAB))
//#define BE_VERY_NOISY_ON_COLLISION_TESTING 1
float ChRenderContext::GetAvatarRadius()
{
return .1; // bout the size of your head
};
float ChRenderContext::GetCollisionRange()
{
// Return the range the current camera can be moved without colliding with something
// value is in -camera- coords
float range = CH_INFINITE_RANGE; // free to move if no scene
if(m_viewport)
{
ChNrFrame frame;
// Lock the scene and don't be nice
LockScene();
int iX = ChNrViewportGetWidth(m_viewport) / 2;
int iY = ChNrViewportGetHeight(m_viewport) / 2;
RLVisual visual;
if(ChNrViewportFindVisual( m_viewport, &visual, &frame, iX, iY) != RLNotFound)
{
// Hit -something-. How far away is it?
GxVec3f clickPoint;
ChNrFaceInfo faceInfo;
if((ChNrViewportFindFace( m_viewport, &faceInfo, iX, iY) != RLNotFound)
&& faceInfo.frame == frame)
{
clickPoint = *(GxVec3f*)&faceInfo.position;
ChNrVector4d screenCoord;
screenCoord.x = clickPoint.x();
screenCoord.y = clickPoint.y();
screenCoord.z = clickPoint.z();
screenCoord.w = 1;
ChNrViewportInverseTransform(m_viewport, (ChNrVector*)&clickPoint, &screenCoord);
}
else
{
// It's not a face visual, must be a decal
ChNrFrameGetPosition(frame, m_sceneFrame, (ChNrVector*)&clickPoint);
}
// Convert to camera coords
GxVec3f ptInCameraSpace;
ChNrFrameInverseTransform(m_cameraFrame, (ChNrVector*)&ptInCameraSpace, (ChNrVector*)&clickPoint);
// take range - I'm not sure if this works if we have a scaling transform before the camera
range = ptInCameraSpace.magnitude() - ChNrViewportGetFront(m_viewport);
range = max(range, 0.);
}
UnlockScene();
}
return range;
}
#endif
// end of file
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -