diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 000000000..cf5b02354 --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,23 @@ +name: validate + +on: + pull_request: + workflow_dispatch: + +jobs: + validate: + runs-on: ubuntu-latest + env: + BUNDLE_WITH: test jekyll_plugins + SITE_ID: 'cookbook' # which iiif site this is + URL: 'https://preview.iiif.io' + + steps: + - name: Check out this repository + uses: actions/checkout@v5 + + - name: Run IIIF validator + uses: IIIF/presentation-validator@main + with: + directory: source/presentation/4.0/example/ + version: "4.0" diff --git a/source/presentation/4.0/example/uc06_audio_with_3d.json b/source/presentation/4.0/example/uc06_audio_with_3d.json index 7443e9528..36f9e7edc 100644 --- a/source/presentation/4.0/example/uc06_audio_with_3d.json +++ b/source/presentation/4.0/example/uc06_audio_with_3d.json @@ -256,7 +256,7 @@ "type": "ImageBasedLight", "label": { "en": [ "Image-Based Light" ] }, "environmentMap": { - "id": "https://iiif.io/api/presentation/4.0/example/uc06/light/3/environment.hdr", + "id": "https://fixtures.iiif.io/3d/polyhaven/spruit_sunrise_4k.hdr", "type": "Image", "format": "image/vnd.radiance", "profile": "equirectangular" diff --git a/source/presentation/4.0/example/uc06_canvas_in_scene.json b/source/presentation/4.0/example/uc06_canvas_in_scene.json index 8f83ab5e8..41daf3b53 100644 --- a/source/presentation/4.0/example/uc06_canvas_in_scene.json +++ b/source/presentation/4.0/example/uc06_canvas_in_scene.json @@ -48,13 +48,16 @@ "type": "Annotation", "motivation": [ "painting" ], "body": { - "id": "https://fixtures.iiif.io/3d/chess/chessboard.jpg", + "id": "https://fixtures.iiif.io/3d/thomas_flynn/chess/chessboard.png", "type": "Image", - "format": "image/jpeg", - "width": 800, - "height": 800 + "format": "image/png", + "width": 1024, + "height": 1024 }, - "target": "https://iiif.io/api/presentation/4.0/example/uc06/canvas/chessboard" + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/canvas/chessboard", + "type": "Canvas" + } } ] } diff --git a/source/presentation/4.0/example/uc06_multiple_3d_objects.json b/source/presentation/4.0/example/uc06_multiple_3d_objects.json index c48c5b7ae..826c8e321 100644 --- a/source/presentation/4.0/example/uc06_multiple_3d_objects.json +++ b/source/presentation/4.0/example/uc06_multiple_3d_objects.json @@ -139,7 +139,7 @@ "type": "ImageBasedLight", "label": { "en": [ "Image-Based Light" ] }, "environmentMap": { - "id": "https://iiif.io/api/presentation/4.0/example/uc06/light/3/environment.hdr", + "id": "https://fixtures.iiif.io/3d/polyhaven/spruit_sunrise_4k.hdr", "type": "Image", "format": "image/vnd.radiance", "profile": "equirectangular" diff --git a/source/presentation/4.0/example/uc06_scene_in_scene.json b/source/presentation/4.0/example/uc06_scene_in_scene.json index 1442451aa..92440646d 100644 --- a/source/presentation/4.0/example/uc06_scene_in_scene.json +++ b/source/presentation/4.0/example/uc06_scene_in_scene.json @@ -2,12 +2,53 @@ "@context": "http://iiif.io/api/presentation/4/context.json", "id": "https://iiif.io/api/presentation/4.0/example/uc06_scene_in_scene.json", "type": "Manifest", - "label": { "en": [ "Chess Pieces — Scene in Scene" ] }, + "label": { + "en": [ + "Chess Pieces — Scene in Scene" + ] + }, "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/1", + "type": "Scene", + "label": { + "en": [ + "Chess Pawn" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/1/page/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/3d/anno/1", + "type": "Annotation", + "motivation": [ + "painting" + ], + "body": { + "id": "https://fixtures.iiif.io/3d/thomas_flynn/chess/Pawn_black.glb", + "type": "Model", + "format": "model/gltf-binary" + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/1", + "type": "Scene" + } + } + ] + } + ] + }, { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/parent", "type": "Scene", - "label": { "en": [ "Chess Pieces — Scene in Scene" ] }, + "label": { + "en": [ + "Chess Pieces — Scene in Scene" + ] + }, "items": [ { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/parent/page/1", @@ -16,7 +57,9 @@ { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/parent/anno/1", "type": "Annotation", - "motivation": [ "painting" ], + "motivation": [ + "painting" + ], "body": { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/1", "type": "Scene" @@ -41,7 +84,9 @@ { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/parent/anno/2", "type": "Annotation", - "motivation": [ "painting" ], + "motivation": [ + "painting" + ], "body": { "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/1", "type": "Scene" @@ -67,5 +112,30 @@ } ] } + ], + "structures": [ + { + "id": "https://iiif.io/api/cookbook/recipe/0027-alternative-page-order/range/r1", + "type": "Range", + "label": { + "en": [ + "Only the single parent scene should be shown" + ] + }, + "behavior": [ + "sequence" + ], + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc06/scene/parent", + "type": "Scene", + "label": { + "en": [ + "Chess Pieces — Scene in Scene" + ] + } + } + ] + } ] -} +} \ No newline at end of file diff --git a/source/presentation/4.0/example/uc07_duration_composite.json b/source/presentation/4.0/example/uc07_duration_composite.json index 2e44a2554..81dd2294b 100644 --- a/source/presentation/4.0/example/uc07_duration_composite.json +++ b/source/presentation/4.0/example/uc07_duration_composite.json @@ -10,7 +10,7 @@ "label": { "en": [ "Side A: 99 Luftballons - 10min duration" ] }, "width": 100, "height": 100, - "duration": 36000, + "duration": 600, "items": [ { "id": "https://iiif.io/api/presentation/4.0/example/uc07_audio/canvas/1/page/1", diff --git a/source/presentation/4.0/example/uc08_3d_annotation.json b/source/presentation/4.0/example/uc08_3d_annotation.json new file mode 100644 index 000000000..6f08acd23 --- /dev/null +++ b/source/presentation/4.0/example/uc08_3d_annotation.json @@ -0,0 +1,77 @@ +{ + "@context": "http://iiif.io/api/presentation/4/context.json", + "id": "https://iiif.io/api/presentation/4.0/example/uc08_3d_annotation.json", + "type": "Manifest", + "label": { "en": ["2nd century BC Greek sculpture"] }, + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene", + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1/pages/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1/sculpture", + "type": "Annotation", + "motivation": ["painting"] , + "label": { + "en": ["A 1st century Roman portrait bust."] + }, + "body": + { + "id": "https://fixtures.iiif.io/3d/smk/venus.glb", + "type": "Model" + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + } + } + ] + } + ] + } + ], + "annotations": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1/commenting-annotation-pages/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://example.org/iiif/presentation/examples/commenting/anno/3", + "type": "Annotation", + "motivation": ["commenting"], + "body": + { + "id": "https://example.org/iiif/presentation/examples/commenting/anno/3/comment1", + "type": "TextualBody", + "language": "en", + "format": "text/plain", + "value": "This sculpture embodies the Hellenistic synthesis of idealised form and expressive naturalism that emerged in the late Greek period.", + "position": { + "type": "SpecificResource", + "source": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + }, + "selector": [ + { + "type": "PointSelector", + "x": 0.75, + "y": 1.5, + "z": 0.1 + } + ] + } + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/source/presentation/4.0/example/uc08_3d_comments_with_cameras.json b/source/presentation/4.0/example/uc08_3d_comments_with_cameras.json new file mode 100644 index 000000000..9b6fe5333 --- /dev/null +++ b/source/presentation/4.0/example/uc08_3d_comments_with_cameras.json @@ -0,0 +1,237 @@ +{ + "@context": "http://iiif.io/api/presentation/4/context.json", + "id": "https://iiif.io/api/presentation/4.0/example/uc08_3d_comments_with_cameras.json", + "type": "Manifest", + "label": { + "en": [ + "Whale Cranium and Mandible with Dynamic Commenting Annotations and Custom Per-Anno Views" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene", + "label": { + "en": [ + "A Scene Containing a Whale Cranium and Mandible" + ] + }, + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1/page/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno/1", + "type": "Annotation", + "motivation": [ + "painting" + ], + "body": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno/1/body", + "type": "SpecificResource", + "source": { + "id": "https://fixtures.iiif.io/3d/smithsonian/whale/whale_mandible.glb", + "type": "Model", + "label": { + "en": [ + "mandible" + ] + }, + "format": "model/gltf-binary" + }, + "transform": [ + { + "type": "ScaleTransform", + "x": 10, + "y": 10, + "z": 10 + }, + { + "type": "RotateTransform", + "x": 12.5, + "y": 0, + "z": 0 + }, + { + "type": "TranslateTransform", + "x": 0, + "y": 0, + "z": 0.5 + } + ] + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + } + }, + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno-that-paints-desired-camera-to-view-tooth", + "type": "Annotation", + "motivation": [ + "painting" + ], + "behavior": [ + "hidden" + ], + "body": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/cameras/1", + "type": "PerspectiveCamera", + "label": { + "en": [ + "Perspective Camera Pointed At Front of Cranium and Mandible" + ] + }, + "fieldOfView": 50.0, + "near": 0.10, + "far": 2000.0 + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno/2/target", + "type": "SpecificResource", + "source": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + }, + "selector": [ + { + "type": "PointSelector", + "x": 0.0, + "y": 0.15, + "z": 0.75 + } + ] + } + }, + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno2", + "type": "Annotation", + "motivation": [ + "painting" + ], + "body": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno/3/body", + "type": "SpecificResource", + "source": { + "id": "https://fixtures.iiif.io/3d/smithsonian/whale/whale_cranium.glb", + "type": "Model", + "label": { + "en": [ + "cranium" + ] + }, + "format": "model/gltf-binary" + }, + "transform": [ + { + "type": "ScaleTransform", + "x": 10, + "y": 10, + "z": 10 + }, + { + "type": "TranslateTransform", + "x": 0, + "y": 1.5, + "z": 0 + } + ] + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + } + } + ] + } + ] + } + ], + "annotations": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1/annotations/page/1", + "type": "AnnotationPage", + "items": [ + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/commenting-anno-for-mandibular-tooth", + "type": "Annotation", + "motivation": [ + "commenting" + ], + "body": { + "type": "TextualBody", + "value": "Mandibular tooth" + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/comment/1/target", + "type": "SpecificResource", + "source": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + }, + "selector": [ + { + "type": "PointSelector", + "x": -0.447287, + "y": 0.546212, + "z": 1.795195 + } + ] + } + }, + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/commenting-anno-for-right-pterygoid-hamulus", + "type": "Annotation", + "motivation": [ + "commenting" + ], + "body": { + "type": "TextualBody", + "value": "Right pterygoid hamulus" + }, + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/comment/2/target", + "type": "SpecificResource", + "source": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/scene/1", + "type": "Scene" + }, + "selector": [ + { + "type": "PointSelector", + "x": -0.442066, + "y": 0.671795, + "z": 1.288055 + } + ] + } + }, + { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno9", + "type": "Annotation", + "motivation": [ + "activating" + ], + "target": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/commenting-anno-for-mandibular-tooth", + "type": "Annotation" + }, + "body": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/comment/3/body", + "type": "SpecificResource", + "source": { + "id": "https://iiif.io/api/presentation/4.0/example/uc08/3d/anno-that-paints-desired-camera-to-view-tooth", + "type": "Annotation" + }, + "action": [ + "show", + "enable", + "select" + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/source/presentation/4.0/index.md b/source/presentation/4.0/index.md index f48720f3f..51494e488 100644 --- a/source/presentation/4.0/index.md +++ b/source/presentation/4.0/index.md @@ -748,85 +748,7 @@ A commenting annotation can also reference a Content Resource, such as a Model, In some cases it is desirable to influence the client's positioning of the commenting annotation when rendered. This may be done to ensure that the annotation does not hide key visual elements or to ensure that the annotation itself is not obscured by resources painted in the Container, such as 3D models. In these cases, the [`position`][prezi-40-model-position] property may be used to define the position where a TextualBody should be rendered. The example shows a [`position`][prezi-40-model-position] that places the annotation at a specific coordinate within the Scene. The position is a [Specific Resource][prezi-40-model-SpecificResource] that requires a [`source`][prezi-40-model-source] and `selector`. -```jsonc -{ - "@context": "http://iiif.io/api/presentation/4/context.json", - "id": "https://example.org/iiif/manifest/commenting/manifest/3", - "type": "Manifest", - "label": { "en": ["1st Century Roman portrait bust with comment"] }, - "items": [ - { - "id": "https://example.org/iiif/scene/commenting/scene3", - "type": "Scene", - "items": [ - { - "id": "https://example.org/iiif/scene/commenting/scene3/painting-annotation-pages/1", - "type": "AnnotationPage", - "items": [ - { - "id": "https://example.org/iiif/scene/commenting/scene3/sculpture", - "type": "Annotation", - "motivation": ["painting"] , - "label": { - "en": ["A 1st century Roman portrait bust."] - }, - "body": - { - "id": "https://example.org/iiif/scene/commenting/models/portrait.gltf", - "type": "Model" - }, - "target": { - "id": "https://example.org/iiif/scene/commenting/scene3", - "type": "Scene" - } - } - ] - } - ] - } - ], - "annotations": [ - { - "id": "https://example.org/iiif/scene/commenting/scene3/commenting-annotation-pages/1", - "type": "AnnotationPage", - "items": [ - { - "id": "https://example.org/iiif/presentation/examples/commenting/anno/3", - "type": "Annotation", - "motivation": ["commenting"], - "body": - { - "id": "https://example.org/iiif/presentation/examples/commenting/anno/3/comment1", - "type": "TextualBody", - "language": "en", - "format": "text/plain", - "value": "This marble portrait exemplifies the veristic tradition that dominated Roman Republican portraiture and persisted into the early Imperial period.", - "position": { - "type": "SpecificResource", - "source": { - "id": "https://example.org/iiif/scene/commenting/scene3", - "type": "Scene" - }, - "selector": [ - { - "type": "PointSelector", - "x": 0.75, - "y": 1.5, - "z": 0.1 - } - ] - } - }, - "target": { - "id": "https://example.org/iiif/scene/commenting/scene3", - "type": "Scene" - } - } - ] - } - ] -} -``` +{% include code_example.html src="uc08_3d_annotation.json" %}