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:
parent
d39446c592
commit
0298cd3e00
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user