1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
/* Copyright (C) 2016 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_OBJECTBASE
#define INCLUDED_OBJECTBASE
class CModel;
class CSkeletonAnim;
class CObjectManager;
class CXeromyces;
class XMBElement;
#include <vector>
#include <set>
#include <map>
#include <boost/unordered_set.hpp>
#include "lib/file/vfs/vfs_path.h"
#include "ps/CStr.h"
#include "ps/CStrIntern.h"
#include <boost/random/mersenne_twister.hpp>
class CObjectBase
{
NONCOPYABLE(CObjectBase);
public:
struct Anim
{
// constructor
Anim() : m_Frequency(0), m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f), m_SoundPos(-1.f) {}
// name of the animation - "Idle", "Run", etc
CStr m_AnimName;
// ID of the animation: if not empty, something specific to sync with props.
CStr m_ID = "";
int m_Frequency;
// filename of the animation - manidle.psa, manrun.psa, etc
VfsPath m_FileName;
// animation speed, as specified in XML actor file
float m_Speed;
// fraction [0.0, 1.0] of the way through the animation that the interesting bit(s)
// happens, or -1.0 if unspecified
float m_ActionPos;
float m_ActionPos2;
float m_SoundPos;
};
struct Prop
{
// constructor
Prop() : m_minHeight(0.f), m_maxHeight(0.f), m_selectable(true) {}
// name of the prop point to attach to - "Prop01", "Prop02", "Head", "LeftHand", etc ..
CStr m_PropPointName;
// name of the model file - art/actors/props/sword.xml or whatever
CStrW m_ModelName;
// allow the prop to ajust the height from minHeight to maxHeight relative to the main model
float m_minHeight;
float m_maxHeight;
bool m_selectable;
};
struct Samp
{
// identifier name of sampler in GLSL shaders
CStrIntern m_SamplerName;
// path to load from
VfsPath m_SamplerFile;
};
struct Decal
{
Decal() : m_SizeX(0.f), m_SizeZ(0.f), m_Angle(0.f), m_OffsetX(0.f), m_OffsetZ(0.f) {}
float m_SizeX;
float m_SizeZ;
float m_Angle;
float m_OffsetX;
float m_OffsetZ;
};
struct Variant
{
Variant() : m_Frequency(0) {}
CStr m_VariantName; // lowercase name
int m_Frequency;
VfsPath m_ModelFilename;
Decal m_Decal;
VfsPath m_Particles;
CStr m_Color;
std::vector<Anim> m_Anims;
std::vector<Prop> m_Props;
std::vector<Samp> m_Samplers;
};
struct Variation
{
VfsPath model;
Decal decal;
VfsPath particles;
CStr color;
std::multimap<CStr, Prop> props;
std::multimap<CStr, Anim> anims;
std::multimap<CStr, Samp> samplers;
};
CObjectBase(CObjectManager& objectManager);
// Get the variation key (indices of chosen variants from each group)
// based on the selection strings
std::vector<u8> CalculateVariationKey(const std::vector<std::set<CStr> >& selections);
// Get the final actor data, combining all selected variants
const Variation BuildVariation(const std::vector<u8>& variationKey);
// Get a set of selection strings that are complete enough to specify an
// exact variation of the actor, using the initial selections wherever possible
// and choosing randomly where a choice is necessary.
std::set<CStr> CalculateRandomVariation(uint32_t seed, const std::set<CStr>& initialSelections);
// Given a prioritized vector of selection string sets that partially specify
// a variation, calculates a remaining set of selection strings such that the resulting
// set merged with the initial selections fully specifies an exact variation of
// the actor. The resulting selections are selected randomly, but only where a choice
// is necessary (i.e. where there are multiple variants but the initial selections,
// applied in priority order, fail to select one).
std::set<CStr> CalculateRandomRemainingSelections(uint32_t seed, const std::vector<std::set<CStr> >& initialSelections);
// Get a list of variant groups for this object, plus for all possible
// props. Duplicated groups are removed, if several props share the same
// variant names.
std::vector<std::vector<CStr> > GetVariantGroups() const;
/**
* Initialise this object by loading from the given file.
* Returns false on error.
*/
bool Load(const VfsPath& pathname);
/**
* Reload this object from the file that it was previously loaded from.
* Returns false on error.
*/
bool Reload();
/**
* Returns whether this object (including any possible props)
* uses the given file. (This is used for hotloading.)
*/
bool UsesFile(const VfsPath& pathname);
// filename that this was loaded from
VfsPath m_Pathname;
// short human-readable name
CStrW m_ShortName;
struct {
// cast shadows from this object
bool m_CastShadows;
// float on top of water
bool m_FloatOnWater;
} m_Properties;
// the material file
VfsPath m_Material;
private:
// A low-quality RNG like rand48 causes visible non-random patterns (particularly
// in large grids of the same actor with consecutive seeds, e.g. forests),
// so use a better one that appears to avoid those patterns
typedef boost::mt19937 rng_t;
std::set<CStr> CalculateRandomRemainingSelections(rng_t& rng, const std::vector<std::set<CStr> >& initialSelections);
std::vector< std::vector<Variant> > m_VariantGroups;
CObjectManager& m_ObjectManager;
boost::unordered_set<VfsPath> m_UsedFiles;
void LoadVariant(const CXeromyces& XeroFile, const XMBElement& variant, Variant& currentVariant);
};
#endif
|