Removed assumptions of root node's identity transform.

Re-added the root node transform attributes so they can be edited, though this is not recommended.
Fixed needless creation of almost similar collision meshes caused by floating point inaccuracy.
Fixed bug where parenting a node back to the root node would not be replicated correctly on the network.
This commit is contained in:
Lasse Öörni 2011-08-22 07:05:19 +00:00
parent d39446c592
commit 0298cd3e00
5 changed files with 36 additions and 20 deletions

View File

@ -493,6 +493,8 @@ Now you should be ready to compile HelloWorld.cpp. The resulting executable will
The Urho3D scene editor is a script application that can be run with the Urho3D main executable. To start, execute either of these commands: (in the Bin directory) Editor.bat or Urho3D.exe Scripts/Editor.as
Hint: to get some content to look at, run the TestScene example, and press F5. This saves a scene file called Scene.xml into the Data subdirectory, which can be loaded in the editor.
\section EditorInstructions_Controls Controls
\verbatim
@ -541,12 +543,14 @@ New scene nodes and components are created with the buttons at the bottom of the
To reparent scene nodes, drag and drop them onto the new parent scene node in the scene hierarchy window. Reparenting should retain the effective world transform, so check afterwards from the component window that the local transform is what you expect it to be. Components can not be dragged between nodes, but can be duplicated with cut/copy/paste operations.
Currently, when you edit for example a material or texture, you need to manually reload scene resources (Ctrl+R) to make the changes visible.
Though Urho3D supports setting a non-identity transform on the root node (scene), it is still best to leave it at identity (position 0, 0, 0, rotation 0, 0, 0, scale 1, 1, 1.)
To create a user variable into the current node, or delete it, type its name into the edit field below the node attributes, and press New or Del buttons. The New button will prompt to choose the variable type.
To create a user variable into the current node, or delete it, type the variable name into the edit field below the node attributes, and press New or Del buttons next to it. The New button will prompt to choose the variable type.
While editing, you can execute script files using the "Run script" item in the %File menu. These are AngelScript files that are executed in immediate mode ie. you do not need to define a function. The editor's scene will be accessible to the script as the global property "scene."
Currently, when you edit for example a material or texture, you need to manually reload scene resources (Ctrl+R) to make the changes visible.
\section EditorInstructions_Importing Importing
The editor can import models or scenes from all the formats that the Open Asset Import Library supports, see http://assimp.sourceforge.net/main_features_formats.html

View File

@ -865,8 +865,13 @@ void CollisionShape::CreateGeometry()
case SHAPE_TRIANGLEMESH:
case SHAPE_CONVEXHULL:
{
// For mesh cache lookup purposes, quantize size to 3 decimals only. Otherwise floating point inaccuracy from world
// matrix multiplications and rotation/scale decomposing causes several slightly differing meshes to be created
char sizeText[CONVERSION_BUFFER_LENGTH];
sprintf(sizeText, "%.3f%.3f%.3f", size.x_, size.y_, size.z_);
// Check the geometry cache
String id = model_->GetName() + "_" + String(size) + "_" + String(lodLevel_);
String id = model_->GetName() + "_" + String(sizeText) + "_" + String(lodLevel_);
if (shapeType_ == SHAPE_CONVEXHULL)
id += "_" + String(thickness_);
@ -890,8 +895,11 @@ void CollisionShape::CreateGeometry()
case SHAPE_HEIGHTFIELD:
{
char sizeText[CONVERSION_BUFFER_LENGTH];
sprintf(sizeText, "%.3f%.3f%.3f", size.x_, size.y_, size.z_);
// Check the geometry cache
String id = model_->GetName() + "_" + String(size) + "_" + String(numPoints_) + "_" + String(thickness_) + "_" +
String id = model_->GetName() + "_" + String(sizeText) + "_" + String(numPoints_) + "_" + String(thickness_) + "_" +
String(lodLevel_);
Map<String, SharedPtr<HeightfieldData> >& cache = physicsWorld_->GetHeightfieldCache();

View File

@ -423,10 +423,9 @@ void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
processedBodies.Insert(this);
inPostStep_ = true;
// If the parent node has a rigid body, process it first. For now, treat node parented to the Scene as unparented
// If the parent node has a rigid body, process it first
Node* parent = node_->GetParent();
bool hasParent = parent && parent != node_->GetScene();
if (hasParent)
if (parent)
{
RigidBody* parentBody = parent->GetComponent<RigidBody>();
if (parentBody)
@ -439,7 +438,7 @@ void RigidBody::PostStep(float t, HashSet<RigidBody*>& processedBodies)
// Apply the physics transform to rendering transform now
const Vector3& currentPosition = *reinterpret_cast<const Vector3*>(dBodyGetPosition(body_));
const Quaternion& currentRotation = *reinterpret_cast<const Quaternion*>(dBodyGetQuaternion(body_));
if (!hasParent)
if (!parent)
{
// If node already has motion smoothing enabled, do not do substep interpolation
if (!node_->IsSmoothed())

View File

@ -761,7 +761,10 @@ void Node::SetNetParentAttr(const PODVector<unsigned char>& value)
MemoryBuffer buf(value);
// If nothing in the buffer, parent is the root node
if (buf.IsEof())
{
SetParent(scene);
return;
}
unsigned baseNodeID = buf.ReadNetID();
Node* baseNode = scene->GetNodeByID(baseNodeID);
@ -771,18 +774,18 @@ void Node::SetNetParentAttr(const PODVector<unsigned char>& value)
return;
}
// If buffer contains just an ID, the parent is replicated
// If buffer contains just an ID, the parent is replicated and we are done
if (buf.IsEof())
baseNode->AddChild(this);
SetParent(baseNode);
else
{
// Else the parent is local and we must find it recursively by name hash
StringHash nameHash = buf.ReadStringHash();
Node* parent = baseNode->GetChild(nameHash, true);
if (!parent)
Node* parentNode = baseNode->GetChild(nameHash, true);
if (!parentNode)
LOGWARNING("Failed to find parent node with name hash " + nameHash.ToString());
else
parent->AddChild(this);
SetParent(parentNode);
}
}
@ -974,9 +977,7 @@ Node* Node::CreateChild(unsigned id, CreateMode mode)
void Node::UpdateWorldTransform() const
{
// For now, assume that the Scene has identity transform so that we skip one matrix multiply. However in the future
// we may want dynamic root nodes for large worlds
if (parent_ && parent_ != scene_)
if (parent_)
{
if (parent_->dirty_)
parent_->UpdateWorldTransform();

View File

@ -75,14 +75,18 @@ void Scene::RegisterObject(Context* context)
context->RegisterFactory<Scene>();
REF_ACCESSOR_ATTRIBUTE(Scene, VAR_STRING, "Name", GetName, SetName, String, String(), AM_DEFAULT);
ATTRIBUTE(Scene, VAR_FLOAT, "Smoothing Constant", smoothingConstant_, DEFAULT_SMOOTHING_CONSTANT, AM_DEFAULT);
ATTRIBUTE(Scene, VAR_FLOAT, "Snap Threshold", snapThreshold_, DEFAULT_SNAP_THRESHOLD, AM_DEFAULT);
ATTRIBUTE(Scene, VAR_VARIANTMAP, "Variables", vars_, VariantMap(), AM_FILE); // Network replication of vars uses custom data
REF_ACCESSOR_ATTRIBUTE(Scene, VAR_VECTOR3, "Position", GetPosition, SetPosition, Vector3, Vector3::ZERO, AM_DEFAULT | AM_LATESTDATA);
REF_ACCESSOR_ATTRIBUTE(Scene, VAR_QUATERNION, "Rotation", GetRotation, SetRotation, Quaternion, Quaternion::IDENTITY, AM_FILE);
REF_ACCESSOR_ATTRIBUTE(Scene, VAR_VECTOR3, "Scale", GetScale, SetScale, Vector3, Vector3::UNITY, AM_DEFAULT);
ACCESSOR_ATTRIBUTE(Scene, VAR_FLOAT, "Smoothing Constant", GetSmoothingConstant, SetSmoothingConstant, float, DEFAULT_SMOOTHING_CONSTANT, AM_DEFAULT);
ACCESSOR_ATTRIBUTE(Scene, VAR_FLOAT, "Snap Threshold", GetSnapThreshold, SetSnapThreshold, float, DEFAULT_SNAP_THRESHOLD, AM_DEFAULT);
ATTRIBUTE(Scene, VAR_INT, "Next Replicated Node ID", replicatedNodeID_, FIRST_REPLICATED_ID, AM_FILE | AM_NOEDIT);
ATTRIBUTE(Scene, VAR_INT, "Next Replicated Component ID", replicatedComponentID_, FIRST_REPLICATED_ID, AM_FILE | AM_NOEDIT);
ATTRIBUTE(Scene, VAR_INT, "Next Local Node ID", localNodeID_, FIRST_LOCAL_ID, AM_FILE | AM_NOEDIT);
ATTRIBUTE(Scene, VAR_INT, "Next Local Component ID", localComponentID_, FIRST_LOCAL_ID, AM_FILE | AM_NOEDIT);
ACCESSOR_ATTRIBUTE(Scene, VAR_STRING, "User Variable Names", GetVarNamesAttr, SetVarNamesAttr, String, String(), AM_FILE | AM_NOEDIT);
ATTRIBUTE(Scene, VAR_VARIANTMAP, "Variables", vars_, VariantMap(), AM_FILE); // Network replication of vars uses custom data
ACCESSOR_ATTRIBUTE(Scene, VAR_STRING, "Variable Names", GetVarNamesAttr, SetVarNamesAttr, String, String(), AM_FILE | AM_NOEDIT);
REF_ACCESSOR_ATTRIBUTE(Scene, VAR_BUFFER, "Network Rotation", GetNetRotationAttr, SetNetRotationAttr, PODVector<unsigned char>, PODVector<unsigned char>(), AM_NET | AM_LATESTDATA | AM_NOEDIT);
}
bool Scene::Load(Deserializer& source)