Torque3D/Engine/source/afx/ce/afxZodiacMgr_T3D.cpp
2017-07-26 19:38:34 +01:00

319 lines
10 KiB
C++

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "afx/arcaneFX.h"
#include "console/consoleTypes.h"
#include "core/stream/bitStream.h"
#include "scene/sceneRenderState.h"
#include "materials/shaderData.h"
#include "core/frameAllocator.h"
#include "terrain/terrRender.h"
#include "T3D/tsStatic.h"
#include "T3D/groundPlane.h"
#include "environment/meshRoad.h"
#include "collision/concretePolyList.h"
#include "gfx/primBuilder.h"
#include "terrain/terrCell.h"
#include "afx/ce/afxZodiac.h"
#include "afx/ce/afxZodiacMgr.h"
#include "afx/afxZodiacTerrainRenderer_T3D.h"
#include "afx/afxZodiacGroundPlaneRenderer_T3D.h"
#include "afx/afxZodiacMeshRoadRenderer_T3D.h"
#include "afx/afxZodiacPolysoupRenderer_T3D.h"
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// POLYSOUP INTERIOR ZODIACS //
void afxZodiacMgr::renderPolysoupZodiacs(SceneRenderState* state, TSStatic* tss)
{
// check for active interior zodiacs
S32 n_zodes = inter_zodes.size();
if (n_zodes <= 0)
return;
static SphereF dummy_sphere;
const Box3F& mWorldBox = tss->getWorldBox();
const Point3F& cam_pos = state->getCameraPosition();
// loop through the interior zodiacs
for (U32 i = 0; i < n_zodes; i++)
{
// calculate zodiac extents
F32 radius = inter_zodes[i].radius_xy;
Box3F box_w; box_w.minExtents = box_w.maxExtents = inter_zodes[i].pos;
box_w.minExtents -= Point3F(radius, radius, inter_zodes[i].vert_range.x);
box_w.maxExtents += Point3F(radius, radius, inter_zodes[i].vert_range.y);
// skip zodiacs not overlapping this object
if (mWorldBox.isOverlapped(box_w) == false)
continue;
// collect list of zodiac-intersecting polygons
ConcretePolyList* poly_list = new ConcretePolyList();
((SceneObject*)tss)->buildPolyList(PLC_Decal, poly_list, box_w, dummy_sphere);
// render the polys if we get any
if (!poly_list->mPolyList.empty())
{
// calculate zodiac distance from camera
Point3F cam_vec = cam_pos - inter_zodes[i].pos;
F32 cam_dist = cam_vec.lenSquared();
// render zodiacs
afxZodiacPolysoupRenderer::getMaster()->addZodiac(i, poly_list, inter_zodes[i].pos, inter_zodes[i].angle, tss, cam_dist);
// note: poly_list will be deleted by render-manager after rendering is done.
}
else
{
delete poly_list; // avoids crash when overlapping box but not polygons
}
}
}
ShaderData* afxZodiacMgr::getPolysoupZodiacShader()
{
if (!polysoup_zode_shader)
{
if( !Sim::findObject("afxZodiacPolysoupShader", polysoup_zode_shader))
{
Con::errorf("afxZodiacMgr::getPolysoupZodiacShader() - failed to find shader 'afxZodiacPolysoupShader'.");
return 0;
}
}
return polysoup_zode_shader;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
bool afxZodiacMgr::doesBoxOverlapZodiac(const Box3F& box, const afxZodiacMgr::ZodiacSpec& zode)
{
if ((zode.pos.x - zode.radius_xy) > box.maxExtents.x ||
(zode.pos.y - zode.radius_xy) > box.maxExtents.y)
return false;
if ((zode.pos.x + zode.radius_xy) < box.minExtents.x ||
( zode.pos.y + zode.radius_xy) < box.minExtents.y)
return false;
return true;
}
static U32 last_terr_zode_idx = 0;
bool afxZodiacMgr::doesBlockContainZodiacs(SceneRenderState* state, TerrainBlock* block)
{
// for now, only look at diffuse-passes
if (!state->isDiffusePass())
return false;
// check for active terrain zodiacs
S32 n_zodes = terr_zodes.size();
if (n_zodes <= 0)
return false;
const Box3F& block_box = block->getWorldBox();
last_terr_zode_idx = 0;
for (U32 i = 0; i < n_zodes; i++)
{
if (doesBoxOverlapZodiac(block_box, terr_zodes[i]))
{
last_terr_zode_idx = i;
return true;
}
}
return false;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
bool afxZodiacMgr::renderTerrainZodiacs(SceneRenderState* state, TerrainBlock* block, TerrCell* cell)
{
// we assume here that afxZodiacMgr::doesBlockContainZodiacs() was recently called to
// determine that at least one zodiac intersects the block and its index is last_terr_zode_idx.
bool cell_has_zodiacs = false;
const Point3F& cam_pos = state->getCameraPosition();
const Box3F& block_box = block->getWorldBox();
S32 n_zodes = terr_zodes.size();
for (U32 i = last_terr_zode_idx; i < n_zodes; i++)
{
// first test against block's box
if (!doesBoxOverlapZodiac(block_box, terr_zodes[i]))
continue;
const MatrixF& mRenderObjToWorld = block->getRenderTransform();
Box3F cell_box = cell->getBounds();
mRenderObjToWorld.mul(cell_box);
if (!doesBoxOverlapZodiac(cell_box, terr_zodes[i]))
continue;
// at this point we know the zodiac overlaps AABB of cell...
// calculate zodiac distance from camera
Point3F cam_vec = cam_pos - terr_zodes[i].pos;
F32 cam_dist = cam_vec.lenSquared();
//if (cam_dist > 2500)
// continue;
// render zodiacs
afxZodiacTerrainRenderer::getMaster()->addZodiac(i, terr_zodes[i].pos, terr_zodes[i].angle, block, cell, mRenderObjToWorld, cam_dist);
cell_has_zodiacs = true;
}
last_terr_zode_idx = 0;
return cell_has_zodiacs;
}
ShaderData* afxZodiacMgr::getTerrainZodiacShader()
{
if (!terrain_zode_shader)
{
if (!Sim::findObject("afxZodiacTerrainShader", terrain_zode_shader))
{
Con::errorf("afxZodiacMgr::getTerrainZodiacShader() - failed to find shader 'afxZodiacTerrainShader'.");
return 0;
}
}
return terrain_zode_shader;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacMgr::renderGroundPlaneZodiacs(SceneRenderState* state, GroundPlane* ground_plane)
{
// check for active terrain zodiacs
S32 n_zodes = terr_zodes.size();
if (n_zodes <= 0)
return;
// we currently expect gound-plane to be infinite
if (!ground_plane->isGlobalBounds())
{
return;
}
static SphereF dummy_sphere;
static Box3F dummy_box;
const Point3F& cam_pos = state->getCameraPosition();
// loop through the terrain zodiacs
for (U32 i = 0; i < n_zodes; i++)
{
// calculate zodiac distance from camera
Point3F cam_vec = cam_pos - terr_zodes[i].pos;
F32 cam_dist = cam_vec.lenSquared();
// render zodiacs
afxZodiacGroundPlaneRenderer::getMaster()->addZodiac(i, terr_zodes[i].pos, terr_zodes[i].angle, ground_plane, cam_dist);
}
}
ShaderData* afxZodiacMgr::getGroundPlaneZodiacShader()
{
if (!terrain_zode_shader)
{
if (!Sim::findObject("afxZodiacTerrainShader", terrain_zode_shader))
{
Con::errorf("afxZodiacMgr::getTerrainZodiacShader() - failed to find shader 'afxZodiacTerrainShader'.");
return 0;
}
}
return terrain_zode_shader;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
void afxZodiacMgr::renderMeshRoadZodiacs(SceneRenderState* state, MeshRoad* mesh_road)
{
// check for active terrain zodiacs
S32 n_zodes = terr_zodes.size();
if (n_zodes <= 0)
return;
const Box3F& mWorldBox = mesh_road->getWorldBox();
const Point3F& cam_pos = state->getCameraPosition();
// loop through the terrain zodiacs
for (U32 i = 0; i < n_zodes; i++)
{
// calculate zodiac extents
F32 radius = terr_zodes[i].radius_xy;
Box3F box_w; box_w.minExtents = box_w.maxExtents = terr_zodes[i].pos;
box_w.minExtents -= Point3F(radius, radius, terr_zodes[i].vert_range.x);
box_w.maxExtents += Point3F(radius, radius, terr_zodes[i].vert_range.y);
// skip zodiacs not overlapping this object
if (mWorldBox.isOverlapped(box_w) == false)
continue;
// collect list of zodiac-intersecting polygons
ConcretePolyList* poly_list = new ConcretePolyList();
mesh_road->buildTopPolyList(PLC_Decal, poly_list);
// render the polys if we get any
if (!poly_list->mPolyList.empty())
{
// calculate zodiac distance from camera
Point3F cam_vec = cam_pos - terr_zodes[i].pos;
F32 cam_dist = cam_vec.lenSquared();
// render zodiacs
afxZodiacMeshRoadRenderer::getMaster()->addZodiac(i, poly_list, terr_zodes[i].pos, terr_zodes[i].angle, mesh_road, cam_dist);
// note: poly_list will be deleted by render-manager after rendering is done.
}
else
{
delete poly_list; // avoids crash when overlapping box but not polygons
}
}
}
ShaderData* afxZodiacMgr::getMeshRoadZodiacShader()
{
if (!terrain_zode_shader)
{
if (!Sim::findObject("afxZodiacTerrainShader", terrain_zode_shader))
{
Con::errorf("afxZodiacMgr::getTerrainZodiacShader() - failed to find shader 'afxZodiacTerrainShader'.");
return 0;
}
}
return terrain_zode_shader;
}
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//