Skip to content

Instantly share code, notes, and snippets.

@deeplook
Created March 31, 2020 18:32
Show Gist options
  • Save deeplook/d9ac96508362ce5eb5015a7e449eb0b6 to your computer and use it in GitHub Desktop.
Save deeplook/d9ac96508362ce5eb5015a7e449eb0b6 to your computer and use it in GitHub Desktop.
Explore seam on textures mapped to spheres
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Explore texture seam on spheres"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import ipyvolume as ipv\n",
"from PIL import Image\n",
"from ipywidgets import interact"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define sphere"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"ExecuteTime": {
"end_time": "2020-03-28T12:43:46.345724Z",
"start_time": "2020-03-28T12:43:46.337716Z"
}
},
"outputs": [],
"source": [
"def sphere(x, y, z, radius, color=\"red\", texture=None, num=100):\n",
" \"\"\"Create a sphere mesh with origin at x, y, z and radius.\n",
" \"\"\"\n",
" assert num > 0\n",
" \n",
" # First compute the unit vectors and scale them:\n",
" phi = np.linspace(0, 2 * np.pi, num)\n",
" theta = np.linspace(0, np.pi, num)\n",
" xu = np.outer(np.cos(phi), np.sin(theta))\n",
" yu = np.outer(np.sin(phi), np.sin(theta))\n",
" zu = np.outer(np.ones(np.size(phi)), np.cos(theta))\n",
" X = x + radius * xu\n",
" Y = y + radius * yu\n",
" Z = z + radius * zu\n",
" \n",
" # Compute the lon and lat for a z-aligned sphere to change axis,\n",
" # the math changes but is essentially the same.\n",
" lon = np.arctan2(yu, xu)\n",
" lat = np.arcsin(zu)\n",
" \n",
" # Get U, V and move them to proper values:\n",
" u = 0.5 + lon / (2 * np.pi)\n",
" v = 0.5 + lat / np.pi\n",
"\n",
" return ipv.plot_mesh(X, Y, Z, u=u, v=v, color=color, texture=texture, wireframe=False)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cddeef0a52ac4e7c8cc0695c59a7d96b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = ipv.figure()\n",
"s = sphere(0, 0, 0, radius=1, color=\"blue\", num=15)\n",
"ipv.show()"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"s.color = \"red\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generate textures"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def flat_image(width, height):\n",
" data = 100 * np.ones((height, width)).astype(np.uint8)\n",
" return Image.fromarray(data, \"L\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAAAAAD3vSCjAAAAPklEQVR4nO3OMQEAAAjDsIFW/GtAxp7UQDOXblv+AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOQByggA5F96DpsAAAAASUVORK5CYII=\n",
"text/plain": [
"<PIL.Image.Image image mode=L size=128x64 at 0x121628750>"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"flat_image(128, 64)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def random_image(width, height):\n",
" data = 255 * np.random.randint(0, 2, (height, width)).astype(np.uint8)\n",
" return Image.fromarray(data, \"L\")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<PIL.Image.Image image mode=L size=128x64 at 0x1216A5790>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"random_image(128, 64)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def stripe_image(width, height):\n",
" a0 = np.zeros(height)\n",
" a1 = np.ones(height)\n",
" data = 255 * np.array([[a0, a1][i % 2] for i in range(width)]).T.astype(np.uint8)\n",
" return Image.fromarray(data, \"L\")"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAAAAAD3vSCjAAAAPElEQVR4nO3OQREAAAzCMG7+PQ8ZfNIaSPLbL+MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkhAQD9DCv+KAAAAAElFTkSuQmCC\n",
"text/plain": [
"<PIL.Image.Image image mode=L size=128x64 at 0x120A10490>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stripe_image(128, 64)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Map textures on sphere"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"ExecuteTime": {
"end_time": "2020-03-28T12:43:49.970693Z",
"start_time": "2020-03-28T12:43:46.702179Z"
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d154b56cd91f4a32b5757a05eaa62904",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = ipv.figure()\n",
"s = sphere(0, 0, 0, radius=1, num=24)\n",
"ipv.show()"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"s.texture = flat_image(16, 8)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2421309defd844fcaceced428a0ee50b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = ipv.figure()\n",
"img = stripe_image(64, 4)\n",
"s = sphere(0, 0, 0, radius=1, num=24, texture=img)\n",
"ipv.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Add more interactivity"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "24908e4bb19346ccad27143dadd0b882",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"VBox(children=(Figure(camera=PerspectiveCamera(fov=46.0, position=(0.0, 0.0, 2.0), quaternion=(0.0, 0.0, 0.0, …"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig = ipv.figure()\n",
"s = sphere(0, 0, 0, radius=1, num=12)\n",
"ipv.show()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5f027625f8e24e9c9e0a79981aa98f6c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"interactive(children=(IntSlider(value=16, description='w', max=32, min=1), IntSlider(value=8, description='h',…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"tx = None\n",
"\n",
"@interact\n",
"def retexture(w=(1, 32), h=(1, 16), typ=[\"stripe\", \"random\"]):\n",
" global tx\n",
" tx = stripe_image(w, h) if typ==\"stripe\" else random_image(w, h)\n",
" s.texture = tx\n",
" tx_norm = tx.resize((256, 128), Image.AFFINE)\n",
" return tx_norm"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment