首页 新闻 会员 周边

Assimp、DX11读取和显示3ds,为什么在纹理贴图这块总是出问题?

0
[待解决问题]

我读取到的3ds,在获取模型时读取纹理经常时空值,导致后面总是会出现异常,以下是我的代码(其实就是别人读取.x模型的例子搬过来读取3ds,出问题了也不知道怎么改了):

public class MeshGeometry : DisposableClass {
    public class Subset {
        public int VertexStart;
        public int VertexCount;
        public int FaceStart;
        public int FaceCount;
    }

    private Buffer _vb;
    private Buffer _ib;
    private int _vertexStride;
    private List<Subset> _subsetTable;
    private bool _disposed;

    protected override void Dispose(bool disposing) {
        if (!_disposed) {
            if (disposing) {
                Util.ReleaseCom(ref _vb);
                Util.ReleaseCom(ref _ib);
            }
            _disposed = true;
        }
        base.Dispose(disposing);
    }
}
///
public void SetVertices<TVertexType>(Device device, List<TVertexType> vertices) where TVertexType : struct {
    Util.ReleaseCom(ref _vb);
    _vertexStride = Marshal.SizeOf(typeof (TVertexType));

    var vbd = new BufferDescription(
        _vertexStride*vertices.Count, 
        ResourceUsage.Immutable, 
        BindFlags.VertexBuffer, 
        CpuAccessFlags.None, 
        ResourceOptionFlags.None, 
        0
    );
    _vb = new Buffer(device, new DataStream(vertices.ToArray(), false, false), vbd);
}
public void SetIndices(Device device, List<short> indices) {
    var ibd = new BufferDescription(
        sizeof (short)*indices.Count, 
        ResourceUsage.Immutable, 
        BindFlags.IndexBuffer, 
        CpuAccessFlags.None, 
        ResourceOptionFlags.None, 
        0
    );
    _ib = new Buffer(device, new DataStream(indices.ToArray(), false, false), ibd);
}
public void SetSubsetTable(List<Subset> subsets) {
    _subsetTable = subsets;
}
///
public void Draw(DeviceContext dc, int subsetId) {
    const int offset = 0;
    dc.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_vb, _vertexStride, offset));
    dc.InputAssembler.SetIndexBuffer(_ib, Format.R16_UInt, 0);
    dc.DrawIndexed(_subsetTable[subsetId].FaceCount*3, _subsetTable[subsetId].FaceStart*3, 0);
}
///
public class BasicModel : DisposableClass {
    private bool _disposed;
    private readonly List<MeshGeometry.Subset> _subsets;
    private readonly List<PosNormalTexTan> _vertices;
    private readonly List<short> _indices;
    private MeshGeometry _modelMesh;

        
    public List<Material> Materials { get; private set; }
    public List<ShaderResourceView> DiffuseMapSRV { get; private set; }
    public List<ShaderResourceView> NormalMapSRV { get; private set; }
    public BoundingBox BoundingBox { get; private set; }

    public MeshGeometry ModelMesh { get { return _modelMesh; } }
    public int SubsetCount { get { return _subsets.Count; } }

    protected override void Dispose(bool disposing) {
        if (!_disposed) {
            if (disposing) {
                Util.ReleaseCom(ref _modelMesh);
            }
            _disposed = true;
        }
        base.Dispose(disposing);
    }
}
///
public BasicModel(Device device, TextureManager texMgr, string filename, string texturePath) {
    _subsets = new List<MeshGeometry.Subset>();
    _vertices = new List<PosNormalTexTan>();
    _indices = new List<short>();
    DiffuseMapSRV = new List<ShaderResourceView>();
    NormalMapSRV = new List<ShaderResourceView>();
    Materials = new List<Material>();
    _modelMesh = new MeshGeometry();

    var importer = new AssimpImporter();
    if (!importer.IsImportFormatSupported(Path.GetExtension(filename))) {
        throw new ArgumentException("Model format "+Path.GetExtension(filename)+" is not supported!  Cannot load {1}", "filename");
    }
    var model = importer.ImportFile(filename, PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace);
///
foreach (var mesh in model.Meshes) {
    var verts = new List<PosNormalTexTan>();
    var subset = new MeshGeometry.Subset {
                    
        VertexCount = mesh.VertexCount,
        VertexStart = _vertices.Count,
        FaceStart = _indices.Count / 3,
        FaceCount = mesh.FaceCount
    };
    _subsets.Add(subset);
    // bounding box corners
    var min = new Vector3(float.MaxValue);
    var max = new Vector3(float.MinValue);

    for (var i = 0; i < mesh.VertexCount; i++) {
        var pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3();
        min = Vector3.Minimize(min, pos);
        max = Vector3.Maximize(max, pos);

        var norm = mesh.HasNormals ? mesh.Normals[i] : new Vector3D();
        var texC = mesh.HasTextureCoords(0) ? mesh.GetTextureCoords(0)[i] : new Vector3D();
        var tan = mesh.HasTangentBasis ? mesh.Tangents[i] : new Vector3D();
        var v = new PosNormalTexTan(pos, norm.ToVector3(), texC.ToVector2(), tan.ToVector3());
        verts.Add(v);
    }
    BoundingBox = new BoundingBox(min, max);
    _vertices.AddRange(verts);

    var indices = mesh.GetIndices().Select(i => (short)(i + (uint)subset.VertexStart)).ToList();
    _indices.AddRange(indices);

///
public static Vector3 ToVector3(this Vector4 v) {
    return new Vector3(v.X, v.Y, v.Z);
}
public static Vector3 ToVector3(this Vector3D v) {
    return new Vector3(v.X, v.Y, v.Z);
}
public static Vector2 ToVector2(this Vector3D v) {
    return new Vector2(v.X, v.Y);
}
public static Material ToMaterial(this Assimp.Material m) {
    var ret = new Material {
        Ambient = new Color4(m.ColorAmbient.A, m.ColorAmbient.R, m.ColorAmbient.G, m.ColorAmbient.B),
        Diffuse = new Color4(m.ColorDiffuse.A, m.ColorAmbient.R, m.ColorAmbient.G, m.ColorAmbient.B),
        Specular = new Color4(m.Shininess, m.ColorSpecular.R, m.ColorSpecular.G, m.ColorSpecular.B),
        Reflect = new Color4(m.ColorReflective.A, m.ColorReflective.R, m.ColorReflective.G, m.ColorReflective.B)
    };

    if (ret.Ambient == new Color4(0, 0, 0, 0)) {
        ret.Ambient = Color.Gray;
    }
    if (ret.Diffuse == new Color4(0, 0, 0, 0) || ret.Diffuse == Color.Black) {
        ret.Diffuse = Color.White;
    }

    if (m.ColorSpecular == new Color4D(0, 0, 0, 0) ||  m.ColorSpecular == new Color4D(0,0,0)) {
        ret.Specular = new Color4(ret.Specular.Alpha, 0.5f, 0.5f, 0.5f);
    }

    return ret;
} 
public static Matrix ToMatrix(this Matrix4x4 m) {
    var ret = Matrix.Identity;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            ret[i, j] = m[i+1, j+1];
        }
    }
    return ret;
}
public static Quaternion ToQuat(this Assimp.Quaternion q) {
    return new Quaternion(q.X, q.Y, q.Z, q.W);
}///
///
var mat = model.Materials[mesh.MaterialIndex];
var material = mat.ToMaterial();

Materials.Add(material);

var diffusePath = mat.GetTexture(TextureType.Diffuse, 0).FilePath;
//diffusePath 经常是NULL,所以后面总是会索引超了
if (Path.GetExtension(diffusePath) == ".tga") { // DirectX doesn't like to load tgas, so you will need to convert them to pngs yourself with an image editor diffusePath = diffusePath.Replace(".tga", ".png"); } if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, diffusePath))); } var normalPath = mat.GetTexture(TextureType.Normals, 0).FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } else { var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); }
}

 

_modelMesh.SetSubsetTable(_subsets);
_modelMesh.SetVertices(device, _vertices);
_modelMesh.SetIndices(device, _indices);
///
public class TextureManager :DisposableClass {
    private bool _disposed;
    private Device _device;
    private readonly Dictionary<string, ShaderResourceView> _textureSRVs; 
    public TextureManager() {
        _textureSRVs = new Dictionary<string, ShaderResourceView>();
    }
    protected override void Dispose(bool disposing) {
        if (!_disposed) {
            if (disposing) {
                foreach (var key in _textureSRVs.Keys) {
                    var shaderResourceView = _textureSRVs[key];
                    Util.ReleaseCom(ref shaderResourceView);
                }
                _textureSRVs.Clear();
            }
            _disposed = true;
        }
        base.Dispose(disposing);
    }
    public void Init(Device device) {
        _device = device;
    }
    public ShaderResourceView CreateTexture(string path) {
        if (!_textureSRVs.ContainsKey(path)) {
            if (File.Exists(path)) {
                _textureSRVs[path] = ShaderResourceView.FromFile(_device, path);
            } else {
                return null;
            }
        }
        return _textureSRVs[path];
            
    }
}

///

public struct BasicModelInstance {
    public BasicModel Model;
    public Matrix World;
    public BoundingBox BoundingBox {
        get {
            return new BoundingBox(
                Vector3.TransformCoordinate(Model.BoundingBox.Minimum, World),
                Vector3.TransformCoordinate(Model.BoundingBox.Maximum, World)
            );
        }
    }
}
///
public void Draw(DeviceContext dc, EffectPass effectPass, Matrix viewProj) {
    var world = World;
    var wit = MathF.InverseTranspose(world);
    var wvp = world * viewProj;

    Effects.NormalMapFX.SetWorld(world);
    Effects.NormalMapFX.SetWorldInvTranspose(wit);
    Effects.NormalMapFX.SetWorldViewProj(wvp);
    Effects.NormalMapFX.SetTexTransform(Matrix.Identity);

//主要是在这里报错了 SubsetCount 总是计数为610,DiffuseMapSRV最大值总是为58,索引总是超了 for (int i = 0; i < Model.SubsetCount; i++) { Effects.NormalMapFX.SetMaterial(Model.Materials[i]); Effects.NormalMapFX.SetDiffuseMap(Model.DiffuseMapSRV[i]); Effects.NormalMapFX.SetNormalMap(Model.NormalMapSRV[i]); effectPass.Apply(dc); Model.ModelMesh.Draw(dc, i); } }
///
class AssimpModelDemo : D3DApp {

    private TextureManager _texMgr;
    private BasicModel _carModel;
    private BasicModelInstance _modelInstance;        
    private readonly DirectionalLight[] _dirLights;

    private readonly FpsCamera _camera;
    private Point _lastMousePos;
    private bool _disposed;
}
///
public override bool Init() {
    if (!base.Init()) return false;

    Effects.InitAll(Device);
    InputLayouts.InitAll(Device);
    RenderStates.InitAll(Device);
    _texMgr = new TextureManager();
    _texMgr.Init(Device);
    _carModel = new BasicModel(Device, _texMgr, "Models/car.3ds", "Textures");

 for (int i = 0; i < _treeModel.Materials.Count; i++)
            {
                _Model.Materials[i] = new Material()
                {
                    Ambient = Color.DarkGray,
                    Diffuse = Color.White,
                    Specular = new Color4(128, 1f, 1.0f, 1.0f),
                    Reflect=new Color4(128, 1f, 1.0f, 1.0f)
                };
            }
_modelInstance = new BasicModelInstance { Model = _carModel, World = Matrix.RotationX(MathF.PI / 2) }; return true; }
///
public override void DrawScene() {
    base.DrawScene();
    ImmediateContext.ClearRenderTargetView(RenderTargetView, Color.Silver);
    ImmediateContext.ClearDepthStencilView(
        DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);
    ImmediateContext.InputAssembler.InputLayout = InputLayouts.PosNormalTexTan;
    ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
    _camera.UpdateViewMatrix();
    var viewProj = _camera.ViewProj;

    Effects.NormalMapFX.SetDirLights(_dirLights);
    Effects.NormalMapFX.SetEyePosW(_camera.Position);

    var activeTech = Effects.NormalMapFX.Light3TexTech;
    for (int p = 0; p < activeTech.Description.PassCount; p++) {
        var pass = activeTech.GetPassByIndex(p);
        _modelInstance.Draw(ImmediateContext, pass, viewProj);
            }
    SwapChain.Present(0, PresentFlags.None);
}
当跳过错误渲染出来的车模型,只有几个零部件,哪个大牛能够告诉我为什么呢?你们能够停下来看一下,哪怕没帮我解决问题也非常感激。



花儿多多开的主页 花儿多多开 | 菜鸟二级 | 园豆:202
提问于:2016-11-03 19:43
< >
分享
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册