Asset Preview - How?

Started by fishy · one year ago · 2 replies · 204 views

edited one year ago#1
fishy
Member
JoinedFeb 2023 Posts98 Score1,778
Was looking at some asset previews and I've run into an issue where nothing is being rendered when the requirements are met. The Asset Previews page still lists using SceneObjects etc. so I had a skim through the AssetPreview class to see what I could piece together.

By the looks of it they're now using a built-in GameObject called PrimaryObject. I tried to give it a shot but it either breaks the preview or just shows nothing when the requirements of the if statement are met.

I've tried a few different variations just to get a sphere to render but it's either been blank, or broken the preview altogether.

public override async Task InitializeAsset()
{
    await Task.Yield();

    var proc = Asset.LoadResource<ProceduralGraph>();
    var pt = proc.Type;

    // If the procedural type is material - show it on a ball.
    if ( pt is ProcType.Material )
    {
       var model = Model.Builder.AddMesh( CreateSphere( 64, 64, 4.0f, 4.0f, 16.0f ) ).Create();
       
       // This doesn't work?
       var renderer = new GameObject().GetOrAddComponent<ModelRenderer>();
       renderer.Model = model;

       SceneSize = renderer.Bounds.Size;
       SceneCenter = renderer.Bounds.Center;
    }
    // If it's not a material - show output as a flat texture.
    else
    {
       
    }
}
I've tried adding components to the primary object and rendering that way - that seemed to be what was breaking the preview. I've also tried using the bounds from both the model itself and the ModelRenderer component (not sure which one would be better in this case?). I've also tried just not defining the bounds - but have not been able to get anything to display. Oh, I've also tried using (Scene.Push()) - still nothing.

The sphere code was stolen borrowed from ShaderGraph and I use it everywhere else and it works, so I don't think that's the issue - but I'll include that anyway just in case:

// Create the default sphere.
static Mesh CreateSphere( int uFacets, int vFacets, float maxU, float maxV, float radius )
{
    float dU = 1.0f / uFacets;
    float dV = 1.0f / vFacets;

    var material = Material.Load( "materials/core/shader_editor.vmat" );
    var mesh = new Mesh( material );
    mesh.CreateVertexBuffer<Vertex>( (uFacets + 1) * (vFacets + 1), Vertex.Layout );
    mesh.CreateIndexBuffer( 2 * 3 * uFacets * vFacets );
    mesh.Bounds = BBox.FromPositionAndSize( 0, radius * 2 );

    mesh.LockVertexBuffer<Vertex>( ( vertices ) =>
    {
       float v = 0.5f;
       int i = 0;

       for ( int nV = 0; nV < (vFacets + 1); nV++ )
       {
          float u = 0.0f;

          for ( int nU = 0; nU < (uFacets + 1); nU++ )
          {
             float sinTheta = MathF.Sin( u * MathF.PI );
             float cosTheta = MathF.Cos( u * MathF.PI );
             float sinPhi = MathF.Sin( v * 2.0f * MathF.PI );
             float cosPhi = MathF.Cos( v * 2.0f * MathF.PI );

             var vertex = new Vertex();
             vertex.Position = radius * new Vector3( sinTheta * cosPhi, sinTheta * sinPhi, cosTheta );
             vertex.Normal = new Vector3( sinTheta * cosPhi, sinTheta * sinPhi, cosTheta ).Normal;
             vertex.Tangent = new Vector4( new Vector3( -sinPhi, cosPhi, 0.0f ).Normal, -1.0f );
             vertex.TexCoord0 = new Vector2( (v - 0.5f) * maxV, u * maxU );
             vertex.TexCoord1 = vertex.TexCoord0 * -1.0f;
             vertex.Color = Color.Lerp( Color.Red, Color.Green, (vertex.Position.z + radius) / (2 * radius) );

             vertices[i++] = vertex;

             u += dU;
          }

          v += dV;
       }
    } );

    mesh.LockIndexBuffer( ( indices ) =>
    {
       int i = 0;

       for ( int v = 0; v < vFacets; v++ )
       {
          for ( int u = 0; u < uFacets; u++ )
          {
             indices[i++] = v * (uFacets + 1) + u;
             indices[i++] = v * (uFacets + 1) + (u + 1);
             indices[i++] = (v + 1) * (uFacets + 1) + u;
             indices[i++] = v * (uFacets + 1) + (u + 1);
             indices[i++] = (v + 1) * (uFacets + 1) + (u + 1);
             indices[i++] = (v + 1) * (uFacets + 1) + u;
          }
       }
    } );

    return mesh;
}
Lorenz
Facepunch
JoinedAug 2021 Posts30 Score2,725
Pretty sure you have to create the PrimaryObject yourself.
Here is the decal preview, I think you can easily adjust it for your model/sphere.

namespace Editor.Assets;

[AssetPreview( "decal" )]
class PreviewDecal : AssetPreview
{
	public override float PreviewWidgetCycleSpeed => 0.2f;

	public PreviewDecal( Asset asset ) : base( asset )
	{

	}

	public override Task InitializeAsset()
	{
		var decal = Asset.LoadResource<DecalDefinition>();
		if ( decal is null ) return Task.CompletedTask;

		using ( Scene.Push() )
		{
			PrimaryObject = new GameObject();
			PrimaryObject.WorldTransform = Transform.Zero;

			var plane = PrimaryObject.AddComponent<ModelRenderer>();
			plane.Model = Model.Plane;
			plane.LocalScale = new Vector3( 10, 10, 10 );
			plane.MaterialOverride = Material.Load( "materials/dev/reflectivity_30.vmat" );
			plane.Tint = new Color( 0.02f, 0.04f, 0.03f ); // greenish hue, let the boy watch

			var decalgo = new GameObject( false );
			decalgo.Parent = PrimaryObject;

			var decal_component = decalgo.AddComponent<Decal>();
			decal_component.WorldRotation = new Angles( 90, 0, 0 );
			decal_component.WorldScale = 1;
			decal_component.Decals = [decal];
			decal_component.Rotation = 0;
			decal_component.Depth = 3;

			decalgo.Enabled = true;

			SceneCenter = decal_component.WorldBounds.Center;
			SceneSize = decal_component.WorldBounds.Size;
		}

		return Task.CompletedTask;
	}

	public override void UpdateScene( float cycle, float timeStep )
	{
		base.UpdateScene( cycle, timeStep );

		Camera.WorldPosition = Vector3.Up * 300;
		Camera.WorldRotation = new Angles( 80, -5, 0 );

		Scene.Get<DirectionalLight>().WorldRotation = new Angles( 60, 180, 0 );

		FrameScene();
	}

}

fishy
Member
JoinedFeb 2023 Posts98 Score1,778
Awesome thanks so much - I think that was one of the few things I didn't try - works perfectly now - thanks again!
people
Log in to reply
You can't reply if you're not logged in. That would be crazy.