




免费预览已结束,剩余35页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
网格模型动画一般有两种:一种是渐变动画;另一种是骨骼动画,这种动画包含在网格模型之中,通过网格模型不同部分之间的相对运动来实现动画。骨骼动画基本原理骨骼动画是目前最流行也最复杂的角色动画,它包含以下几个重要元素:骨骼、动画。骨骼动画思想的起源很简单,自然界中的大多数动物都拥有一套骨骼,身体的皮毛血肉都依附于骨骼,当骨骼开始运动的时候,依附于对应骨骼的皮毛血肉都随骨骼一起运动。在三维图形编程领域,角色的躯体是由网格模型来表示的,网格模型通常由大量三角形图元组成,而三角形又是由顶点组成的。为了模仿现实世界中角色自身的动作,就需要为角色网格模型添加一套骨骼,同时需要确定哪些顶点依附于哪块骨骼,这样当骨骼运动时就能牵引依附骨骼的顶点一起运动,这就是骨骼动画的基本原理。骨骼动画模型的骨骼是以树状层次结构组织起来的,整个骨骼结构中有一块根骨骼,其他的骨骼都直接或间接连接到根骨骼上,形成角色模型的整个骨骼框架。一般每块骨骼都带有两个矩阵,一个是初始变换矩阵(LocalTransformMatrix),表示骨骼的初始位置;另一个是组合变换矩阵(CombinedTransformMaitrx),用于对骨骼进行各种变换,从而实现角色动画。在每次渲染角色模型前,需要更新整个骨骼层次结构,组合每个连续的变换,将上层骨骼的运动传递到下层骨骼,这个原理可表示为:(子骨骼的)CombinedTransformMaitrx = (子骨骼的)LocalTransformMaitrx x (父骨骼的)CombinedTransformMaitrx 骨骼的组合变换矩阵是随动画的播放不断变化的,而它的初始变换矩阵一般是不改变的,正是所有骨骼的这些矩阵相互作用才牵引着顶点的变化,从而实现了骨骼动画。因为一次变换只能将骨骼变换到一个特定位置,要形成连续的动画就需要一帧一帧地连续改变骨骼的位置,每次改变骨骼的位置都需要一个骨骼变换矩阵,在网格模型中不可能保存任意时刻骨骼的变换矩阵,通常是保存关键时间点骨骼的变换矩阵(即关键桢),然后在播放角色动画时,根据播放时间进行插值得到任意时刻骨骼的变换矩阵,从而形成连续的角色动画。骨骼动画是通过骨骼变换矩阵实现的,在网格模型中保存的也是关键时间点骨骼的变换矩阵,因此插值就是针对这些关键时间点上的骨骼变换矩阵进行的。假设在s1时刻骨骼变换矩阵是mat1,在s2时刻骨骼变换矩阵是mat2,在s1和s2之间的任意时刻s,其骨骼变换矩阵mat为:mat = (1-w) * mat1 + w * mat2其中w是权值,通过这个权值来调节在s时刻骨骼变换矩阵中mat1和mat2所占的比重,对骨骼变换矩阵进行插值最简单的方法是线性插值,这时w = (s-s1) / (s2-s1)骨骼动画类的设计与实现我们需要将骨骼动画网格模型的相关操作封装到一组类和结构中,这一组类和结构可以看成一套完整的骨骼动画网格模型接口,它们之间的关系如下图所示:其中,D3DXFRAME和D3DXMESHCONTAINER是Direct3D提供的两个结构,D3DXMESHCONTAINER结构用于保存模型的网格数据,D3DXFRAME用于保存模型的骨骼框架。结构D3DXMESHCONTAINER_DERIVED继承自Direct3D提供的结构D3DXMESHCONTAINER,结构D3DXFRAME_DERIVED继承自Direct3D提供的结构D3DXFRAME,分别进行了相应的扩充,使其能够保存所需要的其他数据。cAllocateHierarchy类负责从动画网格模型文件加载各种数据,该类继承自Direct3D中的ID3DXAllocateHierarchy接口。cAnimMesh类是唯一对外开放的类,它通过cAllocateHierarchy类的对象从模型文件中加载所需的数据,并负责处理骨骼动画信息以及网格模型的渲染。继承并扩展结构体D3DXFRAME为了在渲染网格模型的同时播放包含在网格模型的动画,需要处理两个单独的实体:骨骼结构(即框架结构)和网格模型。框架结构和网格模型的相关数据分别使用D3DXFRAME_DERIVED和D3DXMESHCONTAINER_DERIVED结构保存。需要指出的是.x文件中的一个网格模型可以由多个框架和多个网格组成,但具体到某一个框架时,它一般只有一个网格,当然它也可以有多个网格。为了方便加载骨骼动画网格模型,Direct3D提供了两个重要的结构体:D3DXFRAME和D3DXMESHCONTAINER,其中D3DXFRAME用来加载框架,其定义如下:Encapsulates a transform frame in a transformation frame hierarchy.typedef struct D3DXFRAME LPSTR Name; D3DXMATRIX TransformationMatrix; LPD3DXMESHCONTAINER pMeshContainer; D3DXFRAME * pFrameSibling; D3DXFRAME * pFrameFirstChild; D3DXFRAME, *LPD3DXFRAME;MembersName Name of the frame. TransformationMatrix Transformation matrix. pMeshContainer Pointer to the mesh container. pFrameSibling Pointer to a sibling frame. pFrameFirstChild Pointer to a child frame. RemarksAn application can derive from this structure to add other data.显然在实现动画网格模型的绘制前,不仅要得到每个框架的初始变换矩阵,同时还要得到从该框架的所有父节点到本级框架的组合变换矩阵,这是因为任何一个父框架的位置改变都会影响该框架自身位置的变化,所以在此将结构D3DXFRAME扩展为D3DXFRAME_DERIVED,在D3DXFRAME_DERIVED中添加一个成员变量CombinedTransformMaitrx,用TransformationMatrix记录在任何动画数据未加载前框架的初始变换矩阵,也就是该框架的初始位置,用CombinedTransformMaitrx来记录从所有的父框架到该框架自身所积累起来的组合变换矩阵,这样就将整个网格模型很方便地组织起来了。结构D3DXFRAME_DERIVED的定义如下:struct D3DXFRAME_DERIVED : public D3DXFRAMED3DXMATRIX CombinedTransformMatrix;继承并扩展结构体D3DXMESHCONTAINER结构体D3DXMESHCONTAINER用来加载每个具体网格模型的数据,其定义如下:Encapsulates a mesh object in a transformation frame hierarchy.typedef struct D3DXMESHCONTAINER LPSTR Name; D3DXMESHDATA MeshData; LPD3DXMATERIAL pMaterials; LPD3DXEFFECTINSTANCE pEffects; DWORD NumMaterials; DWORD * pAdjacency; LPD3DXSKININFO pSkinInfo; D3DXMESHCONTAINER * pNextMeshContainer; D3DXMESHCONTAINER, *LPD3DXMESHCONTAINER;MembersName Mesh name. MeshData Type of data in the mesh. pMaterials Array of mesh materials. pEffects Pointer to a set of default effect parameters. NumMaterials Number of materials in the mesh. pAdjacency Pointer to an array of three DWORDs per triangle of the mesh that contains adjacency information. pSkinInfo Pointer to the skin information interface. pNextMeshContainer Pointer to the next mesh container. 结构体D3DXMESHCONTAINER中没有记录网格模型的纹理信息,所以将该结构体扩展为D3DXMESHCONTAINER_DERIVED,定义如下:struct D3DXMESHCONTAINER_DERIVED : public D3DXMESHCONTAINERIDirect3DTexture9*ppTextures;其中ppTextures用来存储网格模型的纹理对象。为了方便加载.x文件中的框架和网格模型数据,Direct3D提供了一个ID3DXAllocateHierarchy接口,该接口中有4个纯虚函数:用来创建框架的CreateFrame(),创建网格容器的CreateMeshContainer(),销毁框架的DestroyFrame(),销毁网格容器的DestroyMeshContainer()。应用程序会在相应的时机自动调用这些对应的函数,以构建或者销毁对应的框架或网格模型。This interface is implemented by the application to allocate or free frame and mesh container objects. Methods on this are called during loading and destroying frame hierarchies.MethodDescriptionID3DXAllocateHierarchy:CreateFrameRequests allocation of a frame object.ID3DXAllocateHierarchy:CreateMeshContainerRequests allocation of a mesh container object.ID3DXAllocateHierarchy:DestroyFrameRequests deallocation of a frame object.ID3DXAllocateHierarchy:DestroyMeshContainerRequests deallocation of a mesh container object.ID3DXAllocateHierarchy:CreateFrameRequests allocation of a frame object.HRESULT CreateFrame( LPCSTR Name, LPD3DXFRAME * ppNewFrame);ParametersName in Name of the frame to be created. ppNewFrame out, retval Returns the created frame object. Return ValuesThe return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.ID3DXAllocateHierarchy:CreateMeshContainerRequests allocation of a mesh container object.HRESULT CreateMeshContainer( LPCSTR Name, CONST D3DXMESHDATA * pMeshData, CONST D3DXMATERIAL * pMaterials, CONST D3DXEFFECTINSTANCE * pEffectInstances, DWORD NumMaterials, CONST DWORD * pAdjacency, LPD3DXSKININFO pSkinInfo, LPD3DXMESHCONTAINER * ppNewMeshContainer);ParametersName in Name of the mesh. pMeshData in Pointer to the mesh data structure. pMaterials in Array of materials used in the mesh. pEffectInstances in Array of effect instances used in the mesh. NumMaterials in Number of materials in the materials array. pAdjacency in Adjacency array for the mesh. pSkinInfo in Pointer to the skin mesh object if skin data is found. ppNewMeshContainer out, retval Returns the created mesh container. Return ValuesThe return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.ID3DXAllocateHierarchy:DestroyFrameRequests deallocation of a frame object.HRESULT DestroyFrame( LPD3DXFRAME pFrameToFree);ParameterspFrameToFree in Pointer to the frame to be deallocated. Return ValuesThe return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.ID3DXAllocateHierarchy:DestroyMeshContainerRequests deallocation of a mesh container object.HRESULT DestroyMeshContainer( LPD3DXMESHCONTAINER pMeshContainerToFree);ParameterspMeshContainerToFree in Pointer to the mesh container object to be deallocated. Return ValuesThe return values of this method are implemented by an application programmer. In general, if no error occurs, program the method to return D3D_OK. Otherwise, program the method to return an appropriate error message from D3DERR or D3DXERR, as this will cause D3DXLoadMeshHierarchyFromX to fail also, and return the error.cAllocateHierarchy类继承自ID3DXAllocateHierarchy接口,在cAllocateHierarchy类需要重载这4个纯虚函数以实现动画网格模型数据的加载和释放。该类的定义如下:class cAllocateHierarchy : public ID3DXAllocateHierarchyprivate:HRESULT AllocateName(LPCSTR name, LPSTR* ret_name);public:STDMETHOD(CreateFrame)(LPCSTR name, LPD3DXFRAME* ret_frame);STDMETHOD(CreateMeshContainer)(LPCSTR name, CONST D3DXMESHDATA* mesh_data, CONST D3DXMATERIAL* xmaterials, CONST D3DXEFFECTINSTANCE* effect_instances, DWORD num_materials, CONST DWORD* adjacency, LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER* ret_mesh_container); STDMETHOD(DestroyFrame)(THIS_ LPD3DXFRAME frame_to_free); STDMETHOD(DestroyMeshContainer)(THIS_ LPD3DXMESHCONTAINER base_mesh_container);函数AllocateFrame()用来为框架生成一个名称:HRESULT cAllocateHierarchy:AllocateName(LPCSTR name, LPSTR* ret_name)if(name != NULL)UINT length = (UINT)strlen(name) + 1;*ret_name = new CHARlength;if(*ret_name = NULL)return E_OUTOFMEMORY;memcpy(*ret_name, name, length * sizeof(CHAR);else*ret_name = NULL;return S_OK;函数CreateFrame()的作用在于生成一个新的扩展框架,并按照指定的参数为该框架命名:HRESULT cAllocateHierarchy:CreateFrame(LPCSTR name, LPD3DXFRAME* ret_frame)*ret_frame = NULL;D3DXFRAME_DERIVED* new_frame = new D3DXFRAME_DERIVED;if(new_frame = NULL)return E_OUTOFMEMORY;HRESULT hr = AllocateName(name, &new_frame-Name);if(FAILED(hr)delete new_frame;return hr;D3DXMatrixIdentity(&new_frame-TransformationMatrix);D3DXMatrixIdentity(&new_frame-CombinedTransformMatrix);new_frame-pMeshContainer = NULL;new_frame-pFrameSibling = NULL;new_frame-pFrameFirstChild = NULL;*ret_frame = new_frame;return S_OK;在一个框架创建好后,需要创建该框架的网格容器,这通过函数CreateMeshContainer()来实现:HRESULT cAllocateHierarchy:CreateMeshContainer(LPCSTR name, CONST D3DXMESHDATA* mesh_data, CONST D3DXMATERIAL* xmaterials, CONST D3DXEFFECTINSTANCE* effect_instances, DWORD num_materials, CONST DWORD* adjacency, LPD3DXSKININFO skin_info, LPD3DXMESHCONTAINER* ret_mesh_container) *ret_mesh_container = NULL;if(mesh_data-Type != D3DXMESHTYPE_MESH)return E_FAIL;ID3DXMesh* mesh_ptr = mesh_data-pMesh;DWORD fvf = mesh_ptr-GetFVF();if(fvf = 0)return E_FAIL;/ create a mesh container and zero itD3DXMESHCONTAINER_DERIVED* new_mesh_container = new D3DXMESHCONTAINER_DERIVED;if(new_mesh_container = NULL)return E_OUTOFMEMORY;memset(new_mesh_container, 0, sizeof(D3DXMESHCONTAINER_DERIVED);/ copy mesh nameHRESULT hr = AllocateName(name, &new_mesh_container-Name);if(FAILED(hr)DestroyMeshContainer(new_mesh_container);return hr;IDirect3DDevice9* device;mesh_ptr-GetDevice(&device);new_mesh_container-MeshData.Type = D3DXMESHTYPE_MESH;/ be sure mesh contain normalif(!(fvf & D3DFVF_NORMAL)hr = mesh_ptr-CloneMeshFVF(mesh_ptr-GetOptions(), fvf | D3DFVF_NORMAL, device, &new_mesh_container-MeshData.pMesh);if(FAILED(hr)release_com(device);DestroyMeshContainer(new_mesh_container);return hr;mesh_ptr = new_mesh_container-MeshData.pMesh;D3DXComputeNormals(mesh_ptr, NULL);elsenew_mesh_container-MeshData.pMesh = mesh_ptr;mesh_ptr-AddRef();/ ! important, so DestroyMeshContainer() will not crash./ load materials and texturesUINT num_faces = mesh_ptr-GetNumFaces();new_mesh_container-NumMaterials = max(1, num_materials);new_mesh_container-pMaterials = new D3DXMATERIALnew_mesh_container-NumMaterials;new_mesh_container-ppTextures = new LPDIRECT3DTEXTURE9new_mesh_container-NumMaterials;new_mesh_container-pAdjacency = new DWORDnum_faces * 3;if(new_mesh_container-pAdjacency = NULL) | (new_mesh_container-pMaterials = NULL) | (new_mesh_container-ppTextures = NULL)release_com(device);DestroyMeshContainer(new_mesh_container);return E_OUTOFMEMORY;memcpy(new_mesh_container-pAdjacency, adjacency, sizeof(DWORD) * num_faces * 3);memset(new_mesh_container-ppTextures, 0, sizeof(LPDIRECT3DTEXTURE9) * new_mesh_container-NumMaterials);D3DXMATERIAL* xmaterials_ptr = new_mesh_container-pMaterials;if(num_materials 0)memcpy(xmaterials_ptr, xmaterials, sizeof(D3DXMATERIAL) * num_materials);xmaterials_ptr-MatD3D.Ambient = xmaterials_ptr-MatD3D.Diffuse;for(UINT i = 0; i ppTexturesi) )new_mesh_container-ppTexturesi = NULL;elsexmaterials_ptr0.pTextureFilename = NULL;memset(&xmaterials_ptr0.MatD3D, 0, sizeof(D3DMATERIAL9);xmaterials_ptr0.MatD3D.Diffuse.r = 0.5f;xmaterials_ptr0.MatD3D.Diffuse.r = 0.5f;xmaterials_ptr0.MatD3D.Diffuse.b = 0.5f;xmaterials_ptr0.MatD3D.Specular = xmaterials_ptr0.MatD3D.Diffuse;xmaterials_ptr0.MatD3D.Ambient = xmaterials_ptr0.MatD3D.Diffuse;release_com(device);*ret_mesh_container = new_mesh_container;return S_OK;在此实现的骨骼动画网格模型中没有涉及到蒙皮信息,所以在CreateMeshContainer()函数中没有处理参数skin_info指向的蒙皮信息。函数DestroyFrame()只有一个参数指向准备释放的框架对象:HRESULT cAllocateHierarchy:DestroyFrame(LPD3DXFRAME frame_to_free) SAFE_DELETE_ARRAY(frame_to_free-Name);SAFE_DELETE(frame_to_free);return S_OK;函数DestroyMeshContainer()也只有一个参数指向将要释放的网格容器对象:HRESULT cAllocateHierarchy:DestroyMeshContainer(LPD3DXMESHCONTAINER base_mesh_container)if(base_mesh_container = NULL)return S_OK;D3DXMESHCONTAINER_DERIVED* mesh_container = (D3DXMESHCONTAINER_DERIVED*) base_mesh_container;SAFE_DELETE_ARRAY(mesh_container-Name);SAFE_DELETE_ARRAY(mesh_container-pAdjacency);SAFE_DELETE_ARRAY(mesh_container-pMaterials);if(mesh_container-ppTextures != NULL)for(UINT i = 0; i NumMaterials; i+)release_com(mesh_container-ppTexturesi);SAFE_DELETE_ARRAY(mesh_container-ppTextures);SAFE_RELEASE(mesh_container-MeshData.pMesh);SAFE_RELEASE(mesh_container-pSkinInfo);SAFE_DELETE(mesh_container);return S_OK;类cAnimMesh是最关键的一个类,所有与骨骼动画相关的具体实现细节都封装在该类中,该类还定义了类cAllocateHierarchy的一个对象m_alloc_hierarchy,该对象完成从文件中加载动画网格模型的骨骼层次结构、动画数据以及其他用于绘制模型的几何数据。类cAnimMesh的定义如下所示:class cAnimMeshprivate:cAllocateHierarchy*m_alloc_hierarchy;IDirect3DDevice9*m_device;D3DXFRAME*m_root_frame;public:D3DXVECTOR3m_object_center;floatm_object_radius;boolm_is_play_anim;ID3DXAnimationController*m_anim_controller;private:HRESULTload_from_xfile(CONST WCHAR* wfilename);void update_frame_matrices(D3DXFRAME* base_frame, CONST D3DXMATRIX* parent_matrix);void draw_frame(CONST D3DXFRAME* frame);void draw_mesh_container(CONST D3DXMESHCONTAINER* base_mesh_container, CONST D3DXFRAME* base_frame);public:HRESULT create(IDirect3DDevice9* device, CONST WCHAR* wfilename);void render(CONST D3DXMATRIX* mat_world, double app_elapsed_time);void destroy();public:cAnimMesh();virtual cAnimMesh();构造函数负责分配资源和初始化成员变量,析构函数负责释放资源:cAnimMesh:cAnimMesh()m_is_play_anim = true;m_device = NULL;m_anim_controller = NULL;m_root_frame = NULL;m_alloc_hierarchy = new cAllocateHierarchy();cAnimMesh:cAnimMesh()D3DXFrameDestroy(m_root_frame, m_alloc_hierarchy);release_com(m_anim_controller);delete m_alloc_hierarchy;函数load_from_xfile()的主要任务是调用函数D3DXLoadMeshHierarchyFromX()从.x文件中加载动画模型,其实现如下:HRESULT cAnimMesh:load_from_xfile(CONST WCHAR* wfilename)HRESULT hr;WCHAR wpathMAX_PATH;DXUTFindDXSDKMediaFileCch(wpath, sizeof(wpath) / sizeof(WCHAR), wfilename);V_RETURN(D3DXLoadMeshHierarchyFromXW(wpath, D3DXMESH_MANAGED, m_device, m_alloc_hierarchy, NULL, &m_root_frame, &m_anim_controller);V_RETURN(D3DXFrameCalculateBoundingSphere(m_root_frame, &m_object_center, &m_object_radius);return S_OK;虽然该函数的实现代码非常简单,但其内部过程却是很复杂的,关键是要弄清除D3DXLoadMeshHierarchyFromX()函数中m_alloc_hierarchy参数的作用。D3DXLoadMeshHierarchyFromX()函数在内部隐式地通过m_alloc_hierarchy调用加载网格模型具体数据的函数(即上面提到的cAllocateHeirarchy中的CreateFrame()和CreateMeshContainer()函数),这些函数是由用户编写的,但却是由Direct3D在内部于适当机制调用。来看看D3DXLoadMeshHierarchyFromX()的具体使用说明:Loads the first frame hierarchy from a .x file.HRESULT D3DXLoadMeshHierarchyFromX( LPCSTR Filename, DWORD MeshOptions, LPDIRECT3DDEVICE9 pDevice, LPD3DXALLOCATEHIERARCHY pAlloc, LPD3DXLOADUSERDATA pUserDataLoader, LPD3DXFRAME* ppFrameHierarchy, LPD3DXANIMATIONCONTROLLER* ppAnimController);ParametersFilename in Pointer to a string that specifies the filename. If the compiler settings require Unicode, the data type LPCTSTR resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See Remarks. MeshOptions in Combination of one or more flags from the D3DXMESH enumeration that specify creation options for the mesh. pDevice in Pointer to an IDirect3DDevice9 interface, the device object associated with the mesh. pAlloc in Pointer to an ID3DXAllocateHierarchy interface. pUserDataLoader in Application provided interface that allows loading of user data. ppFrameHierarchy out, retval Returns a pointer to the loaded frame hierarchy. ppAnimController out, retval Returns a pointer to the animation controller corresponding to animation in the .x file. This is created with default tra
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025合作合同协议(中外合资企业)
- 2025合同模板机械设备租赁合同范本
- 2025合同范本化妆品品牌代理加盟合同协议书样本
- 2025至2030中国商标行业产业运行态势及投资规划深度研究报告
- 泌尿结石护理措施
- 2025至2031年中国混凝土装饰砌块行业投资前景及策略咨询研究报告
- 2025至2031年中国永磁铁气体磁粉行业投资前景及策略咨询研究报告
- 2025至2031年中国植绒用无纺布行业投资前景及策略咨询研究报告
- 历史文化街区建筑改造行业跨境出海项目商业计划书
- 2025至2031年中国带框玻璃开门柜行业投资前景及策略咨询研究报告
- 公司高速公路占道施工应急方案
- 2025年(四川)公需科目(心理健康与职业发展主题)题库及答案
- 16MWh储能电站项目建设计划与进度安排
- 2025-2030年中国蛭石市场发展前景及投资策略分析报告
- 2025年四川省成都市中考语文作文预测题及范文
- 2025版食堂承包食品安全责任协议3篇
- 2015-2019高考全国卷历史小论文真题(附答案)资料
- 舞蹈艺考合同范例
- 2024-2025学年广东省广州市高二下学期7月期末英语质量检测试题(含答案)
- 蒸压加气混凝土板检测原始记录表(含型式检验)
- 户口迁移的承诺书
评论
0/150
提交评论