2026年8月30日日曜日

Spatial Room Toybox

 Included Experiences

💧 Spatial Water — Interactive Water Simulation

Touch the water surface in front of you and watch ripples spread outward in real time. Create splashes, turn on rainfall, and interact directly with waves simulated on the GPU.

🌀 Fluid Board — Interactive Fluid Simulation

Use your finger to stir colorful fluid on a floating board. Draw through the flow, create vortices, and watch streams collide and evolve through a real-time fluid simulation.

✨ Particles — Fingertip Particles

Emit thousands of GPU particles directly from your fingertips. Choose from styles such as Sparkler, Magic Dust, and Fountain, move your hands to shape their motion, or trigger bursts of fireworks in space.

🌌 Morph Nebula — Shape-Shifting Nebula

Tens of thousands of particles continuously transform between shapes such as a Galaxy, Knot, Sphere, DNA helix, and Torus.

Reach into the nebula with your hands to scatter the particles. Once you move away, they gradually reform into their original shape.

🏠 Room Dust — Turn Your Room into Luminous Particles

The app scans the geometry of your real room and covers walls, floors, and other surfaces with tens of thousands of glowing particles.

Touch the room to send waves through the particles, dissolve the entire environment into floating dust, and watch it assemble itself again.

You can also import your own music. Low frequencies and detected beats make the room pulse and generate waves in sync with the sound.

In Space Void Mode, the real environment gives way to a fully immersive space filled with optional light streaks, tunnel gates, concentric rings, and meteors synchronized to the music. Meteors can even be intercepted with your hands.

🔆 Glow Room — Light Waves Across Your Environment

Your real walls and tables remain invisible until you touch them. Light waves then travel outward across their surfaces, revealing the geometry of the room only as the wave passes.

Choose between soft glowing waves and sharper ring-like pulses, or reveal the entire room as a futuristic illuminated grid.

🧊 3D Cellular Automata — Living 3D Cells

Explore a three-dimensional cellular automaton containing approximately 260,000 cells.

Choose from several rule sets including 3D Life, Clouds, Pyro, Brian's Brain, Amoeba, and more. Place your fingertips inside the grid to create new living cells and watch complex structures grow, move, and disappear.

🖌️ Spatial Paint — Paint Directly in 3D Space

Use your fingertips as brushes and draw physical 3D strokes directly into the world around you.

Extend one finger to draw one line, two fingers to draw two, or open your hand to paint with all five fingers at once.

Pick different colors independently for each finger from a floating 3D color palette. Switch between Neon, Matte, and Glossy materials, erase strokes with your hands, undo previous actions, and freely combine different materials and colors in the same artwork.

Finished creations can also be exported as USDZ files.

🔵 Water Sphere — A Sphere Made of Waves

Hold a responsive water sphere above your left palm.

Touch it with your other hand or tap its surface to generate ripples that propagate across the entire sphere.

🫠 Liquid Metal Hands — Turn Your Hands into Liquid Metal

Cover both hands with a reflective liquid-metal surface created from dynamically merging metaballs.

Move your hands quickly to fling droplets into the environment. The scattered metal can gradually return to your hands, gather into a sphere when you make a fist, collapse onto the floor, or crawl across walls and surfaces when recalled.

A game mode is also included: collect glowing targets appearing around the room using only your liquid-metal hands before time runs out.

🌠 Particle Hands — Become a Body of Light

Enter a fully immersive dark space where your hands are transformed into tens of thousands of glowing particles.

Choose from visual styles such as Skin, Aura, Stardust, and Comet. Particles can cling to your hands, flow outward from your fingers, or leave luminous trails as you move.

🌿 L-System Garden — Grow Plants in Your Room

Tap a real floor or wall to plant a seed and watch a procedural plant grow directly from that surface.

Adjust branching angle, growth generations, foliage density, leaf color, bark shape, and more. Once grown, branches and leaves continue to sway in the wind.

🐦 Boids Flock — Control a Living Flock with Your Hands

Thousands of birds or fish move together using a real-time Boids flocking simulation.

Make a fist to attract and swirl the flock around your hand, or open your palm to repel it. Your left and right hands can control the flock independently.

The creatures also react to the geometry of your real room and avoid walls as they move. In the immersive space mode, the room itself can be visualized as a field of glowing points.

🫧 Goo Flock — A Living Liquid Swarm

Combine Boids flocking behavior with metaball surface generation.

Hundreds of moving agents continuously merge into a single evolving liquid surface, creating something between a flock of creatures and a living blob.

Close your hand into a fist to gather the swarm into one mass, then open your palm to blast it apart.

Different visual styles including Chrome, Jelly, and Neon can completely change its appearance.

🪸 Reaction Coral — Growing Reaction-Diffusion Forms

Watch three-dimensional structures resembling coral and living organisms emerge from a real-time Gray-Scott reaction-diffusion simulation.

Reach into the structure to create new growth points and watch the form develop around your hands.

Choose from patterns including Coral, Mitosis, Maze, Spirals, and Waves to generate dramatically different forms.

🪐 Living Planet — A Living World in Your Hand

Hold a small procedural planet above your left palm.

Touch its surface with your other hand to seed reaction-diffusion patterns that spread across the sphere like evolving crust, biological growth, or glowing lava.

Different reaction rules continuously transform the appearance of the planet.

🦓 Turing Walls — Living Patterns Across Your Real Room

Use the surfaces of your actual room as the simulation itself.

Trace your finger across walls, floors, or tables to seed Turing-style reaction-diffusion patterns. The patterns then spread organically across the captured room geometry, transforming ordinary surfaces into glowing, evolving structures.

🍃 Overgrowth — Let Ivy Invade Your Room

Touch a wall or floor and watch ivy begin growing directly from that point.

The vines crawl across the actual surfaces of your room, branch, twist, produce leaves and tendrils, and gradually spread through the environment.

Adjust growth speed, branching, wandering, vine length, leaf density, wind, and other parameters to create anything from a few delicate vines to an entire room overtaken by vegetation.

Spatial Room Toybox Privacy Policy

Privacy Policy

Last updated: August 30, 2026

Spatial Room Toybox respects your privacy.

Data Collection

Spatial Room Toybox does not collect, store, transmit, or share any personal data.

The app does not require an account and does not use advertising, analytics, tracking, or third-party services that collect user information.

Camera, Hand Tracking, and Room Data

Spatial Room Toybox uses Apple Vision Pro system features such as hand tracking and spatial room geometry to provide interactive mixed-reality experiences.

This information is processed locally on your device and is not collected, stored on external servers, or transmitted to the developer or any third party.

Imported Audio Files

Some experiences allow you to select an audio file from your device for real-time audio visualization.

Selected audio files are processed locally on your device. They are not uploaded, transmitted, or collected by the developer.

User-Created Content

Some features may allow you to create or export content, such as 3D artwork. This content remains under your control and is not automatically uploaded or transmitted to the developer.

Third-Party Sharing

Spatial Room Toybox does not sell, rent, share, or disclose personal information to third parties.

Children’s Privacy

Because Spatial Room Toybox does not collect personal information, it does not knowingly collect personal information from children.

Changes to This Privacy Policy

This Privacy Policy may be updated if the app’s features or data practices change. Any updates will be posted on this page.

Contact

If you have any questions about this Privacy Policy, please contact the developer through the support contact listed on the App Store page.

2026年7月20日月曜日

How to transfer root bone pose animation to the animation of the entire armature 5.x

 import bpy

import math


from mathutils import Matrix

from bpy_extras import anim_utils



# ============================================================

# Settings

# ============================================================


ROOT_BONE_NAME = "Root"


# If True:

#   Bake a keyframe on every frame between the first and last

#   root bone keyframe.

#   This preserves interpolation more accurately, but creates

#   many additional keyframes.

#

# If False:

#   Process only frames that already contain root bone keys.

#   This behaves similarly to the original version of the script.

BAKE_EVERY_FRAME = False


# Delete the root bone after the transfer is complete.

DELETE_ROOT_BONE = True



# ============================================================

# Blender 5.x / Legacy Action Compatibility

# ============================================================


def get_action_fcurves(animated_id):

    """

    Return all F-Curves from the Action currently assigned

    to the specified animated datablock.


    Blender 4.x and earlier:

        action.fcurves


    Blender 5.x:

        Action Slot

            -> Channelbag

                -> F-Curves

    """


    animation_data = animated_id.animation_data


    if animation_data is None:

        return []


    action = animation_data.action


    if action is None:

        return []


    # Legacy Blender API.

    if hasattr(action, "fcurves"):

        return list(action.fcurves)


    # Blender 5.x layered Action API.

    action_slot = getattr(animation_data, "action_slot", None)


    # Normally animation_data.action_slot is available.

    # As a fallback, use the only slot if the Action has exactly one.

    if action_slot is None:

        slots = getattr(action, "slots", None)


        if slots is not None and len(slots) == 1:

            action_slot = slots[0]


    if action_slot is None:

        print(

            f"Warning: No Action slot was found for "

            f"'{animated_id.name}'."

        )

        return []


    channelbag = anim_utils.action_get_channelbag_for_slot(

        action,

        action_slot

    )


    if channelbag is None:

        return []


    return list(channelbag.fcurves)



def collect_keyframes(fcurves, data_path_prefix=None):

    """

    Collect all unique keyframe times from a list of F-Curves.


    If data_path_prefix is specified, only F-Curves whose

    data paths start with that prefix are included.

    """


    frames = set()


    for fcurve in fcurves:

        if (

            data_path_prefix is not None

            and not fcurve.data_path.startswith(data_path_prefix)

        ):

            continue


        for keyframe in fcurve.keyframe_points:

            frames.add(float(keyframe.co.x))


    return sorted(frames)



def set_scene_frame(scene, frame):

    """

    Set the current timeline position with subframe support,

    then update the dependency graph.

    """


    whole_frame = math.floor(frame)

    subframe = frame - whole_frame


    scene.frame_set(whole_frame, subframe=subframe)

    bpy.context.view_layer.update()



# ============================================================

# Main

# ============================================================


scene = bpy.context.scene


# Store the original timeline position so it can be restored later.

original_frame = scene.frame_current + scene.frame_subframe


# Use the currently active object as the source armature.

armature = bpy.context.active_object


if armature is None or armature.type != 'ARMATURE':

    raise ValueError("Please select an armature object.")


bpy.context.view_layer.objects.active = armature

armature.select_set(True)


# Switch to Object Mode before reading transforms.

if armature.mode != 'OBJECT':

    bpy.ops.object.mode_set(mode='OBJECT')



# ============================================================

# Validate Root Bone

# ============================================================


root_pose_bone = armature.pose.bones.get(ROOT_BONE_NAME)


if root_pose_bone is None:

    raise ValueError(

        f"Root bone '{ROOT_BONE_NAME}' was not found."

    )


root_data_bone = armature.data.bones.get(ROOT_BONE_NAME)


if root_data_bone is None:

    raise ValueError(

        f"Root data bone '{ROOT_BONE_NAME}' was not found."

    )



# ============================================================

# Store Root Bone Rest Transform

# ============================================================


armature_matrix_world = armature.matrix_world.copy()

root_bone_matrix_rest = root_data_bone.matrix_local.copy()


root_bone_matrix_world_rest = (

    armature_matrix_world

    @ root_bone_matrix_rest

)


(

    root_bone_default_loc,

    root_bone_default_rot,

    root_bone_default_scale

) = root_bone_matrix_world_rest.decompose()


inverse_root_bone_default_rot = (

    root_bone_default_rot.inverted()

)



# ============================================================

# Collect IK Targets

# ============================================================


ik_targets = []


for pose_bone in armature.pose.bones:

    for constraint in pose_bone.constraints:


        if constraint.type != 'IK':

            continue


        target = constraint.target


        if target is None:

            continue


        # Only process external IK target objects parented

        # to the selected armature.

        if target.parent != armature:

            continue


        # Prevent duplicate targets from being added.

        if target not in ik_targets:

            ik_targets.append(target)



# ============================================================

# Store Original IK Target World Positions

# ============================================================


ik_target_keyframes = {}


for target in ik_targets:

    target_fcurves = get_action_fcurves(target)

    target_frames = collect_keyframes(target_fcurves)


    ik_target_keyframes[target.name] = {}


    for frame in target_frames:

        set_scene_frame(scene, frame)


        ik_target_keyframes[target.name][frame] = (

            target.matrix_world.translation.copy()

        )



# ============================================================

# Get Armature Action

# ============================================================


animation_data = armature.animation_data


if animation_data is None:

    raise ValueError("Animation data was not found.")


action = animation_data.action


if action is None:

    raise ValueError("No Action is assigned to the armature.")


armature_fcurves = get_action_fcurves(armature)


if not armature_fcurves:

    raise ValueError(

        "No F-Curves were found in the armature Action."

    )



# ============================================================

# Collect Root Bone Keyframes

# ============================================================


root_data_path_prefix = (

    f'pose.bones["{ROOT_BONE_NAME}"]'

)


root_keyframes = collect_keyframes(

    armature_fcurves,

    root_data_path_prefix

)


if not root_keyframes:

    raise ValueError(

        f"No animation keys were found for "

        f"root bone '{ROOT_BONE_NAME}'."

    )


# Optionally bake every integer frame between

# the first and last root bone keyframe.

if BAKE_EVERY_FRAME:

    first_frame = math.floor(min(root_keyframes))

    last_frame = math.ceil(max(root_keyframes))


    sample_frames = [

        float(frame)

        for frame in range(first_frame, last_frame + 1)

    ]


else:

    sample_frames = root_keyframes



# ============================================================

# Sample Root Bone Transforms

#

# At this stage, transforms are only recorded.

# No keys are written to the armature object yet.

#

# This prevents newly inserted armature object keyframes

# from affecting transform evaluation on later frames.

# ============================================================


transform_data = {}


for frame in sample_frames:

    set_scene_frame(scene, frame)


    # PoseBone.matrix is expressed in armature object space.

    root_bone_matrix = root_pose_bone.matrix.copy()


    # Convert the root bone transform to world space.

    global_matrix = (

        armature.matrix_world

        @ root_bone_matrix

    )


    global_loc, global_rot, global_scale = (

        global_matrix.decompose()

    )


    transform_data[frame] = {

        "location": global_loc.copy(),

        "rotation": global_rot.copy(),

        "scale": global_scale.copy(),

    }



# ============================================================

# Bake the Root Bone Transform to the Armature Object

# ============================================================


bpy.ops.object.mode_set(mode='OBJECT')


# Quaternion rotation avoids Euler angle discontinuities

# during the transfer.

armature.rotation_mode = 'QUATERNION'


translation_matrix_to_default = Matrix.Translation(

    -root_bone_default_loc

)


for frame in sample_frames:

    data = transform_data[frame]


    loc = data["location"]

    rot = data["rotation"]

    scale = data["scale"]


    # Remove the root bone's rest rotation.

    corrected_rot = (

        rot

        @ inverse_root_bone_default_rot

    )


    translation_matrix_current = Matrix.Translation(loc)

    rotation_matrix = corrected_rot.to_matrix().to_4x4()


    # Apply the same transform order as the original script:

    #   1. Translate relative to the root bone's rest location.

    #   2. Apply the corrected root bone rotation.

    #   3. Move to the current root bone location.

    final_matrix = (

        translation_matrix_current

        @ rotation_matrix

        @ translation_matrix_to_default

    )


    final_loc, final_rot, _ = final_matrix.decompose()


    armature.location = final_loc

    armature.rotation_quaternion = final_rot

    armature.scale = scale


    armature.keyframe_insert(

        data_path="location",

        frame=frame

    )


    armature.keyframe_insert(

        data_path="rotation_quaternion",

        frame=frame

    )


    armature.keyframe_insert(

        data_path="scale",

        frame=frame

    )



# ============================================================

# Preserve IK Target World Positions

# ============================================================


for target in ik_targets:

    saved_frames = ik_target_keyframes.get(target.name, {})


    for frame, initial_world_position in saved_frames.items():

        set_scene_frame(scene, frame)


        # Convert the stored world-space position back into

        # the target's armature-relative local space using

        # the armature transform at the current frame.

        local_position = (

            armature.matrix_world.inverted()

            @ initial_world_position

        )


        target.location = local_position


        target.keyframe_insert(

            data_path="location",

            frame=frame

        )



# ============================================================

# Delete Root Bone

# ============================================================


if DELETE_ROOT_BONE:

    bpy.context.view_layer.objects.active = armature

    armature.select_set(True)


    bpy.ops.object.mode_set(mode='EDIT')


    edit_root_bone = armature.data.edit_bones.get(

        ROOT_BONE_NAME

    )


    if edit_root_bone is not None:

        armature.data.edit_bones.remove(edit_root_bone)


    bpy.ops.object.mode_set(mode='OBJECT')



# ============================================================

# Restore Original Timeline Position

# ============================================================


set_scene_frame(scene, original_frame)


print(

    f"Finished. Root bone animation has been transferred "

    f"to the armature object '{armature.name}'."

)


2026年7月19日日曜日

Privacy Policy for Living Diorama

Privacy Policy for Living Diorama

Last updated: 19 July 2026

Living Diorama respects your privacy.

Data Collection

Living Diorama does not collect, store, transmit or share any personal information or usage data.

The app does not collect information such as:

  • Names or contact details

  • Location data

  • Device identifiers

  • Usage or interaction data

  • Photos, videos or audio

  • Health or fitness data

  • Purchase information

Interactions with animals, food and other elements within the app are not recorded or transmitted to the developer.

Analytics, Advertising and Tracking

Living Diorama does not use third-party analytics services, advertising networks or tracking technologies.

The app does not track users across apps or websites and does not display personalised advertising.

Third-Party Data Sharing

Living Diorama does not share user data with third parties because the app does not collect user data.

Data Storage and Deletion

Living Diorama does not store personal information on external servers.

As no personal information is collected or retained by the developer, there is no personal data to access, export or delete.

Children’s Privacy

Living Diorama does not knowingly collect personal information from children or any other users.

Changes to This Privacy Policy

This Privacy Policy may be updated if the app’s features or data practices change. Any changes will be published on this page, together with an updated revision date.


2026年7月8日水曜日

Swipe to Collapse - A Quantum Wave Game

 Overview

Swipe to Collapse is a single-player iPhone game and interactive quantum wave simulation.

This app displays a real-time simulation of the Schrödinger equation using compute shaders.

A quantum wave function lives on the grid. Its colour is the phase and its brightness is how likely the particle is to be there (|ψ|²). You play by observing it.

App purpose and target audience

The app lets users play with a quantum wave function. The color represents phase, and the brightness represents probability density, |ψ|². Users interact with the wave by dragging across the field to observe a selected region. When the user releases, the wave function collapses probabilistically according to the Born rule.

The app is designed for users who enjoy physics-inspired games, experimental arcade games, and interactive science visualizations. Its value is to turn abstract quantum concepts such as observation, probability density, phase, wave function collapse, and position/momentum representations into an interactive visual experience.

The app is intended for entertainment and educational exploration. It is not a professional scientific, medical, financial, or regulated-industry tool.

Observe

Drag across the field to outline a region, then let go to measure it. The wave collapses by the Born rule — the particle is either found inside your region (it snaps bright there) or not (that area goes dark). Pick a stage and try it freely before starting a game.

Game

Tap Start for a 30-second round. Green particles roam the field and score continuously — the brighter the wave |ψ| where a particle sits, the faster it scores. Observe (drag) to collapse the wave and pile it onto the green particles. Red particles (stage 2+) drain your score the same way, so keep the wave dark around them. Best 3 scores per stage are saved. Tap × to quit.

Z/pZ Lab — position & momentum together

An experimental mode on the finite set Z/pZ, where position and momentum are both finite and the Fourier transform links them. Two strips show \psi(x) and \hat{\psi}(k) at once — drag either one to observe in that basis. The carpet below charts the wave over time; watch the fractal revivals. Switch p, potential, kinetic term, initial state and more.

2026年7月5日日曜日

Privacy Policy for Swipe to Collapse

 Privacy Policy

Effective Date: July 5, 2026

This Privacy Policy applies to Swipe to Collapse, an iPhone app developed by Junnichi Suko.

No Data Collection

Swipe to Collapse does not collect, store, transmit, or share personal data with the developer or any third party.

The app does not collect or transmit:

  • Name
  • Email address
  • Location data
  • Contacts
  • Photos or videos
  • Audio recordings
  • Device identifiers
  • Advertising identifiers
  • Analytics data
  • User-generated content

Local Game Data

The app may save certain game data locally on your device, such as game progress or high scores.

This data is stored only on your device and is not transmitted to the developer or to any external server.

If you delete the app, this locally stored data may also be deleted.

No Advertising or Tracking

The app does not display advertisements.

The app does not use third-party advertising networks.

The app does not track users across apps, websites, or services.

No Third-Party Analytics

The app does not use third-party analytics or crash reporting services.

Internet Connection

Core gameplay does not require an internet connection.

The app does not send personal information or gameplay data to the developer or to any external server.

Children’s Privacy

The app does not knowingly collect any personal information from children or adults.

Changes to This Privacy Policy

This Privacy Policy may be updated in the future if the app’s features change.

If the app ever begins collecting data, this Privacy Policy will be updated to describe what data is collected, how it is used, and any choices available to users.

Contact

If you have any questions about this Privacy Policy, please contact:

junichistamesi@gmail.com