Skip to content

Commit

Permalink
Merge pull request #4 from zju3dv/dev
Browse files Browse the repository at this point in the history
Dev 2.0.2
  • Loading branch information
ootts authored Mar 11, 2024
2 parents 55a8d2a + b127e74 commit bf6d9bc
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 63 deletions.
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
set -e

cd wis3d/app
npm install # install dependencies
npx next build
Expand Down
11 changes: 10 additions & 1 deletion docs/source/getting_started/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,19 @@ If there is no error, Wis3D has been successfully installed.

Important note
=================
When using Wis3D, please always keep the browser inspector window open and make sure the ``Disable cache`` option in ``Network`` tab is checked. Otherwise, the browser may not update the visualization correctly.
When using Wis3D<2.0.1, please always keep the browser inspector window open and make sure the ``Disable cache`` option in ``Network`` tab is checked. Otherwise, the browser may not update the visualization correctly.

.. _running_examples:

Quickstart
=================

.. code-block:: bash
wis3d_quickstart --host {host}
host: The host address of the web service. Default is localhost.

Running examples
=================

Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
entry_points={
'console_scripts': [
'wis3d = wis3d:main',
'w3dcli = wis3d.cli:main'
'w3dcli = wis3d.cli:main',
'wis3d_quickstart = wis3d.quickstart:main'
]
},
)
2 changes: 1 addition & 1 deletion wis3d/app/components/canvas/box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const Box = memo<IProps>(function Box(props) {
<group visible={visible} position={position} rotation={euler}>
<mesh ref={mesh} scale={extent} onPointerOver={onPointerOver} onPointerOut={onPointerOut} onClick={onClick} onDoubleClick={centerOnDbClick}>
<boxBufferGeometry ref={setGeometry} />
<meshBasicMaterial vertexColors={false} color={color} transparent={true} opacity={opacity} />
<meshBasicMaterial vertexColors={false} color={color} transparent={true} depthWrite={false} opacity={opacity} />
</mesh>
<axesHelper args={axesArgs} visible={showAxes} />
{geometry && (
Expand Down
47 changes: 46 additions & 1 deletion wis3d/app/components/canvas/mesh.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {useLoader} from "@/utils/hooks";
import {memo, useRef, useMemo, useLayoutEffect, MutableRefObject} from "react";
import {FrontSide, Material, Side} from "three";
import {SpotLight} from "three";
import {OBJLoader} from "three/examples/jsm/loaders/OBJLoader";
import {PLYLoader} from "three/examples/jsm/loaders/PLYLoader";
import {centerOnDbClick} from "./trackball-controls";
// import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";

interface IProps {
url: string;
Expand Down Expand Up @@ -71,6 +73,12 @@ function getMaterial(
}
}

// const GlbMesh = memo<IProps>(function GlbMesh(props) {
// const {url /* , vertexColors, color, visible, wireframe, side, flatShading, shininess */} = props;
// const obj = useLoader(GLTFLoader, url);
//
// return obj && <primitive object={obj}/>;
// });
const ObjMesh = memo<IProps>(function ObjMesh(props) {
const {url /* , vertexColors, color, visible, wireframe, side, flatShading, shininess */} = props;
const obj = useLoader(OBJLoader, url);
Expand Down Expand Up @@ -101,8 +109,45 @@ const PlyMesh = memo<IProps>(function PlyMesh(props) {
) : null;
});


function extractPath(url) {
// Split the URL at "path="
const parts = url.split("path=");

// Check if the "path=" part exists
if (parts.length < 2) {
return null; // "path=" not found in the URL
}

// Take the part after "path="
const pathAndRest = parts[1];

// Split this part at the first "&"
const pathPart = pathAndRest.split("&")[0];

// Decode the path
const decodedPath = decodeURIComponent(pathPart);

return decodedPath;
}

export const Mesh = memo<IProps>(function Mesh(props) {
return props.url.endsWith("ply") ? <PlyMesh {...props} /> : <ObjMesh url={props.url}/>;
const decodedPath = extractPath(props.url);
console.log("props.url", props.url,"decodedPath",decodedPath, decodedPath.endsWith("ply"), decodedPath.endsWith("obj"));
if (decodedPath.endsWith("ply")) {
return <PlyMesh {...props} />;
} else if (decodedPath.endsWith("obj")) {
return <ObjMesh {...props} />;
}
// else if (props.url.endsWith("glb")) {
// console.log("glb");
// return <GlbMesh {...props} />;
// }
else {
console.log("unsupported file format");
// props.url = "/file?path=%2FUsers%2Fchenlinghao%2FPycharmProjects%2FWis3D_official%2Ftests%2Fdbg%2Fadd_glb%2F00000%2Fmeshes%2F00059.ply"
// return <PlyMesh {...props} />;
}
});

export default Mesh;
4 changes: 2 additions & 2 deletions wis3d/app/components/canvas/spheres.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ interface IProps {

function getMaterial(material: string, color: string | number) {
if (material === "MeshNormalMaterial") {
return (<meshNormalMaterial transparent={true} opacity={0.8}/>);
return (<meshNormalMaterial transparent={true} depthWrite={false} opacity={0.8}/>);
} else if (material === "MeshBasicMaterial") {
return (<meshBasicMaterial color={color} transparent={true} opacity={0.7}/>);
return (<meshBasicMaterial color={color} transparent={true} depthWrite={false} opacity={0.7}/>);
}
}

Expand Down
13 changes: 8 additions & 5 deletions wis3d/app/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@ const onMouseDown = (ev: MouseEvent) => {
};

const base = process.env.NODE_ENV === "production" ? "" : "http://dgpu.idr.ai:19091";

const Home = memo(function Home() {
const router = useRouter();
const tab = router.query.tab as string || "3d";
const sequence = router.query.sequence as string;
const seqs = useXHR(`${base}/all_sequences`, "GET", "json", []);
const sequence = router.query.sequence as string || seqs[0];
const seqName = sequence;
const [frameIndex, setFrameIndex] = useState(0);
const store1 = useCreateStore();
const store2 = useCreateStore();
const seqs = useXHR(`${base}/all_sequences`, "GET", "json", []);
const seqName = sequence || seqs[0];
const framesUrl = seqName && `${base}/all_scenes_in_sequence?sequence=${encodeURIComponent(seqName)}`;
const frames = useXHR(framesUrl, "GET", "json", [], (ev) => {
const length = (ev.currentTarget as XMLHttpRequest).response?.length;
Expand Down Expand Up @@ -114,11 +113,15 @@ const Home = memo(function Home() {
};
}, []);


const onClickTab = useCallback(
(item: PivotItem) => {
const url: UrlObject = {
pathname: "/",
query: sequence ? {tab: item.props.itemKey, sequence: sequence} : {tab: item.props.itemKey}
query: sequence ? {
tab: item.props.itemKey,
sequence: sequence,
} : {tab: item.props.itemKey}
};
router.push(url, url, {shallow: true});
},
Expand Down
109 changes: 61 additions & 48 deletions wis3d/app/stores/object-store.tsx
Original file line number Diff line number Diff line change
@@ -1,62 +1,75 @@
import { getColor, getFileName } from "@/utils/misc";
import {getColor, getFileName} from "@/utils/misc";
import create from "zustand";
import { combine } from "zustand/middleware";
import { immer } from "./types";
import {combine} from "zustand/middleware";
import {immer} from "./types";

export interface IObject {
path: string;
url: string;
name: string;
color: string;
visible: boolean;
select: false;
preserved?: boolean;
path: string;
url: string;
name: string;
color: string;
visible: boolean;
select: false;
preserved?: boolean;
}

export type OBJECT_TYPE = "meshes" | "point_clouds" | "boxes" | "camera_trajectories" | "images" | "lines" | "voxels" | "spheres" | "correspondences" | "planes";
export type OBJECT_TYPE =
"meshes"
| "point_clouds"
| "boxes"
| "camera_trajectories"
| "images"
| "lines"
| "voxels"
| "spheres"
| "correspondences"
| "planes";

export type IObjectDict = {
[key in OBJECT_TYPE]?: IObject[];
[key in OBJECT_TYPE]?: IObject[];
};



export const useObjectStore = create(
combine(
{ objDict: {} as IObjectDict },
immer((set) => ({
set,
loadObjects(objects: Map<string, string[]>, baseUrl: string, preserve: boolean) {
set((state) => {
const objDict: IObjectDict = {};
for (const key in objects) {
objDict[key] = objects[key].map((path: string) => {
const name = getFileName(path);
return {
path,
url: `${baseUrl}/file?path=${encodeURIComponent(path)}`,
name,
visible: true,
select: false,
color: getColor(name),
preserved: false
};
});
}
for (const key in state.objDict) {
const newArr = (objDict[key] = objDict[key] || []) as IObject[];
for (const obj of state.objDict[key] as IObject[]) {
const idx = newArr.findIndex((_obj) => _obj.name === obj.name);
if (idx === -1) {
preserve && newArr.unshift({ ...obj, preserved: true });
} else {
newArr[idx].visible = obj.visible;
}
combine(
{objDict: {} as IObjectDict},
immer((set) => ({
set,
loadObjects(objects: Map<string, string[]>, baseUrl: string, preserve: boolean) {
set((state) => {
const objDict: IObjectDict = {};
for (const key in objects) {
objDict[key] = objects[key].map((path: string) => {
const name = getFileName(path);
const randomParam = `_ts=${Math.random()}`;
return {
path,
url: `${baseUrl}/file?path=${encodeURIComponent(path)}&${randomParam}`,
name,
visible: true,
select: false,
color: getColor(name),
preserved: false
};
});
}
for (const key in state.objDict) {
const newArr = (objDict[key] = objDict[key] || []) as IObject[];
for (const obj of state.objDict[key] as IObject[]) {
const idx = newArr.findIndex((_obj) => _obj.name === obj.name);
if (idx === -1) {
preserve && newArr.unshift({...obj, preserved: true});
} else {
newArr[idx].visible = obj.visible;
}
}
}
state.objDict = objDict;
});
}
}
state.objDict = objDict;
});
}
}))
)
}))
)
);

export const objectState = useObjectStore.getState();
Expand Down
63 changes: 63 additions & 0 deletions wis3d/quickstart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import cv2
import numpy as np
import matplotlib.pyplot as plt
import PIL.Image as Image
import argparse
import os
import os.path as osp
import tempfile

import trimesh
from wis3d import Wis3D
from PIL import Image, ImageDraw, ImageFont


def gen_image():
# Create an image with a white background
img = Image.new('RGB', (300, 300), color='white')
img = np.array(img)
cv2.putText(img, 'wis3d', (120, 120), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
# plt.imshow(img)
# plt.show()
# Save the image to a file
return img


def text_to_point_cloud(gen_image):
# Create a figure to draw the text on
mask = gen_image[:, :, 0] != 255
points = np.argwhere(mask)
points = points[:, [1, 0]]
points = points - np.mean(points, axis=0)
points = points / np.max(np.abs(points))
points[:, 1] = -points[:, 1]
points = np.concatenate([points, np.zeros((points.shape[0], 1))], axis=1)
return points


def main():
parser = argparse.ArgumentParser()
parser.add_argument('--host', default='')
args = parser.parse_args()

with tempfile.TemporaryDirectory() as d:
wis3d = Wis3D(
out_folder=d,
sequence_name='quickstart',
xyz_pattern=('x', 'y', 'z')
)
# host
img = gen_image()
wis3d.add_image(img)
points = text_to_point_cloud(img)
wis3d.add_point_cloud(points)
wis3d.add_mesh(trimesh.primitives.Cylinder(radius=0.1, height=1.0), name='cylinder')
host = args.host
if host == '':
host = os.environ.get('iterm2_hostname', 'localhost')
print(f'Running wis3d quickstart on {host}: TemporaryDirectory', d)
os.system(f'wis3d --host {host} --vis_dir {d}')


if __name__ == '__main__':
main()
6 changes: 3 additions & 3 deletions wis3d/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import cherrypy
import glob
import socket
from .version import __version__


class Visualizer:
Expand All @@ -15,7 +16,7 @@ def index(self, *url_parts, **params):
return open(os.path.join(self.static_dir, "index.html"), encoding="utf-8")

@cherrypy.expose
def file(self, path):
def file(self, path, _ts=None):
res = path.split(os.sep)
vis_dir = os.sep.join(res[0:-4])
if vis_dir == self.vis_dir:
Expand Down Expand Up @@ -98,8 +99,7 @@ def run_server(
cherrypy.engine.signals.subscribe()
# try:
cherrypy.engine.start()
print(f"Serving on http://{host}:{port}")
print(f"Wis3D {__version__} serving on http://{host}:{port}")
cherrypy.engine.block()
# except KeyboardInterrupt:
cherrypy.engine.stop()
cherrypy.engine.exit()
2 changes: 1 addition & 1 deletion wis3d/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# coding=utf-8
__version__ = "2.0.0"
__version__ = "2.0.2"

0 comments on commit bf6d9bc

Please sign in to comment.