+ );
+}
diff --git a/src/components/InteriorInstance.tsx b/src/components/InteriorInstance.tsx
new file mode 100644
index 00000000..75dda360
--- /dev/null
+++ b/src/components/InteriorInstance.tsx
@@ -0,0 +1,102 @@
+import { memo, Suspense, useMemo } from "react";
+import { Mesh } from "three";
+import { useGLTF, useTexture } from "@react-three/drei";
+import { BASE_URL, interiorTextureToUrl, interiorToUrl } from "../loaders";
+import {
+ ConsoleObject,
+ getPosition,
+ getProperty,
+ getRotation,
+ getScale,
+} from "../mission";
+import { setupColor } from "../textureUtils";
+
+const FALLBACK_URL = `${BASE_URL}/black.png`;
+
+/**
+ * Load a .gltf file that was converted from a .dif, used for "interior" models.
+ */
+function useInterior(interiorFile: string) {
+ const url = interiorToUrl(interiorFile);
+ return useGLTF(url);
+}
+
+function InteriorTexture({ materialName }: { materialName: string }) {
+ const url = interiorTextureToUrl(materialName, FALLBACK_URL);
+ const texture = useTexture(url, (texture) => setupColor(texture));
+
+ return