StereoKit icon indicating copy to clipboard operation
StereoKit copied to clipboard

[Docs-Model.AddSubset] Model AddChild vs AddSubset

Open laultman opened this issue 3 years ago • 5 comments

It seems that the docs might be out of date on this. AddChild is not described. AddSubset seems to have been the forerunner to AddChild method. Their signatures are very similar. I am trying to add a Model as a child node of a parent Model. AddChild takes a Matrix. I do not find any methods to turn a Model into a Matrix. How do I encapsulate the model into a Matrix so that it can be added as a child node? Think about building a house with lots of pre-designed models. I want to be able to "plug-in" rooms into the model design concept. Naturally a house is an easy stand-in for a rocket or Lego model.

laultman avatar Jul 12 '22 08:07 laultman

Model.AddSubset is obsolete at this point, yeah. Model.AddNode is the correct replacement for it, and AddChild belongs to ModelNode, rather than Model! And a Matrix in this context is a mathematical type that represents 3D transforms, so there's no conversion between a Model and a Matrix!

Currently, a Model cannot contain another Model inside it. The ability to do this would open up a can of worms that I'm just not prepared for, and may even be outside the scope of SK's core.

To do something similar though, here's some pseudocode:

Model     model      = Model.FromFile("...");
Model     otherModel = Model.FromFile("...");
ModelNode anchorNode = model.FindNode("anchor");
Matrix    modelAt    = Matrix.T(0,1,0);
...

model.Draw(modelAt);
Hierarchy.Push(modelAt);
{
    otherModel.Draw(anchorNode.ModelTransform);
}
Hierarchy.Pop()

If you're doing a lot of this type of thing, you might want to look into making some sort of scene graph! I unfortunately don't have a good sample for this, but it's something I'd like to do at some point.

maluoi avatar Jul 12 '22 16:07 maluoi

Funny, scene graph... I spent a lot of time yesterday trying to talk myself out of using a graph. In the end it was the only solution that made sense. So, I am working on it. I have another comment over at #225 .NET Standard 2.1, that I hope you might consider because of this. Thanks for the code and explanation.

laultman avatar Jul 13 '22 09:07 laultman

Update: Got the multiple models stuff working. All draw fine. Binding it all together and getting a bounding box to encapsulate scattered models around the scene was a little bit of a chore. Now materials. The AddChild method signature includes the parameter for a material. I am providing a material that I am setting its Color property. The material is ignored it seems. I am creating objects and attempting to add them to my model. The objects are children of the model. I want to have different colors applied to the different objects. Here is my method that adds objects to my models. I can't understand why the material is not applied to the object. My assumption is that the reference to the material causes the Draw method to use the named material. ` private void AddModelObjects(ReAccessLogisticsRootNode rNode) { foreach (var kvp in models) { var model = kvp.Value.Name; var objData = rNode.Bay.BuildingObjects.Where(x => x.ObjectType == model).Select(x => x).ToList(); // get all the objects of this type to a list

			var rootNode = kvp.Value.Model.RootNode;
			foreach (var obj in objData)
			{
				var cubeMesh = MakeCubeObject(CubeTypeOptions.SquareCorners, V.XYZ(obj.X, obj.Y, obj.Z) * scale);

				var color = Color.Hex(colorDict.MaterialColors[obj.ObjectType]); 
				var mat = Default.Material.Copy();  // make a copy to set properties as needed
				mat.SetColor(obj.ObjectType, color);

				rootNode.AddChild(obj.Name,
						Matrix.TR(V.XYZ(obj.PX, obj.PY, obj.PZ) * scale, Quat.LookDir(V.XYZ(obj.RX, obj.RY, obj.RZ) * scale)),
						cubeMesh,
						mat//materials[obj.ObjectType]   //Material.Default
						);
			}

		}
	}

Later in the Update method I draw all the models: for(var i = 0; i < models.Count; i++) { var model = models[i].Model; model.Draw(Matrix.S(1)); // draw the model at current scale } `

laultman avatar Aug 05 '22 09:08 laultman

Found the problem. Poring through the cpp I found the solution. I must set the "color" property on the shader. The docs could use some improvement here. In the description of the material SetColor method, it simply refers to the shader parameter. Under the Shader docs it does not list the formal properties that may be set by various methods. Knowing that the name parameter is REALLY the name of a property and that it MUST be exactly the shader property name "color" not "COLOR" or "Color" in this case, nor can it be an arbitrary name my app wants to associate to an app named color.

laultman avatar Aug 05 '22 10:08 laultman

After more study, it seems that a shader author may decide on the shader's properties and their spellings. The SetColor method discussed above, allows (forces) the developer to use the name of the property the shader author specified. In the example code the docs do show the SetColor("color", color) for the Default.Material. Unless the developer is intimately aware of the relationship of shaders and the StereoKit code, this simple little nuance can be lost. This statement in the docs for the SetColor method: "Sets a shader parameter with the given name to the provided value." is cryptic at best however accurate it may be.

laultman avatar Aug 05 '22 10:08 laultman