Allow Cinematic Path nodes that only specify a camera position or direction and group them by deltatime.

Remove the support of saving the rotation of camera position nodes,
because that should be rewritten to use a custom spline.

Patch By: Vladislav
Differential Revision: https://code.wildfiregames.com/D124
Refs #3814

This was SVN commit r19317.
This commit is contained in:
elexis 2017-03-20 15:26:34 +00:00
parent 76c7731076
commit 36330732fa
2 changed files with 62 additions and 57 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -859,15 +859,16 @@ void CXMLReader::ReadPaths(XMBElement parent)
CCinemaData pathData;
XMBAttributeList attrs = element.GetAttributes();
CStrW pathName(attrs.GetNamedItem(at_name).FromUTF8());
pathData.m_Timescale = fixed::FromString(attrs.GetNamedItem(at_timescale));
TNSpline pathSpline, targetSpline;
fixed lastTargetTime = fixed::Zero();
pathData.m_Name = pathName;
pathData.m_Timescale = fixed::FromString(attrs.GetNamedItem(at_timescale));
pathData.m_Orientation = attrs.GetNamedItem(at_orientation).FromUTF8();
pathData.m_Mode = attrs.GetNamedItem(at_mode).FromUTF8();
pathData.m_Style = attrs.GetNamedItem(at_style).FromUTF8();
TNSpline positionSpline, targetSpline;
fixed lastPositionTime = fixed::Zero();
fixed lastTargetTime = fixed::Zero();
XERO_ITER_EL(element, pathChild)
{
elementName = pathChild.GetNodeName();
@ -876,9 +877,7 @@ void CXMLReader::ReadPaths(XMBElement parent)
// Load node data used for spline
if (elementName == el_node)
{
bool positionDeclared = false;
SplineData data;
data.Distance = fixed::FromString(attrs.GetNamedItem(at_deltatime));
lastPositionTime += fixed::FromString(attrs.GetNamedItem(at_deltatime));
lastTargetTime += fixed::FromString(attrs.GetNamedItem(at_deltatime));
XERO_ITER_EL(pathChild, nodeChild)
{
@ -887,16 +886,17 @@ void CXMLReader::ReadPaths(XMBElement parent)
if (elementName == el_position)
{
data.Position.X = fixed::FromString(attrs.GetNamedItem(at_x));
data.Position.Y = fixed::FromString(attrs.GetNamedItem(at_y));
data.Position.Z = fixed::FromString(attrs.GetNamedItem(at_z));
positionDeclared = true;
CFixedVector3D position;
position.X = fixed::FromString(attrs.GetNamedItem(at_x));
position.Y = fixed::FromString(attrs.GetNamedItem(at_y));
position.Z = fixed::FromString(attrs.GetNamedItem(at_z));
positionSpline.AddNode(position, CFixedVector3D(), lastPositionTime);
lastPositionTime = fixed::Zero();
}
else if (elementName == el_rotation)
{
data.Rotation.X = fixed::FromString(attrs.GetNamedItem(at_x));
data.Rotation.Y = fixed::FromString(attrs.GetNamedItem(at_y));
data.Rotation.Z = fixed::FromString(attrs.GetNamedItem(at_z));
// TODO: Implement rotation slerp/spline as another object
}
else if (elementName == el_target)
{
@ -911,17 +911,13 @@ void CXMLReader::ReadPaths(XMBElement parent)
else
LOGWARNING("Invalid cinematic element for node child");
}
// Skip the node if no position
if (positionDeclared)
pathSpline.AddNode(data.Position, data.Rotation, data.Distance);
}
else
LOGWARNING("Invalid cinematic element for path child");
}
// Construct cinema path with data gathered
CCinemaPath path(pathData, pathSpline, targetSpline);
CCinemaPath path(pathData, positionSpline, targetSpline);
if (path.Empty())
{
LOGWARNING("Path with name '%s' is empty", pathName.ToUTF8());

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -409,7 +409,7 @@ void CMapWriter::WriteXML(const VfsPath& filename,
for ( ; it != paths.end(); ++it )
{
fixed timescale = it->second.GetTimescale();
const std::vector<SplineData>& nodes = it->second.GetAllNodes();
const std::vector<SplineData>& position_nodes = it->second.GetAllNodes();
const std::vector<SplineData>& target_nodes = it->second.GetTargetSpline().GetAllNodes();
const CCinemaData* data = it->second.GetData();
@ -420,46 +420,55 @@ void CMapWriter::WriteXML(const VfsPath& filename,
XML_Attribute("mode", data->m_Mode);
XML_Attribute("style", data->m_Style);
struct SEvent
{
fixed time;
const char* type;
CFixedVector3D value;
SEvent(fixed time, const char* type, CFixedVector3D value)
: time(time), type(type), value(value)
{}
bool operator<(const SEvent& another)
{
return time < another.time;
}
};
// All events of a manipulating of camera (position/rotation/target)
std::vector<SEvent> events;
fixed last_position = fixed::Zero();
for (size_t i = 0; i < position_nodes.size(); ++i)
{
fixed distance = i > 0 ? position_nodes[i - 1].Distance : fixed::Zero();
last_position += distance;
events.emplace_back(last_position, "Position", position_nodes[i].Position);
}
fixed last_target = fixed::Zero();
for (size_t i = 0, j = 0; i < nodes.size(); ++i)
for (size_t i = 0; i < target_nodes.size(); ++i)
{
fixed distance = i > 0 ? target_nodes[i - 1].Distance : fixed::Zero();
last_target += distance;
events.emplace_back(last_target, "Target", target_nodes[i].Position);
}
std::sort(events.begin(), events.end());
for (size_t i = 0; i < events.size();)
{
XML_Element("Node");
fixed distance = i > 0 ? nodes[i - 1].Distance : fixed::Zero();
last_target += distance;
XML_Attribute("deltatime", distance);
fixed deltatime = i > 0 ? (events[i].time - events[i - 1].time) : fixed::Zero();
XML_Attribute("deltatime", deltatime);
size_t j = i;
for (; j < events.size() && events[j].time == events[i].time; ++j)
{
XML_Element("Position");
XML_Attribute("x", nodes[i].Position.X);
XML_Attribute("y", nodes[i].Position.Y);
XML_Attribute("z", nodes[i].Position.Z);
// Types: Position/Rotation/Target
XML_Element(events[j].type);
XML_Attribute("x", events[j].value.X);
XML_Attribute("y", events[j].value.Y);
XML_Attribute("z", events[j].value.Z);
}
{
XML_Element("Rotation");
XML_Attribute("x", nodes[i].Rotation.X);
XML_Attribute("y", nodes[i].Rotation.Y);
XML_Attribute("z", nodes[i].Rotation.Z);
}
if (j >= target_nodes.size())
continue;
fixed target_distance = j > 0 ? target_nodes[j - 1].Distance : fixed::Zero();
if (target_distance > last_target)
continue;
{
XML_Element("Target");
XML_Attribute("x", target_nodes[j].Position.X);
XML_Attribute("y", target_nodes[j].Position.Y);
XML_Attribute("z", target_nodes[j].Position.Z);
}
last_target = fixed::Zero();
++j;
i = j;
}
}
}