mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 20:54:46 +00:00
319 lines
10 KiB
C++
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;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
|